-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
What happened?
Summary:
When using StabilityMatrix.analyze() on large sparse matrices (scipy.sparse.csr_matrix), the function returns NaN eigenvalues and fails to classify stability correctly.
The issue seems to occur because the module uses numpy.linalg.eigvals() instead of a sparse-aware solver like scipy.sparse.linalg.eigs().
Environment Details:
- StabilityMatrix version: 1.3.2 (installed via pip)
- Commit hash: 9a6c21b (main branch, latest as of Oct 2025)
- OS: Ubuntu 24.04 (64-bit)
- Python: 3.11.6
- NumPy: 1.26.4
- SciPy: 1.11.1
- CPU: AMD Ryzen 7 7800X
- Memory: 32GB RAM
Steps to Reproduce:
import numpy as np
import scipy.sparse as sp
from stabilitymatrix import StabilityAnalyzer
# Create random sparse matrix
n = 20000
rows = np.random.randint(0, n, size=100000)
cols = np.random.randint(0, n, size=100000)
data = np.random.randn(100000)
A = sp.csr_matrix((data, (rows, cols)), shape=(n, n))
analyzer = StabilityAnalyzer(config={"threshold": 0.01})
result = analyzer.analyze(A)
print(result)Expected Behavior:
- Function should detect sparse input and use a suitable sparse solver.
- Should return finite, valid eigenvalues and an accurate stability classification (
stable,unstable,neutral, etc.).
Actual Behavior:
- Output contains
NaNvalues for most eigenvalues. - Stability classification incorrectly defaults to
"unstable". - Full traceback below:
Traceback (most recent call last):
File "sparse_test.py", line 12, in <module>
result = analyzer.analyze(A)
File "/usr/local/lib/python3.11/site-packages/stabilitymatrix/core.py", line 234, in analyze
vals = np.linalg.eigvals(A)
File "<__array_function__ internals>", line 200, in eigvals
ValueError: Array must not contain NaN
Observed Frequency:
Reproducible 100% of the time when using scipy.sparse.csr_matrix inputs larger than 5000×5000.
Dense arrays (np.ndarray) work fine, so issue is specific to sparse formats.
Impact Severity:
🟠 Major — prevents large-scale systems from being analyzed. Converting to dense matrices causes OOM errors on medium to large inputs.
Workaround:
Convert sparse matrix to dense before analysis:
result = analyzer.analyze(A.toarray())Suggested Fix:
- Add sparse matrix detection before eigenvalue computation:
if sp.issparse(A):
vals = sp.linalg.eigs(A, k=min(A.shape[0]-2, 10))[0]
else:
vals = np.linalg.eigvals(A)- Normalize results with
np.nan_to_num(vals)before stability classification. - Add unit test in
tests/test_sparse_input.pyfor both CSR and CSC inputs.
Possible Root Cause:
np.linalg.eigvals() does not handle sparse matrix objects and implicitly converts them to dense arrays filled with zeros, causing instability and NaN propagation.
Proposed Solution:
- Use
scipy.sparse.linalg.eigs()for all sparse matrices. - Add input validation in
analyze()to warn users when passing unsupported matrix types. - Include regression test with sparse input to prevent recurrence.
Related Code:
File: /stabilitymatrix/core.py
Lines: 220–240
Likely responsible function:
def analyze(self, A):
vals = np.linalg.eigvals(A)
...Additional Context:
This bug appeared after the switch from eigsh to eigvals in commit 6d8c3a.
It may have been introduced when adding GPU acceleration support.
Would be ideal to add an optional config flag:
use_sparse_solver=True to handle these cases automatically.
Maintainer Notes (if applicable):
Please tag this issue as bug, high-priority, and sparse-matrix.
I’m happy to submit a PR with the fix if approved.
Steps to reproduce
No response
Relevant logs
Version
v1.1.23
What Operating System are you using?
Windows