Coverage for src\pqlattice\_utils.py: 21%
94 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-01-10 12:32 +0100
« prev ^ index » next coverage.py v7.11.0, created at 2026-01-10 12:32 +0100
1from fractions import Fraction
2from typing import Any
4import numpy as np
5from numpy.typing import ArrayLike
7from .typing import Array, Matrix, Vector, is_integer, is_Matrix, is_rational, is_Vector, validate_aliases
10def as_integer(obj: ArrayLike) -> Array:
11 """
12 Helper function that converts given obj to numpy's array of python's ints allowing arbitrary large elements
14 Parameters
15 ----------
16 obj : ArrayLike
17 object to be converted to numpy's array
19 Returns
20 -------
21 Array
22 numpy's array with dtype=object and elements converted to int
24 Examples
25 --------
26 >>> import pqlattice as pq
27 >>> pq.as_integer([3**100, 2**100, 5**50])
28 array([515377520732011331036461129765621272702107522001,
29 1267650600228229401496703205376,
30 88817841970012523233890533447265625], dtype=object)
31 """
32 arr = np.array(obj, dtype=object)
33 if arr.size == 0:
34 return arr
35 else:
36 return (np.vectorize(int)(arr.flat).reshape(arr.shape)).astype(object)
39def as_rational(obj: ArrayLike) -> Array:
40 """
41 Helper function that converts given obj to numpy's array of python's fractions.Fraction allowing arbitrary big rational elements
43 Parameters
44 ----------
45 obj : ArrayLike
46 object to be converted to numpy's array
48 Returns
49 -------
50 Array
51 numpy's array with dtype=object and elements converted to fractions.Fraction
53 Examples
54 --------
55 >>> import pqlattice as pq
56 >>> pq.as_rational([3**100, 2**100, 5**50])
57 array([Fraction(515377520732011331036461129765621272702107522001, 1),
58 Fraction(1267650600228229401496703205376, 1),
59 Fraction(88817841970012523233890533447265625, 1)], dtype=object)
60 """
61 arr = np.array(obj, dtype=object)
62 if arr.size == 0:
63 return arr
64 else:
65 return (np.vectorize(Fraction)(arr.flat).reshape(arr.shape)).astype(object)
68def zeros_vec(n: int) -> Vector:
69 return as_integer(np.zeros((n,)))
72def zeros_mat(rows: int, cols: int | None = None) -> Matrix:
73 if cols is None:
74 cols = rows
75 return as_integer(np.zeros((rows, cols)))
78@validate_aliases
79def show(a: Array, max_rows: int = 10, max_cols: int = 10, val_width: int = 15):
80 """
81 Helper function that prints the numpy's array in a human redable format
83 Parameters
84 ----------
85 a : Array
86 The array to print
87 max_rows : int, optional
88 Max number of rows to display before truncating, by default 10
89 max_cols : int, optional
90 Max number of columns to display before truncating, by default 10
91 val_width : int, optional
92 Max characters per cell, by default 15. If a string representation of element is longer, it is truncated e.g 1234...5678
94 Examples
95 --------
96 >>> import pqlattice as pq
97 >>> M = pq.random.distribution.Uniform(0, 2**50, seed=0).sample_matrix(7, 5)
98 >>> pq.show(M)
99 Matrix of integers with shape: 7 x 5
100 ====================================
101 [0] [1] [2] [3] [4]
102 [0] 867496826243021 91162487198805 109421..4040930 806253307773444 491889324856851
103 [1] 313616384600182 314680579360371 213540430176889 330931104930059 222394738660569
104 [2] 166055160201467 743539086037546 796665326308852 712012953150114 460445890320316
105 [3] 996855368208390 140240390954947 210028256050344 750154124310314 141827853726696
106 [4] 499232256057935 320872572303314 205400145011268 110177..2031755 678794279728913
107 [5] 655478801553847 281048514639229 749289460799082 457570956347073 647748016542327
108 [6] 206336435080453 713924001980837 545175556185458 414036094290124 74247901643189
109 """
111 def format_val(val: Any) -> str:
112 s = str(val)
113 if len(s) > val_width:
114 mid = (val_width - 2) // 2
115 remainder = (val_width - 2) % 2
116 return f"{s[:mid]}..{s[-(mid + remainder) :]}"
117 return s
119 element_type: str = f"{a.dtype}"
120 if is_integer(a):
121 element_type = "integers"
122 if is_rational(a):
123 element_type = "rationals"
125 info_header = f"numpy array of {element_type} with shape: {a.shape}"
127 is_v = False
128 if is_Matrix(a):
129 rows, cols = a.shape
130 info_header = f"Matrix of {element_type} with shape: {rows} x {cols}"
131 elif is_Vector(a):
132 dim = a.shape[0]
133 info_header = f"Vector of {element_type} with shape: {dim}"
134 is_v = True
135 rows, cols = 1, dim
136 else:
137 print(info_header)
138 print("=" * len(info_header))
139 print(f"{a}")
140 return
142 print(info_header)
143 print("=" * len(info_header))
145 ellipsis_col_idx: int | None = None
146 ellipsis_row_idx: int | None = None
147 if rows <= max_rows:
148 row_indices = list(range(rows))
149 show_row_ellipsis = False
150 else:
151 # Top half and bottom half
152 r_cut = max_rows // 2
153 row_indices = list(range(r_cut)) + list(range(rows - r_cut, rows))
154 show_row_ellipsis = True
155 ellipsis_row_idx = r_cut
157 if cols <= max_cols:
158 col_indices = list(range(cols))
159 show_col_ellipsis = False
160 else:
161 c_cut = max_cols // 2
162 col_indices = list(range(c_cut)) + list(range(cols - c_cut, cols))
163 show_col_ellipsis = True
164 ellipsis_col_idx = c_cut
166 header = [""]
167 for i, c_idx in enumerate(col_indices):
168 if show_col_ellipsis and i == ellipsis_col_idx:
169 header.append("...")
170 header.append(f"[{c_idx}]")
172 table_data = [header]
174 for i, r_idx in enumerate(row_indices):
175 if show_row_ellipsis and i == ellipsis_row_idx:
176 ellipsis_row = ["..."] + ["..."] * (len(header) - 1)
177 table_data.append(ellipsis_row)
179 row_str = [f"[{r_idx}]"]
181 for j, c_idx in enumerate(col_indices):
182 if show_col_ellipsis and j == ellipsis_col_idx:
183 row_str.append("...")
185 val = a[c_idx] if is_v else a[r_idx, c_idx]
186 row_str.append(format_val(val))
188 table_data.append(row_str)
190 num_display_cols = len(table_data[0])
191 col_widths = [0] * num_display_cols
193 for row in table_data:
194 for idx, cell in enumerate(row):
195 col_widths[idx] = max(col_widths[idx], len(cell))
197 for row in table_data:
198 formatted_row: list[str] = []
199 for idx, cell in enumerate(row):
200 formatted_row.append(cell.rjust(col_widths[idx]))
201 print(" ".join(formatted_row))