torchsparsegradutils 0.2.4__tar.gz → 0.2.5__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.
- {torchsparsegradutils-0.2.4/torchsparsegradutils.egg-info → torchsparsegradutils-0.2.5}/PKG-INFO +11 -8
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/README.md +10 -7
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/docs/source/conf.py +2 -2
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/pyproject.toml +7 -1
- torchsparsegradutils-0.2.5/torchsparsegradutils/_compat.py +48 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/sparse_generic_solve_rand.py +2 -2
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/sparse_generic_solve_suite.py +3 -4
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/sparse_triangular_solve_rand.py +16 -12
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/sparse_triangular_solve_suitesparse.py +15 -12
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/sparse_solve.py +8 -10
- torchsparsegradutils-0.2.5/torchsparsegradutils/tests/test_deprecated_torch_apis.py +62 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_integration_pairwise_sparse_mvn.py +7 -7
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_linear_cg.py +5 -5
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_minres.py +1 -1
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_quickstart_guide.py +2 -7
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_random.py +1 -1
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_sparse_triangular_solve.py +104 -79
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/utils/linear_cg.py +8 -10
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/utils/lsmr.py +6 -6
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/utils/minres.py +3 -3
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5/torchsparsegradutils.egg-info}/PKG-INFO +11 -8
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils.egg-info/SOURCES.txt +2 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/LICENSE +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/MANIFEST.in +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/setup.cfg +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/setup.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/__init__.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/__init__.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/batched_sparse_mm_rand.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/benchmark_suite.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/benchmark_utils.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/sparse_bidir_logsumexp_rand.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/sparse_bidir_logsumexp_suitesparse.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/sparse_logsumexp_rand.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/sparse_logsumexp_suitesparse.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/sparse_mm_rand.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/sparse_mm_suite.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/benchmarks/visualize_benchmark_results.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/cupy/__init__.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/cupy/cupy_bindings.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/cupy/cupy_sparse_solve.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/distributions/__init__.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/distributions/constraints.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/distributions/sparse_multivariate_normal.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/encoders/__init__.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/encoders/pairwise_encoder.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/encoders/pairwise_voxel_encoder.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/indexed_matmul.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/jax/__init__.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/jax/jax_bindings.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/jax/jax_sparse_solve.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/sparse_logsumexp.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/sparse_lstsq.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/sparse_matmul.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/__init__.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/conftest.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_bicgstab.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_config.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_cupy_bindings.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_cupy_sparse_solve.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_dist_stats_helpers.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_distributions.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_doctests.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_encoders.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_indexed_matmul.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_jax_bindings.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_jax_sparse_solve.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_lsmr.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_params/czyx_shifts.yaml +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_params/pairwise_coo_indices.yaml +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_params/xyz_coords.yaml +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_sparse_bidir_logsumexp.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_sparse_logsumexp.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_sparse_lstsq.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_sparse_matmul.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_sparse_solve.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_utils.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/utils/__init__.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/utils/bicgstab.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/utils/dist_stats_helpers.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/utils/random_sparse.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/utils/utils.py +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils.egg-info/dependency_links.txt +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils.egg-info/not-zip-safe +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils.egg-info/requires.txt +0 -0
- {torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils.egg-info/top_level.txt +0 -0
{torchsparsegradutils-0.2.4/torchsparsegradutils.egg-info → torchsparsegradutils-0.2.5}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: torchsparsegradutils
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: A collection of utility functions to work with PyTorch sparse tensors
|
|
5
5
|
Author-email: CAI4CAI research group <contact@cai4cai.uk>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -239,15 +239,18 @@ batch_size, event_size = 2, 1000
|
|
|
239
239
|
loc = torch.zeros(batch_size, event_size)
|
|
240
240
|
|
|
241
241
|
# Example 1: LDL^T parameterization (numerically stable for precision matrices)
|
|
242
|
-
# Create sparse lower triangular matrix (
|
|
242
|
+
# Create sparse lower triangular matrix (strictly lower triangular, no diagonal)
|
|
243
|
+
|
|
243
244
|
scale_tril = rand_sparse_tri(
|
|
244
245
|
(batch_size, event_size, event_size),
|
|
245
|
-
nnz=5000, # 5000 non-zeros for
|
|
246
|
+
nnz=5000, # 5000 non-zeros for 1000x1000 dense matrix (99.5% sparsity)
|
|
246
247
|
layout=torch.sparse_csr,
|
|
247
248
|
upper=False,
|
|
248
|
-
|
|
249
|
+
strict=True # Strict triangular (exclude diagonal)
|
|
249
250
|
)
|
|
250
251
|
|
|
252
|
+
scale_tril.requires_grad_(True)
|
|
253
|
+
|
|
251
254
|
# Diagonal component for LDL^T parameterization
|
|
252
255
|
diagonal = torch.ones(batch_size, event_size) * 0.5
|
|
253
256
|
|
|
@@ -255,7 +258,7 @@ diagonal = torch.ones(batch_size, event_size) * 0.5
|
|
|
255
258
|
dist_ldlt = SparseMultivariateNormal(
|
|
256
259
|
loc=loc,
|
|
257
260
|
diagonal=diagonal,
|
|
258
|
-
scale_tril=scale_tril #
|
|
261
|
+
scale_tril=scale_tril # Strictly lower triangular
|
|
259
262
|
)
|
|
260
263
|
|
|
261
264
|
# Example 2: LL^T parameterization (standard Cholesky)
|
|
@@ -264,7 +267,7 @@ scale_tril_chol = rand_sparse_tri(
|
|
|
264
267
|
nnz=5000,
|
|
265
268
|
layout=torch.sparse_csr,
|
|
266
269
|
upper=False,
|
|
267
|
-
|
|
270
|
+
strict=False # Include diagonal
|
|
268
271
|
)
|
|
269
272
|
|
|
270
273
|
# Create distribution with LL^T parameterization
|
|
@@ -279,7 +282,7 @@ precision_tril = rand_sparse_tri(
|
|
|
279
282
|
nnz=5000,
|
|
280
283
|
layout=torch.sparse_csr,
|
|
281
284
|
upper=False,
|
|
282
|
-
|
|
285
|
+
strict=True
|
|
283
286
|
)
|
|
284
287
|
|
|
285
288
|
precision_diagonal = torch.ones(batch_size, event_size) * 2.0
|
|
@@ -287,7 +290,7 @@ precision_diagonal = torch.ones(batch_size, event_size) * 2.0
|
|
|
287
290
|
dist_precision = SparseMultivariateNormal(
|
|
288
291
|
loc=loc,
|
|
289
292
|
diagonal=precision_diagonal,
|
|
290
|
-
precision_tril=precision_tril #
|
|
293
|
+
precision_tril=precision_tril # Strictly triangular precision factor
|
|
291
294
|
)
|
|
292
295
|
|
|
293
296
|
# Sample with gradient support
|
|
@@ -192,15 +192,18 @@ batch_size, event_size = 2, 1000
|
|
|
192
192
|
loc = torch.zeros(batch_size, event_size)
|
|
193
193
|
|
|
194
194
|
# Example 1: LDL^T parameterization (numerically stable for precision matrices)
|
|
195
|
-
# Create sparse lower triangular matrix (
|
|
195
|
+
# Create sparse lower triangular matrix (strictly lower triangular, no diagonal)
|
|
196
|
+
|
|
196
197
|
scale_tril = rand_sparse_tri(
|
|
197
198
|
(batch_size, event_size, event_size),
|
|
198
|
-
nnz=5000, # 5000 non-zeros for
|
|
199
|
+
nnz=5000, # 5000 non-zeros for 1000x1000 dense matrix (99.5% sparsity)
|
|
199
200
|
layout=torch.sparse_csr,
|
|
200
201
|
upper=False,
|
|
201
|
-
|
|
202
|
+
strict=True # Strict triangular (exclude diagonal)
|
|
202
203
|
)
|
|
203
204
|
|
|
205
|
+
scale_tril.requires_grad_(True)
|
|
206
|
+
|
|
204
207
|
# Diagonal component for LDL^T parameterization
|
|
205
208
|
diagonal = torch.ones(batch_size, event_size) * 0.5
|
|
206
209
|
|
|
@@ -208,7 +211,7 @@ diagonal = torch.ones(batch_size, event_size) * 0.5
|
|
|
208
211
|
dist_ldlt = SparseMultivariateNormal(
|
|
209
212
|
loc=loc,
|
|
210
213
|
diagonal=diagonal,
|
|
211
|
-
scale_tril=scale_tril #
|
|
214
|
+
scale_tril=scale_tril # Strictly lower triangular
|
|
212
215
|
)
|
|
213
216
|
|
|
214
217
|
# Example 2: LL^T parameterization (standard Cholesky)
|
|
@@ -217,7 +220,7 @@ scale_tril_chol = rand_sparse_tri(
|
|
|
217
220
|
nnz=5000,
|
|
218
221
|
layout=torch.sparse_csr,
|
|
219
222
|
upper=False,
|
|
220
|
-
|
|
223
|
+
strict=False # Include diagonal
|
|
221
224
|
)
|
|
222
225
|
|
|
223
226
|
# Create distribution with LL^T parameterization
|
|
@@ -232,7 +235,7 @@ precision_tril = rand_sparse_tri(
|
|
|
232
235
|
nnz=5000,
|
|
233
236
|
layout=torch.sparse_csr,
|
|
234
237
|
upper=False,
|
|
235
|
-
|
|
238
|
+
strict=True
|
|
236
239
|
)
|
|
237
240
|
|
|
238
241
|
precision_diagonal = torch.ones(batch_size, event_size) * 2.0
|
|
@@ -240,7 +243,7 @@ precision_diagonal = torch.ones(batch_size, event_size) * 2.0
|
|
|
240
243
|
dist_precision = SparseMultivariateNormal(
|
|
241
244
|
loc=loc,
|
|
242
245
|
diagonal=precision_diagonal,
|
|
243
|
-
precision_tril=precision_tril #
|
|
246
|
+
precision_tril=precision_tril # Strictly triangular precision factor
|
|
244
247
|
)
|
|
245
248
|
|
|
246
249
|
# Sample with gradient support
|
|
@@ -15,8 +15,8 @@ sys.path.insert(0, os.path.abspath("../../"))
|
|
|
15
15
|
project = "torchsparsegradutils"
|
|
16
16
|
copyright = "2026, CAI4CAI research group"
|
|
17
17
|
author = "CAI4CAI research group"
|
|
18
|
-
release = "0.2.
|
|
19
|
-
version = "0.2.
|
|
18
|
+
release = "0.2.5"
|
|
19
|
+
version = "0.2.5"
|
|
20
20
|
|
|
21
21
|
# -- General configuration ---------------------------------------------------
|
|
22
22
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "torchsparsegradutils"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.5"
|
|
8
8
|
description = "A collection of utility functions to work with PyTorch sparse tensors"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -105,6 +105,12 @@ testpaths = [
|
|
|
105
105
|
pythonpath = [
|
|
106
106
|
"torchsparsegradutils/tests",
|
|
107
107
|
]
|
|
108
|
+
# Fail tests when deprecated upstream APIs are exercised outside intentional compatibility paths.
|
|
109
|
+
filterwarnings = [
|
|
110
|
+
'error:torch\.norm is deprecated.*:UserWarning',
|
|
111
|
+
'error:torch\.triangular_solve is deprecated.*:UserWarning',
|
|
112
|
+
'error:.*torch\.jit\.script.*is deprecated.*:DeprecationWarning',
|
|
113
|
+
]
|
|
108
114
|
doctest_optionflags = [
|
|
109
115
|
"NORMALIZE_WHITESPACE",
|
|
110
116
|
"IGNORE_EXCEPTION_DETAIL",
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Compatibility helpers for PyTorch APIs without feature-equivalent replacements."""
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
import torch
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def linalg_solve_triangular_compat(
|
|
9
|
+
A: torch.Tensor,
|
|
10
|
+
B: torch.Tensor,
|
|
11
|
+
*,
|
|
12
|
+
upper: bool,
|
|
13
|
+
unitriangular: bool = False,
|
|
14
|
+
transpose: bool = False,
|
|
15
|
+
) -> torch.Tensor:
|
|
16
|
+
"""Solve a triangular system with the appropriate dense or sparse backend.
|
|
17
|
+
|
|
18
|
+
Dense coefficient matrices use ``torch.linalg.solve_triangular``. Sparse
|
|
19
|
+
matrices continue to use the isolated legacy call because the replacement
|
|
20
|
+
API does not support the sparse layouts required by this package. See
|
|
21
|
+
https://github.com/pytorch/pytorch/issues/87358 for upstream sparse feature
|
|
22
|
+
parity tracking.
|
|
23
|
+
"""
|
|
24
|
+
if A.layout == torch.strided:
|
|
25
|
+
if transpose:
|
|
26
|
+
A = A.transpose(-2, -1)
|
|
27
|
+
upper = not upper
|
|
28
|
+
|
|
29
|
+
return torch.linalg.solve_triangular(
|
|
30
|
+
A,
|
|
31
|
+
B,
|
|
32
|
+
upper=upper,
|
|
33
|
+
unitriangular=unitriangular,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
with warnings.catch_warnings():
|
|
37
|
+
warnings.filterwarnings(
|
|
38
|
+
"ignore",
|
|
39
|
+
message=r"torch\.triangular_solve is deprecated.*",
|
|
40
|
+
category=UserWarning,
|
|
41
|
+
)
|
|
42
|
+
return torch.triangular_solve(
|
|
43
|
+
B,
|
|
44
|
+
A,
|
|
45
|
+
upper=upper,
|
|
46
|
+
transpose=transpose,
|
|
47
|
+
unitriangular=unitriangular,
|
|
48
|
+
).solution
|
|
@@ -225,8 +225,8 @@ def run_sparse_generic_solve_benchmark():
|
|
|
225
225
|
else:
|
|
226
226
|
residual = A_sparse @ x - B
|
|
227
227
|
|
|
228
|
-
resnorm = torch.
|
|
229
|
-
B_norm = torch.
|
|
228
|
+
resnorm = torch.linalg.vector_norm(residual).cpu().item()
|
|
229
|
+
B_norm = torch.linalg.vector_norm(B).cpu().item()
|
|
230
230
|
relative_resnorm = resnorm / B_norm if B_norm > 0 else 0.0
|
|
231
231
|
|
|
232
232
|
# Print result with residual norm
|
|
@@ -201,10 +201,9 @@ def run_sparse_solve_benchmark():
|
|
|
201
201
|
with torch.no_grad():
|
|
202
202
|
x = alg_fn(A_sparse, B)
|
|
203
203
|
residual = A_sparse @ x - B
|
|
204
|
-
resnorm = torch.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
)
|
|
204
|
+
resnorm = torch.linalg.vector_norm(residual).cpu().item()
|
|
205
|
+
B_norm = torch.linalg.vector_norm(B).cpu().item()
|
|
206
|
+
relative_resnorm = resnorm / B_norm if B_norm > 0 else 0.0
|
|
208
207
|
|
|
209
208
|
# Print result with residual norm
|
|
210
209
|
print_result_row(
|
|
@@ -27,6 +27,7 @@ from cupyx.scipy.sparse.linalg._solve import spsolve_triangular
|
|
|
27
27
|
from tqdm import tqdm
|
|
28
28
|
|
|
29
29
|
from torchsparsegradutils import sparse_triangular_solve
|
|
30
|
+
from torchsparsegradutils._compat import linalg_solve_triangular_compat
|
|
30
31
|
from torchsparsegradutils.cupy.cupy_sparse_solve import sparse_solve_c4t
|
|
31
32
|
from torchsparsegradutils.utils import rand_sparse, rand_sparse_tri
|
|
32
33
|
|
|
@@ -58,16 +59,19 @@ LAYOUTS = [torch.sparse_coo, torch.sparse_csr]
|
|
|
58
59
|
|
|
59
60
|
ALGORITHMS = [
|
|
60
61
|
(
|
|
61
|
-
"dense.
|
|
62
|
-
lambda A, B: torch.
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
"dense.linalg.solve_triangular",
|
|
63
|
+
lambda A, B: torch.linalg.solve_triangular(
|
|
64
|
+
A.to_dense().transpose(-2, -1) if TRANSPOSE else A.to_dense(),
|
|
65
|
+
B,
|
|
66
|
+
upper=not UPPER if TRANSPOSE else UPPER,
|
|
67
|
+
unitriangular=UNITRIANGULAR,
|
|
68
|
+
),
|
|
65
69
|
),
|
|
66
70
|
(
|
|
67
|
-
"
|
|
68
|
-
lambda A, B:
|
|
69
|
-
|
|
70
|
-
)
|
|
71
|
+
"linalg_solve_triangular_compat",
|
|
72
|
+
lambda A, B: linalg_solve_triangular_compat(
|
|
73
|
+
A, B, upper=UPPER, unitriangular=UNITRIANGULAR, transpose=TRANSPOSE
|
|
74
|
+
),
|
|
71
75
|
),
|
|
72
76
|
(
|
|
73
77
|
"sparse_triangular_solve",
|
|
@@ -153,8 +157,8 @@ def run_sparse_triangular_solve_benchmark():
|
|
|
153
157
|
with torch.no_grad():
|
|
154
158
|
x = alg_fn(A_sparse, B)
|
|
155
159
|
residual = A_sparse @ x - B
|
|
156
|
-
resnorm = torch.
|
|
157
|
-
relative_resnorm = resnorm / torch.
|
|
160
|
+
resnorm = torch.linalg.vector_norm(residual).cpu().item()
|
|
161
|
+
relative_resnorm = resnorm / torch.linalg.vector_norm(B).cpu().item()
|
|
158
162
|
|
|
159
163
|
# # Calculate residual norm for solution accuracy
|
|
160
164
|
# with torch.no_grad():
|
|
@@ -165,8 +169,8 @@ def run_sparse_triangular_solve_benchmark():
|
|
|
165
169
|
# else:
|
|
166
170
|
# Ax = A_sparse @ x
|
|
167
171
|
# residual = Ax - B
|
|
168
|
-
# resnorm = torch.
|
|
169
|
-
# relative_resnorm = resnorm / torch.
|
|
172
|
+
# resnorm = torch.linalg.vector_norm(residual).cpu().item()
|
|
173
|
+
# relative_resnorm = resnorm / torch.linalg.vector_norm(B).cpu().item()
|
|
170
174
|
|
|
171
175
|
# Print result with residual norm
|
|
172
176
|
print_result_row(
|
|
@@ -34,6 +34,7 @@ from cupyx.scipy.sparse.linalg._solve import spsolve_triangular
|
|
|
34
34
|
from tqdm import tqdm
|
|
35
35
|
|
|
36
36
|
from torchsparsegradutils import sparse_triangular_solve
|
|
37
|
+
from torchsparsegradutils._compat import linalg_solve_triangular_compat
|
|
37
38
|
from torchsparsegradutils.cupy.cupy_sparse_solve import sparse_solve_c4t
|
|
38
39
|
|
|
39
40
|
# from jax.lax.linalg import triangular_solve # NOTE: jax doesn't have a sparse triangular solve
|
|
@@ -57,16 +58,19 @@ LAYOUTS = [torch.sparse_coo, torch.sparse_csr]
|
|
|
57
58
|
|
|
58
59
|
ALGORITHMS = [
|
|
59
60
|
(
|
|
60
|
-
"dense.
|
|
61
|
-
lambda A, B: torch.
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
"dense.linalg.solve_triangular",
|
|
62
|
+
lambda A, B: torch.linalg.solve_triangular(
|
|
63
|
+
A.to_dense().transpose(-2, -1) if TRANSPOSE else A.to_dense(),
|
|
64
|
+
B,
|
|
65
|
+
upper=not UPPER if TRANSPOSE else UPPER,
|
|
66
|
+
unitriangular=UNITRIANGULAR,
|
|
67
|
+
),
|
|
64
68
|
),
|
|
65
69
|
(
|
|
66
|
-
"
|
|
67
|
-
lambda A, B:
|
|
68
|
-
|
|
69
|
-
)
|
|
70
|
+
"linalg_solve_triangular_compat",
|
|
71
|
+
lambda A, B: linalg_solve_triangular_compat(
|
|
72
|
+
A, B, upper=UPPER, unitriangular=UNITRIANGULAR, transpose=TRANSPOSE
|
|
73
|
+
),
|
|
70
74
|
),
|
|
71
75
|
(
|
|
72
76
|
"sparse_triangular_solve",
|
|
@@ -185,10 +189,9 @@ def run_triangular_solve_benchmark():
|
|
|
185
189
|
# Use the triangular matrix A_sparse (not A_full) for residual calculation
|
|
186
190
|
# This ensures the residual is computed correctly for the actual triangular system solved
|
|
187
191
|
residual = A_sparse @ x - B
|
|
188
|
-
resnorm = torch.
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
)
|
|
192
|
+
resnorm = torch.linalg.vector_norm(residual).cpu().item()
|
|
193
|
+
B_norm = torch.linalg.vector_norm(B).cpu().item()
|
|
194
|
+
relative_resnorm = resnorm / B_norm if B_norm > 0 else 0.0
|
|
192
195
|
|
|
193
196
|
# Print result
|
|
194
197
|
print_result_row(
|
{torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/sparse_solve.py
RENAMED
|
@@ -3,6 +3,7 @@ from typing import Callable, Optional, cast
|
|
|
3
3
|
|
|
4
4
|
import torch
|
|
5
5
|
|
|
6
|
+
from torchsparsegradutils._compat import linalg_solve_triangular_compat
|
|
6
7
|
from torchsparsegradutils.utils import convert_coo_to_csr, sparse_block_diag, sparse_block_diag_split, stack_csr
|
|
7
8
|
|
|
8
9
|
|
|
@@ -154,7 +155,7 @@ class SparseTriangularSolve(torch.autograd.Function):
|
|
|
154
155
|
See Also
|
|
155
156
|
--------
|
|
156
157
|
sparse_triangular_solve : User-facing function that calls this autograd function.
|
|
157
|
-
torch.
|
|
158
|
+
torch.linalg.solve_triangular : PyTorch's native dense triangular solver.
|
|
158
159
|
"""
|
|
159
160
|
|
|
160
161
|
@staticmethod
|
|
@@ -177,11 +178,9 @@ class SparseTriangularSolve(torch.autograd.Function):
|
|
|
177
178
|
A = convert_coo_to_csr(A) # NOTE: triangular solve doesn't work with sparse coo
|
|
178
179
|
ctx.csr = False
|
|
179
180
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
B.detach(), A.detach(), upper=upper, unitriangular=unitriangular, transpose=transpose
|
|
184
|
-
).solution
|
|
181
|
+
x = linalg_solve_triangular_compat(
|
|
182
|
+
A.detach(), B.detach(), upper=upper, unitriangular=unitriangular, transpose=transpose
|
|
183
|
+
)
|
|
185
184
|
|
|
186
185
|
x.requires_grad = grad_flag
|
|
187
186
|
ctx.save_for_backward(A, x.detach())
|
|
@@ -199,11 +198,10 @@ class SparseTriangularSolve(torch.autograd.Function):
|
|
|
199
198
|
A, x = ctx.saved_tensors
|
|
200
199
|
|
|
201
200
|
# Backprop rule: gradB = A^{-T} grad
|
|
202
|
-
# NOTE: DEPRECATED: Check if a workaround for https://github.com/pytorch/pytorch/issues/88890 is needed
|
|
203
201
|
|
|
204
|
-
gradB =
|
|
205
|
-
|
|
206
|
-
)
|
|
202
|
+
gradB = linalg_solve_triangular_compat(
|
|
203
|
+
A, grad, upper=ctx.upper, transpose=not ctx.transpose, unitriangular=ctx.unitriangular
|
|
204
|
+
)
|
|
207
205
|
|
|
208
206
|
# The gradient with respect to the matrix A seen as a dense matrix would
|
|
209
207
|
# lead to a backprop rule as follows
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Regression checks for deprecated upstream PyTorch APIs."""
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
import re
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
REPOSITORY_ROOT = Path(__file__).parents[2]
|
|
8
|
+
PACKAGE_ROOT = REPOSITORY_ROOT / "torchsparsegradutils"
|
|
9
|
+
COMPATIBILITY_MODULE = Path("_compat.py")
|
|
10
|
+
DEPRECATED_DOCUMENTATION_NORM = re.compile(r"(?<![\w.])torch\.norm\s*\(")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def attribute_name(node):
|
|
14
|
+
parts = []
|
|
15
|
+
while isinstance(node, ast.Attribute):
|
|
16
|
+
parts.append(node.attr)
|
|
17
|
+
node = node.value
|
|
18
|
+
if isinstance(node, ast.Name):
|
|
19
|
+
parts.append(node.id)
|
|
20
|
+
return ".".join(reversed(parts))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_deprecated_torch_calls_are_not_reintroduced():
|
|
24
|
+
violations = []
|
|
25
|
+
compatibility_calls = []
|
|
26
|
+
|
|
27
|
+
for path in PACKAGE_ROOT.rglob("*.py"):
|
|
28
|
+
relative_path = path.relative_to(PACKAGE_ROOT)
|
|
29
|
+
tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
|
|
30
|
+
|
|
31
|
+
for node in ast.walk(tree):
|
|
32
|
+
location = f"{relative_path}:{getattr(node, 'lineno', '?')}"
|
|
33
|
+
if isinstance(node, ast.Attribute) and attribute_name(node) == "torch.jit.script":
|
|
34
|
+
violations.append(location)
|
|
35
|
+
|
|
36
|
+
if not isinstance(node, ast.Call) or not isinstance(node.func, ast.Attribute):
|
|
37
|
+
continue
|
|
38
|
+
|
|
39
|
+
call_name = attribute_name(node.func)
|
|
40
|
+
if call_name == "torch.norm":
|
|
41
|
+
violations.append(location)
|
|
42
|
+
elif call_name == "torch.triangular_solve":
|
|
43
|
+
if relative_path == COMPATIBILITY_MODULE:
|
|
44
|
+
compatibility_calls.append(location)
|
|
45
|
+
else:
|
|
46
|
+
violations.append(location)
|
|
47
|
+
|
|
48
|
+
assert not violations, "Deprecated PyTorch APIs found:\n" + "\n".join(violations)
|
|
49
|
+
assert len(compatibility_calls) == 1, "Expected one isolated sparse triangular compatibility call"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_documentation_does_not_use_deprecated_norm_apis():
|
|
53
|
+
violations = []
|
|
54
|
+
documentation_paths = [REPOSITORY_ROOT / "README.md"]
|
|
55
|
+
documentation_paths.extend((REPOSITORY_ROOT / "docs").rglob("*.md"))
|
|
56
|
+
documentation_paths.extend((REPOSITORY_ROOT / "docs").rglob("*.rst"))
|
|
57
|
+
|
|
58
|
+
for path in documentation_paths:
|
|
59
|
+
if DEPRECATED_DOCUMENTATION_NORM.search(path.read_text(encoding="utf-8")):
|
|
60
|
+
violations.append(str(path.relative_to(REPOSITORY_ROOT)))
|
|
61
|
+
|
|
62
|
+
assert not violations, "Deprecated norm examples found:\n" + "\n".join(violations)
|
|
@@ -360,7 +360,7 @@ def run_forward_backward_iterations(
|
|
|
360
360
|
|
|
361
361
|
# Record gradient statistics
|
|
362
362
|
if params.grad is not None:
|
|
363
|
-
grad_norm = params.grad
|
|
363
|
+
grad_norm = torch.linalg.vector_norm(params.grad).item()
|
|
364
364
|
grad_max = params.grad.abs().max().item()
|
|
365
365
|
grad_mean = params.grad.abs().mean().item()
|
|
366
366
|
|
|
@@ -505,7 +505,7 @@ def test_integration_gradient_flow_consistency_2d(
|
|
|
505
505
|
# Backward pass
|
|
506
506
|
loss.backward()
|
|
507
507
|
|
|
508
|
-
gradient_norms.append(params.grad
|
|
508
|
+
gradient_norms.append(torch.linalg.vector_norm(params.grad).item())
|
|
509
509
|
|
|
510
510
|
# Zero gradients
|
|
511
511
|
params.grad.zero_()
|
|
@@ -551,7 +551,7 @@ def test_integration_gradient_flow_consistency_3d(
|
|
|
551
551
|
# Backward pass
|
|
552
552
|
loss.backward()
|
|
553
553
|
|
|
554
|
-
gradient_norms.append(params.grad
|
|
554
|
+
gradient_norms.append(torch.linalg.vector_norm(params.grad).item())
|
|
555
555
|
|
|
556
556
|
# Zero gradients
|
|
557
557
|
params.grad.zero_()
|
|
@@ -591,7 +591,7 @@ def test_integration_parameter_optimization_2d(
|
|
|
591
591
|
|
|
592
592
|
# Optimization loop
|
|
593
593
|
optimizer = torch.optim.Adam([params], lr=0.01)
|
|
594
|
-
initial_param_norm =
|
|
594
|
+
initial_param_norm = torch.linalg.vector_norm(params).item()
|
|
595
595
|
|
|
596
596
|
for _ in range(10):
|
|
597
597
|
optimizer.zero_grad()
|
|
@@ -611,7 +611,7 @@ def test_integration_parameter_optimization_2d(
|
|
|
611
611
|
optimizer.step()
|
|
612
612
|
|
|
613
613
|
# Check that parameters changed
|
|
614
|
-
final_param_norm =
|
|
614
|
+
final_param_norm = torch.linalg.vector_norm(params).item()
|
|
615
615
|
param_change = abs(final_param_norm - initial_param_norm) / initial_param_norm
|
|
616
616
|
|
|
617
617
|
assert param_change > 0.01, f"Parameters barely changed: {param_change:.6f}"
|
|
@@ -642,7 +642,7 @@ def test_integration_parameter_optimization_3d(
|
|
|
642
642
|
|
|
643
643
|
# Optimization loop
|
|
644
644
|
optimizer = torch.optim.Adam([params], lr=0.01)
|
|
645
|
-
initial_param_norm =
|
|
645
|
+
initial_param_norm = torch.linalg.vector_norm(params).item()
|
|
646
646
|
|
|
647
647
|
for _ in range(10):
|
|
648
648
|
optimizer.zero_grad()
|
|
@@ -662,7 +662,7 @@ def test_integration_parameter_optimization_3d(
|
|
|
662
662
|
optimizer.step()
|
|
663
663
|
|
|
664
664
|
# Check that parameters changed
|
|
665
|
-
final_param_norm =
|
|
665
|
+
final_param_norm = torch.linalg.vector_norm(params).item()
|
|
666
666
|
param_change = abs(final_param_norm - initial_param_norm) / initial_param_norm
|
|
667
667
|
|
|
668
668
|
assert param_change > 0.01, f"Parameters barely changed: {param_change:.6f}"
|
|
@@ -10,7 +10,7 @@ def test_cg():
|
|
|
10
10
|
# SPD matrix
|
|
11
11
|
matrix = torch.randn(size, size, dtype=torch.float64)
|
|
12
12
|
matrix = matrix.matmul(matrix.mT)
|
|
13
|
-
matrix.div_(
|
|
13
|
+
matrix.div_(torch.linalg.vector_norm(matrix)).add_(torch.eye(size, dtype=torch.float64) * 1e-1)
|
|
14
14
|
# single RHS
|
|
15
15
|
rhs = torch.randn(size, dtype=torch.float64)
|
|
16
16
|
solves = linear_cg(matrix.matmul, rhs=rhs, max_iter=size)
|
|
@@ -36,7 +36,7 @@ def test_cg_with_tridiag():
|
|
|
36
36
|
size = 10
|
|
37
37
|
matrix = torch.randn(size, size, dtype=torch.float64)
|
|
38
38
|
matrix = matrix.matmul(matrix.mT)
|
|
39
|
-
matrix.div_(
|
|
39
|
+
matrix.div_(torch.linalg.vector_norm(matrix)).add_(torch.eye(size, dtype=torch.float64) * 1e-1)
|
|
40
40
|
rhs = torch.randn(size, 50, dtype=torch.float64)
|
|
41
41
|
solves, t_mats = linear_cg(
|
|
42
42
|
matrix.matmul, rhs=rhs, n_tridiag=5, max_tridiag_iter=10, max_iter=size, tolerance=0, eps=1e-15
|
|
@@ -57,7 +57,7 @@ def test_batch_cg(batch):
|
|
|
57
57
|
shape = (batch, size, size) if batch else (size, size)
|
|
58
58
|
matrix = torch.randn(*shape, dtype=torch.float64)
|
|
59
59
|
matrix = matrix.matmul(matrix.mT)
|
|
60
|
-
matrix.div_(
|
|
60
|
+
matrix.div_(torch.linalg.vector_norm(matrix)).add_(torch.eye(size, dtype=torch.float64) * 1e-1)
|
|
61
61
|
b_shape = (batch, size, 50) if batch else (size, 50)
|
|
62
62
|
rhs = torch.randn(*b_shape, dtype=torch.float64)
|
|
63
63
|
solves = linear_cg(matrix.matmul, rhs=rhs, max_iter=size)
|
|
@@ -72,7 +72,7 @@ def test_batch_cg_with_tridiag(batch):
|
|
|
72
72
|
shape = (batch, size, size) if batch else (size, size)
|
|
73
73
|
matrix = torch.randn(*shape, dtype=torch.float64)
|
|
74
74
|
matrix = matrix.matmul(matrix.mT)
|
|
75
|
-
matrix.div_(
|
|
75
|
+
matrix.div_(torch.linalg.vector_norm(matrix)).add_(torch.eye(size, dtype=torch.float64) * 1e-1)
|
|
76
76
|
b_shape = (batch, size, 10) if batch else (size, 10)
|
|
77
77
|
rhs = torch.randn(*b_shape, dtype=torch.float64)
|
|
78
78
|
solves, t_mats = linear_cg(
|
|
@@ -95,7 +95,7 @@ def test_batch_cg_init():
|
|
|
95
95
|
size = 100
|
|
96
96
|
matrix = torch.randn(batch, size, size, dtype=torch.float64)
|
|
97
97
|
matrix = matrix.matmul(matrix.mT)
|
|
98
|
-
matrix.div_(
|
|
98
|
+
matrix.div_(torch.linalg.vector_norm(matrix)).add_(torch.eye(size, dtype=torch.float64) * 1e-1)
|
|
99
99
|
rhs = torch.randn(batch, size, 50, dtype=torch.float64)
|
|
100
100
|
solves = linear_cg(matrix.matmul, rhs=rhs, max_iter=size, max_tridiag_iter=0)
|
|
101
101
|
solves_init = linear_cg(matrix.matmul, rhs=rhs, max_iter=1, initial_guess=solves, max_tridiag_iter=0)
|
{torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_minres.py
RENAMED
|
@@ -18,7 +18,7 @@ def _run_minres(rhs_shape, shifts=None, matrix_batch_shape=torch.Size([])):
|
|
|
18
18
|
rhs = torch.randn(rhs_shape, dtype=torch.float64)
|
|
19
19
|
matrix = torch.randn(*matrix_batch_shape, size, size, dtype=torch.float64)
|
|
20
20
|
matrix = matrix @ matrix.mT
|
|
21
|
-
matrix = matrix /
|
|
21
|
+
matrix = matrix / torch.linalg.vector_norm(matrix)
|
|
22
22
|
matrix = matrix + torch.eye(size, dtype=torch.float64) * 1e-1
|
|
23
23
|
# compute minres
|
|
24
24
|
if shifts is not None:
|
|
@@ -5,14 +5,9 @@ This module tests all code examples from the quickstart documentation to ensure
|
|
|
5
5
|
It is integrated with pytest and runs as part of the CI pipeline.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import warnings
|
|
9
|
-
|
|
10
8
|
import pytest
|
|
11
9
|
import torch
|
|
12
10
|
|
|
13
|
-
# Suppress warnings for cleaner test output
|
|
14
|
-
warnings.filterwarnings("ignore")
|
|
15
|
-
|
|
16
11
|
|
|
17
12
|
def test_sparse_mm_example():
|
|
18
13
|
"""Test the basic sparse matrix multiplication example from quickstart guide."""
|
|
@@ -76,7 +71,7 @@ def test_triangular_solve():
|
|
|
76
71
|
|
|
77
72
|
# Verify solution (should be close to zero)
|
|
78
73
|
residual = sparse_mm(L, x) - b
|
|
79
|
-
residual_norm = torch.
|
|
74
|
+
residual_norm = torch.linalg.vector_norm(residual)
|
|
80
75
|
assert residual_norm < 1e-5, f"Residual too large: {residual_norm}"
|
|
81
76
|
|
|
82
77
|
|
|
@@ -97,7 +92,7 @@ def test_generic_solve():
|
|
|
97
92
|
|
|
98
93
|
# Verify solution
|
|
99
94
|
residual = A_sparse @ x_cg - b
|
|
100
|
-
residual_norm = torch.
|
|
95
|
+
residual_norm = torch.linalg.vector_norm(residual)
|
|
101
96
|
assert residual_norm < 1e-4, f"Residual too large: {residual_norm}"
|
|
102
97
|
|
|
103
98
|
|
{torchsparsegradutils-0.2.4 → torchsparsegradutils-0.2.5}/torchsparsegradutils/tests/test_random.py
RENAMED
|
@@ -662,7 +662,7 @@ def test_make_spd_sparse_solve_system(device):
|
|
|
662
662
|
try:
|
|
663
663
|
x_dense = torch.linalg.solve(A_dense, b)
|
|
664
664
|
residual = A_dense @ x_dense - b
|
|
665
|
-
residual_norm = torch.
|
|
665
|
+
residual_norm = torch.linalg.vector_norm(residual).item()
|
|
666
666
|
|
|
667
667
|
# Check that residual is small
|
|
668
668
|
assert residual_norm < 1e-10, f"Dense solve residual too large: {residual_norm}"
|