python-graphblas 2023.12.0__tar.gz → 2025.2.0a0__tar.gz
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.
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/PKG-INFO +58 -19
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/README.md +40 -1
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/agg/__init__.py +2 -1
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/binary/numpy.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/automethods.py +1 -5
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/base.py +1 -1
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/dtypes.py +16 -6
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/expr.py +4 -4
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/formatting.py +1 -1
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/infix.py +1 -2
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/matrix.py +51 -106
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/operator/base.py +3 -3
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/operator/binary.py +2 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/operator/indexunary.py +2 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/operator/monoid.py +2 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/operator/select.py +2 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/operator/semiring.py +2 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/operator/unary.py +2 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/operator/utils.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/scalar.py +12 -1
- python_graphblas-2025.2.0a0/graphblas/core/ss/__init__.py +5 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/binary.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/config.py +1 -1
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/descriptor.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/indexunary.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/matrix.py +90 -64
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/select.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/unary.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/vector.py +61 -30
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/utils.py +18 -6
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/vector.py +31 -72
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/exceptions.py +11 -3
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/io/__init__.py +0 -1
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/io/_awkward.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/io/_matrixmarket.py +2 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/io/_networkx.py +6 -2
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/io/_scipy.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/io/_sparse.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/monoid/numpy.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/select/__init__.py +4 -11
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/semiring/numpy.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/ss/_core.py +2 -4
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/conftest.py +18 -6
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_descriptor.py +1 -2
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_dtype.py +5 -1
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_infix.py +1 -1
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_io.py +1 -12
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_matrix.py +13 -21
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_numpyops.py +10 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_op.py +0 -2
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_scalar.py +5 -1
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_ssjit.py +49 -3
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_vector.py +16 -14
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/unary/numpy.py +1 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/viz.py +2 -0
- python_graphblas-2025.2.0a0/pyproject.toml +499 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/python_graphblas.egg-info/PKG-INFO +58 -19
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/python_graphblas.egg-info/SOURCES.txt +0 -2
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/python_graphblas.egg-info/requires.txt +15 -13
- python-graphblas-2023.12.0/graphblas/core/agg.py +0 -17
- python-graphblas-2023.12.0/graphblas/core/ss/__init__.py +0 -3
- python-graphblas-2023.12.0/graphblas/io/_numpy.py +0 -104
- python-graphblas-2023.12.0/pyproject.toml +0 -479
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/LICENSE +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/MANIFEST.in +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/conftest.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/agg/ss.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/binary/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/binary/ss.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/descriptor.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/infixmethods.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/mask.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/operator/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/operator/agg.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/recorder.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/slice.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/context.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/dtypes.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/core/ss/prefix_scan.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/dtypes/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/dtypes/ss.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/graphblas.yaml +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/indexunary/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/indexunary/ss.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/monoid/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/monoid/ss.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/op/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/op/numpy.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/op/ss.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/select/ss.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/semiring/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/semiring/ss.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/ss/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/pickle1-vanilla.pkl +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/pickle1.pkl +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/pickle2-vanilla.pkl +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/pickle2.pkl +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/pickle3-vanilla.pkl +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/pickle3.pkl +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_auto_init.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_core.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_external_init.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_formatting.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_mask.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_operator_types.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_pickle.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_prefix_scan.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_recorder.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_resolving.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/tests/test_ss_utils.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/unary/__init__.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/graphblas/unary/ss.py +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/python_graphblas.egg-info/dependency_links.txt +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/python_graphblas.egg-info/top_level.txt +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/setup.cfg +0 -0
- {python-graphblas-2023.12.0 → python_graphblas-2025.2.0a0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: python-graphblas
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2025.2.0a0
|
|
4
4
|
Summary: Python library for GraphBLAS: high-performance sparse linear algebra for scalable graph analytics
|
|
5
5
|
Author: Jim Kitchen, Python-graphblas contributors
|
|
6
6
|
Author-email: Erik Welch <erik.n.welch@gmail.com>
|
|
@@ -219,10 +219,10 @@ Classifier: Operating System :: POSIX :: Linux
|
|
|
219
219
|
Classifier: Operating System :: Microsoft :: Windows
|
|
220
220
|
Classifier: Programming Language :: Python
|
|
221
221
|
Classifier: Programming Language :: Python :: 3
|
|
222
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
223
222
|
Classifier: Programming Language :: Python :: 3.10
|
|
224
223
|
Classifier: Programming Language :: Python :: 3.11
|
|
225
224
|
Classifier: Programming Language :: Python :: 3.12
|
|
225
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
226
226
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
227
227
|
Classifier: Intended Audience :: Developers
|
|
228
228
|
Classifier: Intended Audience :: Other Audience
|
|
@@ -231,22 +231,22 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
231
231
|
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
232
232
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
233
233
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
234
|
-
Requires-Python: >=3.
|
|
234
|
+
Requires-Python: >=3.10
|
|
235
235
|
Description-Content-Type: text/markdown
|
|
236
236
|
License-File: LICENSE
|
|
237
|
-
Requires-Dist: numpy>=1.
|
|
237
|
+
Requires-Dist: numpy>=1.23
|
|
238
238
|
Requires-Dist: donfig>=0.6
|
|
239
239
|
Requires-Dist: pyyaml>=5.4
|
|
240
|
-
Requires-Dist: suitesparse-graphblas<
|
|
241
|
-
Requires-Dist: numba>=0.55; python_version < "3.
|
|
240
|
+
Requires-Dist: suitesparse-graphblas<10,>=7.4.0.0
|
|
241
|
+
Requires-Dist: numba>=0.55; python_version < "3.14"
|
|
242
242
|
Provides-Extra: suitesparse
|
|
243
|
-
Requires-Dist: suitesparse-graphblas<
|
|
243
|
+
Requires-Dist: suitesparse-graphblas<10,>=7.4.0.0; extra == "suitesparse"
|
|
244
244
|
Provides-Extra: networkx
|
|
245
245
|
Requires-Dist: networkx>=2.8; extra == "networkx"
|
|
246
246
|
Provides-Extra: numba
|
|
247
247
|
Requires-Dist: numba>=0.55; extra == "numba"
|
|
248
248
|
Provides-Extra: pandas
|
|
249
|
-
Requires-Dist: pandas>=1.
|
|
249
|
+
Requires-Dist: pandas>=1.5; extra == "pandas"
|
|
250
250
|
Provides-Extra: scipy
|
|
251
251
|
Requires-Dist: scipy>=1.9; extra == "scipy"
|
|
252
252
|
Provides-Extra: suitesparse-udf
|
|
@@ -255,17 +255,17 @@ Provides-Extra: repr
|
|
|
255
255
|
Requires-Dist: python-graphblas[pandas]; extra == "repr"
|
|
256
256
|
Provides-Extra: io
|
|
257
257
|
Requires-Dist: python-graphblas[networkx,scipy]; extra == "io"
|
|
258
|
-
Requires-Dist: python-graphblas[numba]; python_version < "3.
|
|
259
|
-
Requires-Dist: awkward>=
|
|
260
|
-
Requires-Dist: sparse>=0.
|
|
261
|
-
Requires-Dist: fast-matrix-market>=1.4.5; extra == "io"
|
|
258
|
+
Requires-Dist: python-graphblas[numba]; python_version < "3.14" and extra == "io"
|
|
259
|
+
Requires-Dist: awkward>=2.0; extra == "io"
|
|
260
|
+
Requires-Dist: sparse>=0.14; python_version < "3.13" and extra == "io"
|
|
261
|
+
Requires-Dist: fast-matrix-market>=1.4.5; python_version < "3.13" and extra == "io"
|
|
262
262
|
Provides-Extra: viz
|
|
263
263
|
Requires-Dist: python-graphblas[networkx,scipy]; extra == "viz"
|
|
264
|
-
Requires-Dist: matplotlib>=3.
|
|
264
|
+
Requires-Dist: matplotlib>=3.6; extra == "viz"
|
|
265
265
|
Provides-Extra: datashade
|
|
266
266
|
Requires-Dist: python-graphblas[numba,pandas,scipy]; extra == "datashade"
|
|
267
|
-
Requires-Dist: datashader>=0.
|
|
268
|
-
Requires-Dist: hvplot>=0.
|
|
267
|
+
Requires-Dist: datashader>=0.14; extra == "datashade"
|
|
268
|
+
Requires-Dist: hvplot>=0.8; extra == "datashade"
|
|
269
269
|
Provides-Extra: test
|
|
270
270
|
Requires-Dist: python-graphblas[pandas,scipy,suitesparse]; extra == "test"
|
|
271
271
|
Requires-Dist: packaging>=21; extra == "test"
|
|
@@ -273,10 +273,10 @@ Requires-Dist: pytest>=6.2; extra == "test"
|
|
|
273
273
|
Requires-Dist: tomli>=1; extra == "test"
|
|
274
274
|
Provides-Extra: default
|
|
275
275
|
Requires-Dist: python-graphblas[pandas,scipy,suitesparse]; extra == "default"
|
|
276
|
-
Requires-Dist: python-graphblas[numba]; python_version < "3.
|
|
276
|
+
Requires-Dist: python-graphblas[numba]; python_version < "3.14" and extra == "default"
|
|
277
277
|
Provides-Extra: all
|
|
278
278
|
Requires-Dist: python-graphblas[default,io,test,viz]; extra == "all"
|
|
279
|
-
Requires-Dist: python-graphblas[datashade]; python_version < "3.
|
|
279
|
+
Requires-Dist: python-graphblas[datashade]; python_version < "3.14" and extra == "all"
|
|
280
280
|
|
|
281
281
|

|
|
282
282
|
|
|
@@ -315,14 +315,19 @@ For algorithms, see
|
|
|
315
315
|
</p>
|
|
316
316
|
|
|
317
317
|
## Install
|
|
318
|
+
|
|
318
319
|
Install the latest version of Python-graphblas via conda:
|
|
320
|
+
|
|
319
321
|
```
|
|
320
322
|
$ conda install -c conda-forge python-graphblas
|
|
321
323
|
```
|
|
324
|
+
|
|
322
325
|
or pip:
|
|
326
|
+
|
|
323
327
|
```
|
|
324
|
-
$ pip install python-graphblas[default]
|
|
328
|
+
$ pip install 'python-graphblas[default]'
|
|
325
329
|
```
|
|
330
|
+
|
|
326
331
|
This will also install the [SuiteSparse:GraphBLAS](https://github.com/DrTimothyAldenDavis/GraphBLAS) compiled C library.
|
|
327
332
|
We currently support the [GraphBLAS C API 2.0 specification](https://graphblas.org/docs/GraphBLAS_API_C_v2.0.0.pdf).
|
|
328
333
|
|
|
@@ -337,6 +342,7 @@ The following are not required by python-graphblas, but may be needed for certai
|
|
|
337
342
|
- `fast-matrix-market` - for faster read/write of Matrix Market files with `gb.io.mmread` and `gb.io.mmwrite`.
|
|
338
343
|
|
|
339
344
|
## Description
|
|
345
|
+
|
|
340
346
|
Currently works with [SuiteSparse:GraphBLAS](https://github.com/DrTimothyAldenDavis/GraphBLAS), but the goal is to make it work with all implementations of the GraphBLAS spec.
|
|
341
347
|
|
|
342
348
|
The approach taken with this library is to follow the C-API 2.0 specification as closely as possible while making improvements
|
|
@@ -350,10 +356,12 @@ with how Python handles assignment, so instead we (ab)use the left-shift `<<` no
|
|
|
350
356
|
assignment. This opens up all kinds of nice possibilities.
|
|
351
357
|
|
|
352
358
|
This is an example of how the mapping works:
|
|
359
|
+
|
|
353
360
|
```C
|
|
354
361
|
// C call
|
|
355
362
|
GrB_Matrix_mxm(M, mask, GrB_PLUS_INT64, GrB_MIN_PLUS_INT64, A, B, NULL)
|
|
356
363
|
```
|
|
364
|
+
|
|
357
365
|
```python
|
|
358
366
|
# Python call
|
|
359
367
|
M(mask.V, accum=binary.plus) << A.mxm(B, semiring.min_plus)
|
|
@@ -371,10 +379,12 @@ is a much better approach, even if it doesn't feel very Pythonic.
|
|
|
371
379
|
Descriptor flags are set on the appropriate elements to keep logic close to what it affects. Here is the same call
|
|
372
380
|
with descriptor bits set. `ttcsr` indicates transpose the first and second matrices, complement the structure of the mask,
|
|
373
381
|
and do a replacement on the output.
|
|
382
|
+
|
|
374
383
|
```C
|
|
375
384
|
// C call
|
|
376
385
|
GrB_Matrix_mxm(M, mask, GrB_PLUS_INT64, GrB_MIN_PLUS_INT64, A, B, desc.ttcsr)
|
|
377
386
|
```
|
|
387
|
+
|
|
378
388
|
```python
|
|
379
389
|
# Python call
|
|
380
390
|
M(~mask.S, accum=binary.plus, replace=True) << A.T.mxm(B.T, semiring.min_plus)
|
|
@@ -384,16 +394,20 @@ The objects receiving the flag operations (A.T, ~mask, etc) are also delayed obj
|
|
|
384
394
|
do no computation, allowing the correct descriptor bits to be set in a single GraphBLAS call.
|
|
385
395
|
|
|
386
396
|
**If no mask or accumulator is used, the call looks like this**:
|
|
397
|
+
|
|
387
398
|
```python
|
|
388
399
|
M << A.mxm(B, semiring.min_plus)
|
|
389
400
|
```
|
|
401
|
+
|
|
390
402
|
The use of `<<` to indicate updating is actually just syntactic sugar for a real `.update()` method. The above
|
|
391
403
|
expression could be written as:
|
|
404
|
+
|
|
392
405
|
```python
|
|
393
406
|
M.update(A.mxm(B, semiring.min_plus))
|
|
394
407
|
```
|
|
395
408
|
|
|
396
409
|
## Operations
|
|
410
|
+
|
|
397
411
|
```python
|
|
398
412
|
M(mask, accum) << A.mxm(B, semiring) # mxm
|
|
399
413
|
w(mask, accum) << A.mxv(v, semiring) # mxv
|
|
@@ -403,14 +417,18 @@ M(mask, accum) << A.ewise_mult(B, binaryop) # eWiseMult
|
|
|
403
417
|
M(mask, accum) << A.kronecker(B, binaryop) # kronecker
|
|
404
418
|
M(mask, accum) << A.T # transpose
|
|
405
419
|
```
|
|
420
|
+
|
|
406
421
|
## Extract
|
|
422
|
+
|
|
407
423
|
```python
|
|
408
424
|
M(mask, accum) << A[rows, cols] # rows and cols are a list or a slice
|
|
409
425
|
w(mask, accum) << A[rows, col_index] # extract column
|
|
410
426
|
w(mask, accum) << A[row_index, cols] # extract row
|
|
411
427
|
s = A[row_index, col_index].value # extract single element
|
|
412
428
|
```
|
|
429
|
+
|
|
413
430
|
## Assign
|
|
431
|
+
|
|
414
432
|
```python
|
|
415
433
|
M(mask, accum)[rows, cols] << A # rows and cols are a list or a slice
|
|
416
434
|
M(mask, accum)[rows, col_index] << v # assign column
|
|
@@ -420,31 +438,42 @@ M[row_index, col_index] << s # assign scalar to single element
|
|
|
420
438
|
# (mask and accum not allowed)
|
|
421
439
|
del M[row_index, col_index] # remove single element
|
|
422
440
|
```
|
|
441
|
+
|
|
423
442
|
## Apply
|
|
443
|
+
|
|
424
444
|
```python
|
|
425
445
|
M(mask, accum) << A.apply(unaryop)
|
|
426
446
|
M(mask, accum) << A.apply(binaryop, left=s) # bind-first
|
|
427
447
|
M(mask, accum) << A.apply(binaryop, right=s) # bind-second
|
|
428
448
|
```
|
|
449
|
+
|
|
429
450
|
## Reduce
|
|
451
|
+
|
|
430
452
|
```python
|
|
431
453
|
v(mask, accum) << A.reduce_rowwise(op) # reduce row-wise
|
|
432
454
|
v(mask, accum) << A.reduce_columnwise(op) # reduce column-wise
|
|
433
455
|
s(accum) << A.reduce_scalar(op)
|
|
434
456
|
s(accum) << v.reduce(op)
|
|
435
457
|
```
|
|
458
|
+
|
|
436
459
|
## Creating new Vectors / Matrices
|
|
460
|
+
|
|
437
461
|
```python
|
|
438
462
|
A = Matrix.new(dtype, num_rows, num_cols) # new_type
|
|
439
463
|
B = A.dup() # dup
|
|
440
464
|
A = Matrix.from_coo([row_indices], [col_indices], [values]) # build
|
|
441
465
|
```
|
|
466
|
+
|
|
442
467
|
## New from delayed
|
|
468
|
+
|
|
443
469
|
Delayed objects can be used to create a new object using `.new()` method
|
|
470
|
+
|
|
444
471
|
```python
|
|
445
472
|
C = A.mxm(B, semiring).new()
|
|
446
473
|
```
|
|
474
|
+
|
|
447
475
|
## Properties
|
|
476
|
+
|
|
448
477
|
```python
|
|
449
478
|
size = v.size # size
|
|
450
479
|
nrows = M.nrows # nrows
|
|
@@ -452,10 +481,13 @@ ncols = M.ncols # ncols
|
|
|
452
481
|
nvals = M.nvals # nvals
|
|
453
482
|
rindices, cindices, vals = M.to_coo() # extractTuples
|
|
454
483
|
```
|
|
484
|
+
|
|
455
485
|
## Initialization
|
|
486
|
+
|
|
456
487
|
There is a mechanism to initialize `graphblas` with a context prior to use. This allows for setting the backend to
|
|
457
488
|
use as well as the blocking/non-blocking mode. If the context is not initialized, a default initialization will
|
|
458
489
|
be performed automatically.
|
|
490
|
+
|
|
459
491
|
```python
|
|
460
492
|
import graphblas as gb
|
|
461
493
|
|
|
@@ -466,10 +498,13 @@ gb.init("suitesparse", blocking=True)
|
|
|
466
498
|
from graphblas import binary, semiring
|
|
467
499
|
from graphblas import Matrix, Vector, Scalar
|
|
468
500
|
```
|
|
501
|
+
|
|
469
502
|
## Performant User Defined Functions
|
|
503
|
+
|
|
470
504
|
Python-graphblas requires `numba` which enables compiling user-defined Python functions to native C for use in GraphBLAS.
|
|
471
505
|
|
|
472
506
|
Example customized UnaryOp:
|
|
507
|
+
|
|
473
508
|
```python
|
|
474
509
|
from graphblas import unary
|
|
475
510
|
|
|
@@ -484,9 +519,11 @@ v = Vector.from_coo([0, 1, 3], [1, 2, 3])
|
|
|
484
519
|
w = v.apply(unary.force_odd).new()
|
|
485
520
|
w # indexes=[0, 1, 3], values=[1, 3, 3]
|
|
486
521
|
```
|
|
522
|
+
|
|
487
523
|
Similar methods exist for BinaryOp, Monoid, and Semiring.
|
|
488
524
|
|
|
489
525
|
## Relation to other network analysis libraries
|
|
526
|
+
|
|
490
527
|
Python-graphblas aims to provide an efficient and consistent expression
|
|
491
528
|
of graph operations using linear algebra. This allows the development of
|
|
492
529
|
high-performance implementations of existing and new graph algorithms
|
|
@@ -503,7 +540,9 @@ other libraries, `graphblas.io` contains multiple connectors, see the
|
|
|
503
540
|
following section.
|
|
504
541
|
|
|
505
542
|
## Import/Export connectors to the Python ecosystem
|
|
543
|
+
|
|
506
544
|
`graphblas.io` contains functions for converting to and from:
|
|
545
|
+
|
|
507
546
|
```python
|
|
508
547
|
import graphblas as gb
|
|
509
548
|
|
|
@@ -35,14 +35,19 @@ For algorithms, see
|
|
|
35
35
|
</p>
|
|
36
36
|
|
|
37
37
|
## Install
|
|
38
|
+
|
|
38
39
|
Install the latest version of Python-graphblas via conda:
|
|
40
|
+
|
|
39
41
|
```
|
|
40
42
|
$ conda install -c conda-forge python-graphblas
|
|
41
43
|
```
|
|
44
|
+
|
|
42
45
|
or pip:
|
|
46
|
+
|
|
43
47
|
```
|
|
44
|
-
$ pip install python-graphblas[default]
|
|
48
|
+
$ pip install 'python-graphblas[default]'
|
|
45
49
|
```
|
|
50
|
+
|
|
46
51
|
This will also install the [SuiteSparse:GraphBLAS](https://github.com/DrTimothyAldenDavis/GraphBLAS) compiled C library.
|
|
47
52
|
We currently support the [GraphBLAS C API 2.0 specification](https://graphblas.org/docs/GraphBLAS_API_C_v2.0.0.pdf).
|
|
48
53
|
|
|
@@ -57,6 +62,7 @@ The following are not required by python-graphblas, but may be needed for certai
|
|
|
57
62
|
- `fast-matrix-market` - for faster read/write of Matrix Market files with `gb.io.mmread` and `gb.io.mmwrite`.
|
|
58
63
|
|
|
59
64
|
## Description
|
|
65
|
+
|
|
60
66
|
Currently works with [SuiteSparse:GraphBLAS](https://github.com/DrTimothyAldenDavis/GraphBLAS), but the goal is to make it work with all implementations of the GraphBLAS spec.
|
|
61
67
|
|
|
62
68
|
The approach taken with this library is to follow the C-API 2.0 specification as closely as possible while making improvements
|
|
@@ -70,10 +76,12 @@ with how Python handles assignment, so instead we (ab)use the left-shift `<<` no
|
|
|
70
76
|
assignment. This opens up all kinds of nice possibilities.
|
|
71
77
|
|
|
72
78
|
This is an example of how the mapping works:
|
|
79
|
+
|
|
73
80
|
```C
|
|
74
81
|
// C call
|
|
75
82
|
GrB_Matrix_mxm(M, mask, GrB_PLUS_INT64, GrB_MIN_PLUS_INT64, A, B, NULL)
|
|
76
83
|
```
|
|
84
|
+
|
|
77
85
|
```python
|
|
78
86
|
# Python call
|
|
79
87
|
M(mask.V, accum=binary.plus) << A.mxm(B, semiring.min_plus)
|
|
@@ -91,10 +99,12 @@ is a much better approach, even if it doesn't feel very Pythonic.
|
|
|
91
99
|
Descriptor flags are set on the appropriate elements to keep logic close to what it affects. Here is the same call
|
|
92
100
|
with descriptor bits set. `ttcsr` indicates transpose the first and second matrices, complement the structure of the mask,
|
|
93
101
|
and do a replacement on the output.
|
|
102
|
+
|
|
94
103
|
```C
|
|
95
104
|
// C call
|
|
96
105
|
GrB_Matrix_mxm(M, mask, GrB_PLUS_INT64, GrB_MIN_PLUS_INT64, A, B, desc.ttcsr)
|
|
97
106
|
```
|
|
107
|
+
|
|
98
108
|
```python
|
|
99
109
|
# Python call
|
|
100
110
|
M(~mask.S, accum=binary.plus, replace=True) << A.T.mxm(B.T, semiring.min_plus)
|
|
@@ -104,16 +114,20 @@ The objects receiving the flag operations (A.T, ~mask, etc) are also delayed obj
|
|
|
104
114
|
do no computation, allowing the correct descriptor bits to be set in a single GraphBLAS call.
|
|
105
115
|
|
|
106
116
|
**If no mask or accumulator is used, the call looks like this**:
|
|
117
|
+
|
|
107
118
|
```python
|
|
108
119
|
M << A.mxm(B, semiring.min_plus)
|
|
109
120
|
```
|
|
121
|
+
|
|
110
122
|
The use of `<<` to indicate updating is actually just syntactic sugar for a real `.update()` method. The above
|
|
111
123
|
expression could be written as:
|
|
124
|
+
|
|
112
125
|
```python
|
|
113
126
|
M.update(A.mxm(B, semiring.min_plus))
|
|
114
127
|
```
|
|
115
128
|
|
|
116
129
|
## Operations
|
|
130
|
+
|
|
117
131
|
```python
|
|
118
132
|
M(mask, accum) << A.mxm(B, semiring) # mxm
|
|
119
133
|
w(mask, accum) << A.mxv(v, semiring) # mxv
|
|
@@ -123,14 +137,18 @@ M(mask, accum) << A.ewise_mult(B, binaryop) # eWiseMult
|
|
|
123
137
|
M(mask, accum) << A.kronecker(B, binaryop) # kronecker
|
|
124
138
|
M(mask, accum) << A.T # transpose
|
|
125
139
|
```
|
|
140
|
+
|
|
126
141
|
## Extract
|
|
142
|
+
|
|
127
143
|
```python
|
|
128
144
|
M(mask, accum) << A[rows, cols] # rows and cols are a list or a slice
|
|
129
145
|
w(mask, accum) << A[rows, col_index] # extract column
|
|
130
146
|
w(mask, accum) << A[row_index, cols] # extract row
|
|
131
147
|
s = A[row_index, col_index].value # extract single element
|
|
132
148
|
```
|
|
149
|
+
|
|
133
150
|
## Assign
|
|
151
|
+
|
|
134
152
|
```python
|
|
135
153
|
M(mask, accum)[rows, cols] << A # rows and cols are a list or a slice
|
|
136
154
|
M(mask, accum)[rows, col_index] << v # assign column
|
|
@@ -140,31 +158,42 @@ M[row_index, col_index] << s # assign scalar to single element
|
|
|
140
158
|
# (mask and accum not allowed)
|
|
141
159
|
del M[row_index, col_index] # remove single element
|
|
142
160
|
```
|
|
161
|
+
|
|
143
162
|
## Apply
|
|
163
|
+
|
|
144
164
|
```python
|
|
145
165
|
M(mask, accum) << A.apply(unaryop)
|
|
146
166
|
M(mask, accum) << A.apply(binaryop, left=s) # bind-first
|
|
147
167
|
M(mask, accum) << A.apply(binaryop, right=s) # bind-second
|
|
148
168
|
```
|
|
169
|
+
|
|
149
170
|
## Reduce
|
|
171
|
+
|
|
150
172
|
```python
|
|
151
173
|
v(mask, accum) << A.reduce_rowwise(op) # reduce row-wise
|
|
152
174
|
v(mask, accum) << A.reduce_columnwise(op) # reduce column-wise
|
|
153
175
|
s(accum) << A.reduce_scalar(op)
|
|
154
176
|
s(accum) << v.reduce(op)
|
|
155
177
|
```
|
|
178
|
+
|
|
156
179
|
## Creating new Vectors / Matrices
|
|
180
|
+
|
|
157
181
|
```python
|
|
158
182
|
A = Matrix.new(dtype, num_rows, num_cols) # new_type
|
|
159
183
|
B = A.dup() # dup
|
|
160
184
|
A = Matrix.from_coo([row_indices], [col_indices], [values]) # build
|
|
161
185
|
```
|
|
186
|
+
|
|
162
187
|
## New from delayed
|
|
188
|
+
|
|
163
189
|
Delayed objects can be used to create a new object using `.new()` method
|
|
190
|
+
|
|
164
191
|
```python
|
|
165
192
|
C = A.mxm(B, semiring).new()
|
|
166
193
|
```
|
|
194
|
+
|
|
167
195
|
## Properties
|
|
196
|
+
|
|
168
197
|
```python
|
|
169
198
|
size = v.size # size
|
|
170
199
|
nrows = M.nrows # nrows
|
|
@@ -172,10 +201,13 @@ ncols = M.ncols # ncols
|
|
|
172
201
|
nvals = M.nvals # nvals
|
|
173
202
|
rindices, cindices, vals = M.to_coo() # extractTuples
|
|
174
203
|
```
|
|
204
|
+
|
|
175
205
|
## Initialization
|
|
206
|
+
|
|
176
207
|
There is a mechanism to initialize `graphblas` with a context prior to use. This allows for setting the backend to
|
|
177
208
|
use as well as the blocking/non-blocking mode. If the context is not initialized, a default initialization will
|
|
178
209
|
be performed automatically.
|
|
210
|
+
|
|
179
211
|
```python
|
|
180
212
|
import graphblas as gb
|
|
181
213
|
|
|
@@ -186,10 +218,13 @@ gb.init("suitesparse", blocking=True)
|
|
|
186
218
|
from graphblas import binary, semiring
|
|
187
219
|
from graphblas import Matrix, Vector, Scalar
|
|
188
220
|
```
|
|
221
|
+
|
|
189
222
|
## Performant User Defined Functions
|
|
223
|
+
|
|
190
224
|
Python-graphblas requires `numba` which enables compiling user-defined Python functions to native C for use in GraphBLAS.
|
|
191
225
|
|
|
192
226
|
Example customized UnaryOp:
|
|
227
|
+
|
|
193
228
|
```python
|
|
194
229
|
from graphblas import unary
|
|
195
230
|
|
|
@@ -204,9 +239,11 @@ v = Vector.from_coo([0, 1, 3], [1, 2, 3])
|
|
|
204
239
|
w = v.apply(unary.force_odd).new()
|
|
205
240
|
w # indexes=[0, 1, 3], values=[1, 3, 3]
|
|
206
241
|
```
|
|
242
|
+
|
|
207
243
|
Similar methods exist for BinaryOp, Monoid, and Semiring.
|
|
208
244
|
|
|
209
245
|
## Relation to other network analysis libraries
|
|
246
|
+
|
|
210
247
|
Python-graphblas aims to provide an efficient and consistent expression
|
|
211
248
|
of graph operations using linear algebra. This allows the development of
|
|
212
249
|
high-performance implementations of existing and new graph algorithms
|
|
@@ -223,7 +260,9 @@ other libraries, `graphblas.io` contains multiple connectors, see the
|
|
|
223
260
|
following section.
|
|
224
261
|
|
|
225
262
|
## Import/Export connectors to the Python ecosystem
|
|
263
|
+
|
|
226
264
|
`graphblas.io` contains functions for converting to and from:
|
|
265
|
+
|
|
227
266
|
```python
|
|
228
267
|
import graphblas as gb
|
|
229
268
|
|
|
@@ -73,7 +73,8 @@ Custom recipes (specific to SuiteSparse:GraphBLAS):
|
|
|
73
73
|
# - bxnor monoid: even bits
|
|
74
74
|
# - bnor monoid: odd bits
|
|
75
75
|
"""
|
|
76
|
-
|
|
76
|
+
|
|
77
|
+
# All items are dynamically added by classes in core/operator/agg.py
|
|
77
78
|
# This module acts as a container of Aggregator instances
|
|
78
79
|
_deprecated = {}
|
|
79
80
|
|
|
@@ -7,6 +7,7 @@ To automatically create the functions, run:
|
|
|
7
7
|
$ python -m graphblas.core.automethods
|
|
8
8
|
|
|
9
9
|
"""
|
|
10
|
+
|
|
10
11
|
from .. import config
|
|
11
12
|
|
|
12
13
|
|
|
@@ -281,10 +282,6 @@ def to_edgelist(self):
|
|
|
281
282
|
return self._get_value("to_edgelist")
|
|
282
283
|
|
|
283
284
|
|
|
284
|
-
def to_values(self):
|
|
285
|
-
return self._get_value("to_values")
|
|
286
|
-
|
|
287
|
-
|
|
288
285
|
def value(self):
|
|
289
286
|
return self._get_value("value")
|
|
290
287
|
|
|
@@ -398,7 +395,6 @@ def _main():
|
|
|
398
395
|
"ss",
|
|
399
396
|
"to_coo",
|
|
400
397
|
"to_dense",
|
|
401
|
-
"to_values",
|
|
402
398
|
}
|
|
403
399
|
vector = {
|
|
404
400
|
"_as_matrix",
|
|
@@ -513,7 +513,7 @@ class BaseType:
|
|
|
513
513
|
_expect_op = _expect_op
|
|
514
514
|
|
|
515
515
|
# Don't let non-scalars be coerced to numpy arrays
|
|
516
|
-
def __array__(self, dtype=None):
|
|
516
|
+
def __array__(self, dtype=None, *, copy=None):
|
|
517
517
|
raise TypeError(
|
|
518
518
|
f"{type(self).__name__} can't be directly converted to a numpy array; "
|
|
519
519
|
f"perhaps use `{self.name}.to_coo()` method instead."
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import warnings
|
|
2
|
+
from ast import literal_eval
|
|
2
3
|
|
|
3
4
|
import numpy as np
|
|
4
5
|
from numpy import promote_types, result_type
|
|
@@ -97,7 +98,7 @@ def register_anonymous(dtype, name=None):
|
|
|
97
98
|
# Allow dtypes such as `"INT64[3, 4]"` for convenience
|
|
98
99
|
base_dtype, shape = dtype.split("[", 1)
|
|
99
100
|
base_dtype = lookup_dtype(base_dtype)
|
|
100
|
-
shape =
|
|
101
|
+
shape = literal_eval(f"[{shape}")
|
|
101
102
|
dtype = np.dtype((base_dtype.np_type, shape))
|
|
102
103
|
else:
|
|
103
104
|
raise
|
|
@@ -115,7 +116,17 @@ def register_anonymous(dtype, name=None):
|
|
|
115
116
|
from ..exceptions import check_status_carg
|
|
116
117
|
|
|
117
118
|
gb_obj = ffi.new("GrB_Type*")
|
|
118
|
-
|
|
119
|
+
|
|
120
|
+
if hasattr(lib, "GrB_Type_set_String"):
|
|
121
|
+
# We name this so that we can serialize and deserialize UDTs
|
|
122
|
+
# We don't yet have C definitions
|
|
123
|
+
np_repr = _dtype_to_string(dtype)
|
|
124
|
+
status = lib.GrB_Type_new(gb_obj, dtype.itemsize)
|
|
125
|
+
check_status_carg(status, "Type", gb_obj[0])
|
|
126
|
+
val_obj = ffi.new("char[]", np_repr.encode())
|
|
127
|
+
status = lib.GrB_Type_set_String(gb_obj[0], val_obj, lib.GrB_NAME)
|
|
128
|
+
elif backend == "suitesparse":
|
|
129
|
+
# For SuiteSparse < 9
|
|
119
130
|
# We name this so that we can serialize and deserialize UDTs
|
|
120
131
|
# We don't yet have C definitions
|
|
121
132
|
np_repr = _dtype_to_string(dtype).encode()
|
|
@@ -375,8 +386,7 @@ def lookup_dtype(key, value=None):
|
|
|
375
386
|
|
|
376
387
|
|
|
377
388
|
def unify(type1, type2, *, is_left_scalar=False, is_right_scalar=False):
|
|
378
|
-
"""
|
|
379
|
-
Returns a type that can hold both type1 and type2.
|
|
389
|
+
"""Returns a type that can hold both type1 and type2.
|
|
380
390
|
|
|
381
391
|
For example:
|
|
382
392
|
unify(INT32, INT64) -> INT64
|
|
@@ -430,7 +440,7 @@ def _dtype_to_string(dtype):
|
|
|
430
440
|
np_type = dtype.np_type
|
|
431
441
|
s = str(np_type)
|
|
432
442
|
try:
|
|
433
|
-
if np.dtype(
|
|
443
|
+
if np.dtype(literal_eval(s)) == np_type: # pragma: no branch (safety)
|
|
434
444
|
return s
|
|
435
445
|
except Exception:
|
|
436
446
|
pass
|
|
@@ -449,5 +459,5 @@ def _string_to_dtype(s):
|
|
|
449
459
|
return lookup_dtype(s)
|
|
450
460
|
except Exception:
|
|
451
461
|
pass
|
|
452
|
-
np_type = np.dtype(
|
|
462
|
+
np_type = np.dtype(literal_eval(s))
|
|
453
463
|
return lookup_dtype(np_type)
|
|
@@ -147,13 +147,13 @@ class IndexerResolver:
|
|
|
147
147
|
return self.indices[0]._py_index()
|
|
148
148
|
|
|
149
149
|
def parse_indices(self, indices, shape):
|
|
150
|
-
"""
|
|
151
|
-
Returns
|
|
150
|
+
"""Returns
|
|
152
151
|
-------
|
|
153
152
|
[(rows, rowsize), (cols, colsize)] for Matrix
|
|
154
153
|
[(idx, idx_size)] for Vector
|
|
155
154
|
|
|
156
155
|
Within each tuple, if the index is of type int, the size will be None
|
|
156
|
+
|
|
157
157
|
"""
|
|
158
158
|
if len(shape) == 1:
|
|
159
159
|
if type(indices) is tuple:
|
|
@@ -312,8 +312,8 @@ class AmbiguousAssignOrExtract:
|
|
|
312
312
|
Updater(self.parent, opts=opts)._setitem(self.resolved_indexes, expr, is_submask=False)
|
|
313
313
|
|
|
314
314
|
def new(self, dtype=None, *, mask=None, input_mask=None, name=None, **opts):
|
|
315
|
-
"""
|
|
316
|
-
|
|
315
|
+
"""Force extraction of the indexes into a new object.
|
|
316
|
+
|
|
317
317
|
dtype and mask are the only controllable parameters.
|
|
318
318
|
"""
|
|
319
319
|
if input_mask is not None:
|
|
@@ -630,7 +630,7 @@ def create_header(type_name, keys, vals, *, lower_border=False, name="", quote=T
|
|
|
630
630
|
name = f'"{name}"'
|
|
631
631
|
key_text = []
|
|
632
632
|
val_text = []
|
|
633
|
-
for key, val in zip(keys, vals):
|
|
633
|
+
for key, val in zip(keys, vals, strict=True):
|
|
634
634
|
width = max(len(key), len(val)) + 2
|
|
635
635
|
key_text.append(key.rjust(width))
|
|
636
636
|
val_text.append(val.rjust(width))
|
|
@@ -236,7 +236,6 @@ class VectorInfixExpr(InfixExprBase):
|
|
|
236
236
|
to_coo = wrapdoc(Vector.to_coo)(property(automethods.to_coo))
|
|
237
237
|
to_dense = wrapdoc(Vector.to_dense)(property(automethods.to_dense))
|
|
238
238
|
to_dict = wrapdoc(Vector.to_dict)(property(automethods.to_dict))
|
|
239
|
-
to_values = wrapdoc(Vector.to_values)(property(automethods.to_values))
|
|
240
239
|
vxm = wrapdoc(Vector.vxm)(property(automethods.vxm))
|
|
241
240
|
wait = wrapdoc(Vector.wait)(property(automethods.wait))
|
|
242
241
|
# These raise exceptions
|
|
@@ -317,6 +316,7 @@ class MatrixInfixExpr(InfixExprBase):
|
|
|
317
316
|
ndim = 2
|
|
318
317
|
output_type = MatrixExpression
|
|
319
318
|
_is_transposed = False
|
|
319
|
+
__networkx_backend__ = "graphblas"
|
|
320
320
|
__networkx_plugin__ = "graphblas"
|
|
321
321
|
|
|
322
322
|
def __init__(self, left, right):
|
|
@@ -396,7 +396,6 @@ class MatrixInfixExpr(InfixExprBase):
|
|
|
396
396
|
to_dense = wrapdoc(Matrix.to_dense)(property(automethods.to_dense))
|
|
397
397
|
to_dicts = wrapdoc(Matrix.to_dicts)(property(automethods.to_dicts))
|
|
398
398
|
to_edgelist = wrapdoc(Matrix.to_edgelist)(property(automethods.to_edgelist))
|
|
399
|
-
to_values = wrapdoc(Matrix.to_values)(property(automethods.to_values))
|
|
400
399
|
wait = wrapdoc(Matrix.wait)(property(automethods.wait))
|
|
401
400
|
# These raise exceptions
|
|
402
401
|
__array__ = Matrix.__array__
|