array-api-shape-check 0.1.2__py3-none-any.whl → 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- array_api_shape_check/__init__.py +1 -1
- array_api_shape_check/_main.py +29 -15
- {array_api_shape_check-0.1.2.dist-info → array_api_shape_check-0.1.3.dist-info}/METADATA +1 -1
- array_api_shape_check-0.1.3.dist-info/RECORD +8 -0
- array_api_shape_check-0.1.2.dist-info/RECORD +0 -8
- {array_api_shape_check-0.1.2.dist-info → array_api_shape_check-0.1.3.dist-info}/WHEEL +0 -0
- {array_api_shape_check-0.1.2.dist-info → array_api_shape_check-0.1.3.dist-info}/licenses/LICENSE +0 -0
- {array_api_shape_check-0.1.2.dist-info → array_api_shape_check-0.1.3.dist-info}/top_level.txt +0 -0
array_api_shape_check/_main.py
CHANGED
|
@@ -77,26 +77,38 @@ class SubscriptInfoFromShape:
|
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
class InconsistentNdimError(ValueError):
|
|
80
|
-
|
|
80
|
+
shapes: Sequence[int] | None
|
|
81
|
+
ndims: Sequence[int]
|
|
82
|
+
reason: str
|
|
81
83
|
|
|
82
84
|
|
|
83
85
|
class InconsistentNdimErrorMultipleSolutions(InconsistentNdimError):
|
|
84
|
-
def __init__(
|
|
86
|
+
def __init__(
|
|
87
|
+
self, ndims: Sequence[int], reason: str, shapes: Sequence[int] | None = None
|
|
88
|
+
) -> None:
|
|
89
|
+
self.ndims = ndims
|
|
90
|
+
self.reason = reason
|
|
91
|
+
self.shapes = shapes
|
|
85
92
|
super().__init__(
|
|
86
93
|
f"Inconsistent ndims: there are multiple possible solutions "
|
|
87
94
|
"to determine the number of dimensions "
|
|
88
|
-
f"for variable subscripts [{reason}]"
|
|
89
|
-
|
|
95
|
+
f"for variable subscripts [{reason}]"
|
|
96
|
+
f"\nndims: {ndims}" + (f"\nshapes: {shapes}" if shapes is not None else "")
|
|
90
97
|
)
|
|
91
98
|
|
|
92
99
|
|
|
93
100
|
class InconsistentNdimErrorNoSolutions(InconsistentNdimError):
|
|
94
|
-
def __init__(
|
|
101
|
+
def __init__(
|
|
102
|
+
self, ndims: Sequence[int], reason: str, shapes: Sequence[int] | None = None
|
|
103
|
+
) -> None:
|
|
104
|
+
self.ndims = ndims
|
|
105
|
+
self.reason = reason
|
|
106
|
+
self.shapes = shapes
|
|
95
107
|
super().__init__(
|
|
96
108
|
f"Inconsistent ndims: there are no solution "
|
|
97
109
|
f"to determine the number of dimensions "
|
|
98
|
-
f"for variable subscripts [{reason}]"
|
|
99
|
-
|
|
110
|
+
f"for variable subscripts [{reason}]"
|
|
111
|
+
f"\nndims: {ndims}" + (f"\nshapes: {shapes}" if shapes is not None else "")
|
|
100
112
|
)
|
|
101
113
|
|
|
102
114
|
|
|
@@ -258,9 +270,8 @@ def parse_variable_ndim(subscripts: str, ndims: Sequence[int], /) -> dict[str, i
|
|
|
258
270
|
subscript for subscript in info.unique.values() if subscript.is_variable
|
|
259
271
|
]
|
|
260
272
|
if len(info_variable_unique) > len(info.all):
|
|
261
|
-
raise InconsistentNdimErrorMultipleSolutions("number of variables")
|
|
273
|
+
raise InconsistentNdimErrorMultipleSolutions(ndims, "number of variables")
|
|
262
274
|
rhs = np.asarray(ndims, dtype=int)
|
|
263
|
-
del ndims
|
|
264
275
|
mat = np.zeros((len(info.all), len(info_variable_unique)), dtype=int)
|
|
265
276
|
for i, info_array in enumerate(info.all):
|
|
266
277
|
for subscript in info_array:
|
|
@@ -273,19 +284,19 @@ def parse_variable_ndim(subscripts: str, ndims: Sequence[int], /) -> dict[str, i
|
|
|
273
284
|
# solve overdetermined linear equations using least squares method
|
|
274
285
|
variable_dims, residuals, rank, _singular_values = np.linalg.lstsq(mat, rhs, rcond=None)
|
|
275
286
|
if rank != len(info_variable_unique):
|
|
276
|
-
raise InconsistentNdimErrorMultipleSolutions("rank")
|
|
287
|
+
raise InconsistentNdimErrorMultipleSolutions(ndims, "rank")
|
|
277
288
|
if residuals.size > 0 and not np.isclose(residuals[0], 0):
|
|
278
|
-
raise InconsistentNdimErrorNoSolutions("residuals")
|
|
289
|
+
raise InconsistentNdimErrorNoSolutions(ndims, "residuals")
|
|
279
290
|
variable_dims = np.round(variable_dims).astype(int)
|
|
280
291
|
if np.any(variable_dims < 0):
|
|
281
|
-
raise InconsistentNdimErrorNoSolutions("negative")
|
|
292
|
+
raise InconsistentNdimErrorNoSolutions(ndims, "negative")
|
|
282
293
|
return {
|
|
283
294
|
subscript.name: int(variable_dims[j]) for j, subscript in enumerate(info_variable_unique)
|
|
284
295
|
}
|
|
285
296
|
|
|
286
297
|
|
|
287
298
|
def _parse_shapes(
|
|
288
|
-
subscripts: str, /, *operands: Array | tuple[int, ...]
|
|
299
|
+
subscripts: str, /, *operands: Array | tuple[int | None, ...]
|
|
289
300
|
) -> tuple[tuple[SubscriptInfoFromShapeItemUnchecked, ...], ...]:
|
|
290
301
|
info = parse_subscripts(subscripts)
|
|
291
302
|
if len(info.all) != len(operands):
|
|
@@ -309,7 +320,10 @@ def _parse_shapes(
|
|
|
309
320
|
shapes += (shape,) # type: ignore
|
|
310
321
|
del operands
|
|
311
322
|
ndims = [len(shape) for shape in shapes]
|
|
312
|
-
|
|
323
|
+
try:
|
|
324
|
+
name_to_ndim = defaultdict(lambda: 1, parse_variable_ndim(subscripts, ndims))
|
|
325
|
+
except InconsistentNdimError as e:
|
|
326
|
+
raise type(e)(e.ndims, e.reason, shapes) from e
|
|
313
327
|
del subscripts, ndims
|
|
314
328
|
info_all: tuple[tuple[SubscriptInfoFromShapeItemUnchecked, ...], ...] = ()
|
|
315
329
|
for info_array, shape in zip(info.all, shapes, strict=False):
|
|
@@ -328,7 +342,7 @@ def _parse_shapes(
|
|
|
328
342
|
|
|
329
343
|
|
|
330
344
|
def check_shapes(
|
|
331
|
-
subscripts: str, /, *operands: Array | tuple[int, ...], names: str | None = None
|
|
345
|
+
subscripts: str, /, *operands: Array | tuple[int | None, ...], names: str | None = None
|
|
332
346
|
) -> SubscriptInfoFromShape:
|
|
333
347
|
"""
|
|
334
348
|
Parse variable subscript ndims by solving linear equations.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
array_api_shape_check/__init__.py,sha256=8i9ZV_x6HXtVd0g7N3ec190lQ1LUC2s93A9p-J3C9WI,940
|
|
2
|
+
array_api_shape_check/_main.py,sha256=LqwDK6OD9ldcUaXmmbG5aBXzOW0gEJuu1iAe9rs2BiY,16652
|
|
3
|
+
array_api_shape_check/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
array_api_shape_check-0.1.3.dist-info/licenses/LICENSE,sha256=Otwb96xcK4QBqXXVdBKpLZVnc4mJuFTa8rsMUEpphMM,1061
|
|
5
|
+
array_api_shape_check-0.1.3.dist-info/METADATA,sha256=of_gXs9JcFp-b0KQwa9Sbf8GIXPvChmU5VGfvBWyYOQ,6213
|
|
6
|
+
array_api_shape_check-0.1.3.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
7
|
+
array_api_shape_check-0.1.3.dist-info/top_level.txt,sha256=pirw2DeaWnDU_rSg3CZ1MsE-tJWEvndYSQG0illDMkI,22
|
|
8
|
+
array_api_shape_check-0.1.3.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
array_api_shape_check/__init__.py,sha256=peDt2aytKiIHNe9K5YRB8VJG15wxDIt0bKm7Z6Wu8s8,940
|
|
2
|
-
array_api_shape_check/_main.py,sha256=kqGml_xsXX1CtieBZDyyd_m-_kBqe-F-oj4PVpfKsek,16029
|
|
3
|
-
array_api_shape_check/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
array_api_shape_check-0.1.2.dist-info/licenses/LICENSE,sha256=Otwb96xcK4QBqXXVdBKpLZVnc4mJuFTa8rsMUEpphMM,1061
|
|
5
|
-
array_api_shape_check-0.1.2.dist-info/METADATA,sha256=bQKTAYo0XcoLyASUyChwsJ0RdNwlb-CBN5oHQrGkgV4,6213
|
|
6
|
-
array_api_shape_check-0.1.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
7
|
-
array_api_shape_check-0.1.2.dist-info/top_level.txt,sha256=pirw2DeaWnDU_rSg3CZ1MsE-tJWEvndYSQG0illDMkI,22
|
|
8
|
-
array_api_shape_check-0.1.2.dist-info/RECORD,,
|
|
File without changes
|
{array_api_shape_check-0.1.2.dist-info → array_api_shape_check-0.1.3.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{array_api_shape_check-0.1.2.dist-info → array_api_shape_check-0.1.3.dist-info}/top_level.txt
RENAMED
|
File without changes
|