Skip to content

Commit

Permalink
change .A -> .toarray() for scipy 1.14
Browse files Browse the repository at this point in the history
  • Loading branch information
jcmgray committed Jul 3, 2024
1 parent e20abf4 commit e05b77e
Show file tree
Hide file tree
Showing 25 changed files with 4,227 additions and 129 deletions.
4,110 changes: 4,090 additions & 20 deletions docs/examples/ex_2d.ipynb

Large diffs are not rendered by default.

21 changes: 18 additions & 3 deletions quimb/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ def H(self):
else:
return self.transpose()

def toarray(self):
return np.asarray(self)

@property
def A(self):
return np.asarray(self)
Expand Down Expand Up @@ -1040,7 +1043,7 @@ def quimbify(

if qtype is not None:
# Must be dense to reshape
data = qarray(data.A if sparse_input else data)
data = qarray(data.toarray() if sparse_input else data)
if qtype in ("k", "ket"):
data = data.reshape((prod(data.shape), 1))
elif qtype in ("b", "bra"):
Expand All @@ -1051,7 +1054,7 @@ def quimbify(

# Just cast as qarray
elif not sparse_output:
data = qarray(data.A if sparse_input else data, dtype=dtype)
data = qarray(data.toarray() if sparse_input else data, dtype=dtype)

# Check if already sparse matrix, or wanted to be one
if sparse_output:
Expand Down Expand Up @@ -1828,7 +1831,7 @@ def permute(p, dims, perm):
>>> IX = speye(2) & pauli('X', sparse=True)
>>> XI = permute(IX, dims=[2, 2], perm=[1, 0])
>>> np.allclose(XI.A, pauli('X') & eye(2))
>>> np.allclose(XI.toarray(), pauli('X') & eye(2))
True
"""
if issparse(p):
Expand Down Expand Up @@ -2152,6 +2155,18 @@ def partial_trace(p, dims, keep):
sp.coo_matrix.__and__ = kron_dispatch


if not hasattr(sp.csr_matrix, "H"):
# scipy >=1.14 removed the .H attribute

def sparse_hermitian_conjugate(self):
return self.conjugate().transpose()

sp.csr_matrix.H = property(sparse_hermitian_conjugate)
sp.csc_matrix.H = property(sparse_hermitian_conjugate)
sp.coo_matrix.H = property(sparse_hermitian_conjugate)
sp.bsr_matrix.H = property(sparse_hermitian_conjugate)


def csr_mulvec_wrap(fn):
"""Dispatch sparse csr-vector multiplication to parallel method."""

Expand Down
6 changes: 4 additions & 2 deletions quimb/evo.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ def _setup_solved_ham(self):
evals, evecs = self._ham
self._method = "solve"
except ValueError:
evals, evecs = eigh(self._ham.A)
evals, evecs = eigh(self._ham.toarray())
self._ham = (evals, evecs)

# Find initial state in energy eigenbasis at t0
Expand Down Expand Up @@ -578,7 +578,9 @@ def solout(t, y):

self._stepper.set_solout(solout)

self._stepper.set_initial_value(self._p0.A.reshape(-1), self.t0)
self._stepper.set_initial_value(
self._p0.toarray().reshape(-1), self.t0
)

# assign the correct update_to method
self._update_method = self._update_to_integrate
Expand Down
2 changes: 1 addition & 1 deletion quimb/experimental/operatorbuilder/operatorbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ def build_dense(self):
operator.
"""
A = self.build_sparse_matrix(stype="coo")
return A.A
return A.toarray()

def build_local_terms(self):
"""Get a dictionary of local terms, where each key is a sorted tuple
Expand Down
4 changes: 2 additions & 2 deletions quimb/gen/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ def ham_fn(*args, stype='csr', sparse=False, **kwargs):
H = H.real

if not sparse:
H = qarray(H.A)
H = qarray(H.toarray())
elif H.format != stype:
H = H.asformat(stype)

Expand Down Expand Up @@ -1021,7 +1021,7 @@ def zspin_projector(n, sz=0, stype="csr", dtype=float):
Examples
--------
>>> zspin_projector(n=2, sz=0).A
>>> zspin_projector(n=2, sz=0).toarray()
array([[0., 0.],
[1., 0.],
[0., 1.],
Expand Down
4 changes: 2 additions & 2 deletions quimb/linalg/base_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,9 @@ def eigh_window(

if isdense(A) or backend.upper() == "NUMPY":
if return_vecs:
lk, vk = eigh(A.A if issparse(A) else A, **kwargs)
lk, vk = eigh(A.toarray() if issparse(A) else A, **kwargs)
else:
lk = eigvalsh(A.A if issparse(A) else A, **kwargs)
lk = eigvalsh(A.toarray() if issparse(A) else A, **kwargs)

lmin, lmax = lk[0], lk[-1]
l_w0, l_wmin, l_wmax = _rel_window_to_abs_window(lmin, lmax, w_0, w_sz)
Expand Down
13 changes: 7 additions & 6 deletions quimb/linalg/numpy_linalg.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Numpy base linear algebra.
"""
"""Numpy base linear algebra."""

import numpy as np
import numpy.linalg as nla
Expand Down Expand Up @@ -188,7 +187,7 @@ def eigs_numpy(

if return_vecs:
# get all eigenpairs
lk, vk = eig_fn(A.A if qu.issparse(A) else A, **eig_opts)
lk, vk = eig_fn(A.toarray() if qu.issparse(A) else A, **eig_opts)

# sort and trim according to which k we want
sk = sort_inds(lk, method=which, sigma=sigma)[:k]
Expand All @@ -207,7 +206,7 @@ def eigs_numpy(

else:
# get all eigenvalues
lk = eig_fn(A.A if qu.issparse(A) else A, **eig_opts)
lk = eig_fn(A.toarray() if qu.issparse(A) else A, **eig_opts)

# sort and trim according to which k we want
sk = sort_inds(lk, method=which, sigma=sigma)[:k]
Expand Down Expand Up @@ -236,8 +235,10 @@ def svds_numpy(a, k, return_vecs=True, **_):
Singlar value triplets.
"""
if return_vecs:
uk, sk, vkt = nla.svd(a.A if qu.issparse(a) else a, compute_uv=True)
uk, sk, vkt = nla.svd(
a.toarray() if qu.issparse(a) else a, compute_uv=True
)
return qu.qarray(uk[:, :k]), sk[:k], qu.qarray(vkt[:k, :])
else:
sk = nla.svd(a.A if qu.issparse(a) else a, compute_uv=False)
sk = nla.svd(a.toarray() if qu.issparse(a) else a, compute_uv=False)
return sk[:k]
6 changes: 3 additions & 3 deletions quimb/linalg/scipy_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def eigs_scipy(

# avoid matrix like behaviour
if isinstance(A, qu.qarray):
A = A.A
A = A.toarray()

# project into subspace
if P is not None:
Expand Down Expand Up @@ -219,7 +219,7 @@ def eigs_lobpcg(

# avoid matrix like behaviour
if isinstance(A, qu.qarray):
A = A.A
A = A.toarray()

d = A.shape[0]

Expand Down Expand Up @@ -271,7 +271,7 @@ def svds_scipy(A, k=6, *, return_vecs=True, backend=None, **svds_opts):

# avoid matrix like behaviour
if isinstance(A, qu.qarray):
A = A.A
A = A.toarray()

if backend is None:
svds = spla.svds
Expand Down
3 changes: 3 additions & 0 deletions quimb/tensor/tensor_1d.py
Original file line number Diff line number Diff line change
Expand Up @@ -4287,6 +4287,9 @@ def to_dense(self):

return T.to_dense(self.left_inds, self.right_inds)

def toarray(self):
return self.to_dense()

@property
def A(self):
return self.to_dense()
2 changes: 1 addition & 1 deletion quimb/tensor/tensor_arbgeom_tebd.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def _convert_from_qarray_cached(self, x):
cache = self._op_cache["convert_from_qarray"]
key = id(x)
if key not in cache:
cache[key] = x.A
cache[key] = x.toarray()
return cache[key]

def _flip_cached(self, x):
Expand Down
3 changes: 2 additions & 1 deletion quimb/tensor/tensor_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1399,7 +1399,7 @@ def get_params(self):

if isinstance(params, qarray):
# some optimizers don't like ndarray subclasses such as qarray
params = params.A
params = params.toarray()

return params

Expand Down Expand Up @@ -11079,6 +11079,7 @@ def to_dense(self, *inds_seq, to_qarray=False, **contract_opts):
to_qarray=to_qarray,
)

toarray = to_dense
to_qarray = functools.partialmethod(to_dense, to_qarray=True)

@functools.wraps(tensor_split)
Expand Down
4 changes: 2 additions & 2 deletions quimb/tensor/tensor_dmrg.py
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ def _update_local_state_1site(self, i, direction, **compress_opts):
loc_en, loc_gs = self.post_check(i, Neff, loc_gs, loc_en, loc_gs_old)

# insert back into state and all tensor networks viewing it
loc_gs = loc_gs.A.reshape(dims)
loc_gs = loc_gs.toarray().reshape(dims)
self._k[i].modify(data=loc_gs)
self._b[i].modify(data=loc_gs.conj())

Expand Down Expand Up @@ -839,7 +839,7 @@ def _update_local_state_2site(self, i, direction, **compress_opts):
loc_en, loc_gs = self.post_check(i, Neff, loc_gs, loc_en, loc_gs_old)

# split the two site local groundstate
T_AB = Tensor(loc_gs.A.reshape(dims), uix)
T_AB = Tensor(loc_gs.toarray().reshape(dims), uix)
L, R = T_AB.split(
left_inds=uix_L,
get="arrays",
Expand Down
48 changes: 27 additions & 21 deletions tests/test_accel.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,21 +225,21 @@ def test_mul_broadcast(self, mat_d, ket_d):

def test_mul_sparse(self, mat_s, mat_s2):
cq = mul(mat_s, mat_s2)
cn = mat_s.A * mat_s2.A
cn = mat_s.toarray() * mat_s2.toarray()
assert issparse(cq)
assert_allclose(cq.A, cn)
cq = mul(mat_s2.A, mat_s)
cn = mat_s2.A * mat_s.A
assert_allclose(cq.toarray(), cn)
cq = mul(mat_s2.toarray(), mat_s)
cn = mat_s2.toarray() * mat_s.toarray()
assert issparse(cq)
assert_allclose(cq.A, cn)
assert_allclose(cq.toarray(), cn)

def test_mul_sparse_broadcast(self, mat_s, ket_d):
ca = mul(mat_s, ket_d)
cn = np.multiply(mat_s.A, ket_d)
assert_allclose(ca.A, cn)
cn = np.multiply(mat_s.toarray(), ket_d)
assert_allclose(ca.toarray(), cn)
ca = mul(mat_s.H, ket_d)
cn = np.multiply(mat_s.H.A, ket_d)
assert_allclose(ca.A, cn)
cn = np.multiply(mat_s.H.toarray(), ket_d)
assert_allclose(ca.toarray(), cn)


class TestDot:
Expand All @@ -259,7 +259,7 @@ def test_dot_sparse_sparse(self, mat_s, mat_s2):
cq = dot(mat_s, mat_s2)
cn = mat_s @ mat_s2
assert issparse(cq)
assert_allclose(cq.A, cn.A)
assert_allclose(cq.toarray(), cn.toarray())

def test_dot_sparse_dense(self, mat_s, ket_d):
cq = dot(mat_s, ket_d)
Expand All @@ -272,15 +272,15 @@ def test_dot_sparse_dense(self, mat_s, ket_d):
cn = mat_s._mul_vector(ket_d)
assert not issparse(cq)
assert isdense(cq)
assert_allclose(cq.A.ravel(), cn)
assert_allclose(cq.toarray().ravel(), cn)

def test_dot_sparse_dense_ket(self, mat_s, ket_d):
cq = dot(mat_s, ket_d)
cn = mat_s @ ket_d
assert not issparse(cq)
assert isdense(cq)
assert isket(cq)
assert_allclose(cq.A, cn)
assert_allclose(cq.toarray(), cn)

def test_par_dot_csr_matvec(self, mat_s, ket_d):
x = par_dot_csr_matvec(mat_s, ket_d)
Expand Down Expand Up @@ -330,9 +330,9 @@ def test_ldmul_large(self):
def test_ldmul_sparse(self, mat_s, l1d):
assert issparse(mat_s)
a = ldmul(l1d, mat_s)
b = np.diag(l1d) @ mat_s.A
b = np.diag(l1d) @ mat_s.toarray()
assert issparse(a)
assert_allclose(a.A, b)
assert_allclose(a.toarray(), b)

def test_rdmul_small(self, mat_d, l1d):
a = rdmul(mat_d, l1d)
Expand All @@ -350,9 +350,9 @@ def test_rdmul_large(self):

def test_rdmul_sparse(self, mat_s, l1d):
a = rdmul(mat_s, l1d)
b = mat_s.A @ np.diag(l1d)
b = mat_s.toarray() @ np.diag(l1d)
assert issparse(a)
assert_allclose(a.A, b)
assert_allclose(a.toarray(), b)


class TestOuter:
Expand Down Expand Up @@ -412,8 +412,14 @@ def test_kron_multi_args(self, mat_d, mat_d2, mat_d3):
)

def test_kron_mixed_types(self, mat_d, mat_s):
assert_allclose(kron(mat_d, mat_s).A, (sp.kron(mat_d, mat_s, "csr")).A)
assert_allclose(kron(mat_s, mat_s).A, (sp.kron(mat_s, mat_s, "csr")).A)
assert_allclose(
kron(mat_d, mat_s).toarray(),
(sp.kron(mat_d, mat_s, "csr")).toarray(),
)
assert_allclose(
kron(mat_s, mat_s).toarray(),
(sp.kron(mat_s, mat_s, "csr")).toarray(),
)


class TestKronSparseFormats:
Expand Down Expand Up @@ -476,14 +482,14 @@ def test_dense(self, mat_d):
def test_sparse(self, mat_s):
x = mat_s & mat_s & mat_s
y = kronpow(mat_s, 3)
assert_allclose(x.A, y.A)
assert_allclose(x.toarray(), y.toarray())

@mark.parametrize("stype", _SPARSE_FORMATS)
def test_sparse_formats(self, stype, mat_s):
x = mat_s & mat_s & mat_s
y = kronpow(mat_s, 3, stype=stype)
assert y.format == stype
assert_allclose(x.A, y.A)
assert_allclose(x.toarray(), y.toarray())

@mark.parametrize("sformat_in", _SPARSE_FORMATS)
@mark.parametrize("stype", (None,) + _SPARSE_FORMATS)
Expand All @@ -492,4 +498,4 @@ def test_sparse_formats_coo_construct(self, sformat_in, stype, mat_s):
x = mat_s & mat_s & mat_s
y = kronpow(mat_s, 3, stype=stype, coo_build=True)
assert y.format == stype if stype is not None else "sformat_in"
assert_allclose(x.A, y.A)
assert_allclose(x.toarray(), y.toarray())
Loading

0 comments on commit e05b77e

Please sign in to comment.