scikit-sparse 0.5.0__tar.gz → 0.5.1__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.
- {scikit_sparse-0.5.0/src/scikit_sparse.egg-info → scikit_sparse-0.5.1}/PKG-INFO +2 -2
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/pyproject.toml +2 -2
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1/src/scikit_sparse.egg-info}/PKG-INFO +2 -2
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/scikit_sparse.egg-info/requires.txt +1 -1
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/cholmod.pxd +5 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/cholmod.pyx +102 -69
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/utils.py +9 -1
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/LICENSE.txt +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/MANIFEST.in +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/README.rst +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/setup.cfg +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/setup.py +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/scikit_sparse.egg-info/SOURCES.txt +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/scikit_sparse.egg-info/dependency_links.txt +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/scikit_sparse.egg-info/top_level.txt +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/__init__.py +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/amd.pxd +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/amd.pyx +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/btf.pxd +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/btf.pyx +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/camd.pxd +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/camd.pyx +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/ccolamd.pxd +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/ccolamd.pyx +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/colamd.pxd +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/colamd.pyx +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/klu.pxd +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/klu.pyx +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/spqr.pxd +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/spqr.pyx +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/umfpack.pxd +0 -0
- {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/umfpack.pyx +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scikit-sparse
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Scikit-sparse is a Python wrapper for the SuiteSparse sparse matrix library.
|
|
5
5
|
Author-email: David Cournapeau <cournape@gmail.com>, Nathaniel Smith <njs@pobox.com>, Dag Sverre Seljebotn <dagss@student.matnat.uio.no>, Leon Barrett <lbarrett@climate.com>, Yuri <yuri@tsoft.com>, Antony Lee <anntzer.lee@gmail.com>, Alex Grigorievskiy <alex.grigorievskiy@gmail.com>, Joscha Reimer <jor@informatik.uni-kiel.de>, Justin Ellis <justin.ellis18@gmail.com>, Aaron Johnson <aaron9035@gmail.com>, Bernard Roesler <bernard.roesler@gmail.com>
|
|
6
6
|
Maintainer-email: Bernard Roesler <bernard.roesler@gmail.com>
|
|
@@ -30,7 +30,7 @@ Provides-Extra: dev
|
|
|
30
30
|
Requires-Dist: build; extra == "dev"
|
|
31
31
|
Requires-Dist: pre-commit; extra == "dev"
|
|
32
32
|
Requires-Dist: pytest; extra == "dev"
|
|
33
|
-
Requires-Dist: ruff; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff==0.14.3; extra == "dev"
|
|
34
34
|
Requires-Dist: sphinx; extra == "dev"
|
|
35
35
|
Requires-Dist: furo; extra == "dev"
|
|
36
36
|
Requires-Dist: sphinx-copybutton; extra == "dev"
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "scikit-sparse"
|
|
8
|
-
version = "0.5.
|
|
8
|
+
version = "0.5.1"
|
|
9
9
|
description = "Scikit-sparse is a Python wrapper for the SuiteSparse sparse matrix library."
|
|
10
10
|
readme = "README.rst"
|
|
11
11
|
requires-python = ">=3.10"
|
|
@@ -56,7 +56,7 @@ dev = [
|
|
|
56
56
|
"build",
|
|
57
57
|
"pre-commit",
|
|
58
58
|
"pytest",
|
|
59
|
-
"ruff",
|
|
59
|
+
"ruff==0.14.3",
|
|
60
60
|
"sphinx",
|
|
61
61
|
"furo",
|
|
62
62
|
"sphinx-copybutton",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scikit-sparse
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Scikit-sparse is a Python wrapper for the SuiteSparse sparse matrix library.
|
|
5
5
|
Author-email: David Cournapeau <cournape@gmail.com>, Nathaniel Smith <njs@pobox.com>, Dag Sverre Seljebotn <dagss@student.matnat.uio.no>, Leon Barrett <lbarrett@climate.com>, Yuri <yuri@tsoft.com>, Antony Lee <anntzer.lee@gmail.com>, Alex Grigorievskiy <alex.grigorievskiy@gmail.com>, Joscha Reimer <jor@informatik.uni-kiel.de>, Justin Ellis <justin.ellis18@gmail.com>, Aaron Johnson <aaron9035@gmail.com>, Bernard Roesler <bernard.roesler@gmail.com>
|
|
6
6
|
Maintainer-email: Bernard Roesler <bernard.roesler@gmail.com>
|
|
@@ -30,7 +30,7 @@ Provides-Extra: dev
|
|
|
30
30
|
Requires-Dist: build; extra == "dev"
|
|
31
31
|
Requires-Dist: pre-commit; extra == "dev"
|
|
32
32
|
Requires-Dist: pytest; extra == "dev"
|
|
33
|
-
Requires-Dist: ruff; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff==0.14.3; extra == "dev"
|
|
34
34
|
Requires-Dist: sphinx; extra == "dev"
|
|
35
35
|
Requires-Dist: furo; extra == "dev"
|
|
36
36
|
Requires-Dist: sphinx-copybutton; extra == "dev"
|
|
@@ -112,6 +112,7 @@ import numpy as np
|
|
|
112
112
|
|
|
113
113
|
from scipy.sparse import csc_array, diags_array, eye_array, issparse
|
|
114
114
|
import warnings
|
|
115
|
+
import weakref
|
|
115
116
|
|
|
116
117
|
from .utils import validate_csc_input
|
|
117
118
|
|
|
@@ -955,47 +956,6 @@ cdef cnp.ndarray _ndarray_copy_from_intptr(void* ptr, size_t N, bint use_int32):
|
|
|
955
956
|
return p.copy() # return a copy in case ptr is freed
|
|
956
957
|
|
|
957
958
|
|
|
958
|
-
cdef cnp.ndarray _ndarray_int_view_from_factor(
|
|
959
|
-
void* ptr, size_t N, CholeskyFactor py_factor
|
|
960
|
-
):
|
|
961
|
-
"""Create a NumPy array from the an integer vector in a CHOLMOD factor.
|
|
962
|
-
|
|
963
|
-
Parameters
|
|
964
|
-
----------
|
|
965
|
-
ptr : void*
|
|
966
|
-
A pointer to the C array, *e.g.* ``cholmod_factor.Perm``.
|
|
967
|
-
N : size_t
|
|
968
|
-
The size of the vector.
|
|
969
|
-
py_factor : CholeskyFactor
|
|
970
|
-
The CholeskyFactor object from which to extract the permutation.
|
|
971
|
-
|
|
972
|
-
Returns
|
|
973
|
-
-------
|
|
974
|
-
p : ndarray
|
|
975
|
-
The permutation vector as a NumPy array. This array is *read-only*,
|
|
976
|
-
so attempts to modify it will raise an error.
|
|
977
|
-
"""
|
|
978
|
-
cdef cholmod_factor *L = py_factor._factor
|
|
979
|
-
|
|
980
|
-
if L is NULL:
|
|
981
|
-
raise ValueError("The factor pointer is NULL.")
|
|
982
|
-
|
|
983
|
-
if ptr is NULL:
|
|
984
|
-
raise ValueError("The input pointer is NULL.")
|
|
985
|
-
|
|
986
|
-
cdef int np_itypenum = _np_itypenum_from_cholmod(L.itype)
|
|
987
|
-
p = cnp.PyArray_SimpleNewFromData(1, [N], np_itypenum, ptr)
|
|
988
|
-
|
|
989
|
-
# NOTE need to increment reference count of base manually,
|
|
990
|
-
# since the PyArray_SetBaseObject steals a reference.
|
|
991
|
-
Py_INCREF(py_factor)
|
|
992
|
-
if cnp.PyArray_SetBaseObject(p, py_factor) < 0:
|
|
993
|
-
raise MemoryError("Failed to set base object for array.")
|
|
994
|
-
cnp.PyArray_CLEARFLAGS(p, cnp.NPY_ARRAY_WRITEABLE) # set to be read-only
|
|
995
|
-
|
|
996
|
-
return p
|
|
997
|
-
|
|
998
|
-
|
|
999
959
|
# -----------------------------------------------------------------------------
|
|
1000
960
|
# Utilities
|
|
1001
961
|
# -----------------------------------------------------------------------------
|
|
@@ -1332,7 +1292,7 @@ cdef class CholeskyFactor:
|
|
|
1332
1292
|
The ordering method used for the factorization. If an unknown ordering
|
|
1333
1293
|
was used, returns the integer value.
|
|
1334
1294
|
perm : *(N,)* :obj:`numpy.ndarray` of int
|
|
1335
|
-
A read-only
|
|
1295
|
+
A read-only copy of the permutation vector used for the factorization.
|
|
1336
1296
|
factor : :obj:`~scipy.sparse.csc_array`
|
|
1337
1297
|
A view of the the Cholesky factor in Compressed Sparse Column (CSC)
|
|
1338
1298
|
format. If ``self.is_ll``, the returned matrix is lower triangular.
|
|
@@ -1407,6 +1367,7 @@ cdef class CholeskyFactor:
|
|
|
1407
1367
|
# Cached factors
|
|
1408
1368
|
cnp.ndarray _perm
|
|
1409
1369
|
cnp.ndarray _colcount
|
|
1370
|
+
object _pattern
|
|
1410
1371
|
object _L
|
|
1411
1372
|
object _R
|
|
1412
1373
|
object _D
|
|
@@ -1508,6 +1469,10 @@ cdef class CholeskyFactor:
|
|
|
1508
1469
|
cdef int minor = -1 if self._factor is NULL else self._factor.minor
|
|
1509
1470
|
_handle_errors(self._cm.status, minor)
|
|
1510
1471
|
|
|
1472
|
+
# The supernodal algorithm requires A to have the analyzed pattern
|
|
1473
|
+
if self._factor.is_super:
|
|
1474
|
+
self._pattern = (A.shape, A.indptr.copy(), A.indices.copy())
|
|
1475
|
+
|
|
1511
1476
|
def __dealloc__(self):
|
|
1512
1477
|
"""Deallocate memory used by the CholeskyFactor."""
|
|
1513
1478
|
if self._use_int32:
|
|
@@ -1522,6 +1487,23 @@ cdef class CholeskyFactor:
|
|
|
1522
1487
|
if not self.is_numeric:
|
|
1523
1488
|
raise CholmodError("Factor is symbolic. Call `factorize` before updating.")
|
|
1524
1489
|
|
|
1490
|
+
cdef int _to_simplicial(self) except -1:
|
|
1491
|
+
"""Convert the factor to simplicial format, keeping its values."""
|
|
1492
|
+
cdef cholmod_factor *L = self._factor
|
|
1493
|
+
if self._use_int32:
|
|
1494
|
+
cholmod_change_factor(L.xtype, L.is_ll, False, True, True, L, self._cm)
|
|
1495
|
+
else:
|
|
1496
|
+
cholmod_l_change_factor(L.xtype, L.is_ll, False, True, True, L, self._cm)
|
|
1497
|
+
return _handle_errors(self._cm.status)
|
|
1498
|
+
|
|
1499
|
+
cdef bint _has_pattern(self, object A) except -1:
|
|
1500
|
+
"""Check whether A has the analyzed (supernodal) sparsity pattern."""
|
|
1501
|
+
return self._pattern is not None and (
|
|
1502
|
+
A.shape == self._pattern[0]
|
|
1503
|
+
and np.array_equal(A.indptr, self._pattern[1])
|
|
1504
|
+
and np.array_equal(A.indices, self._pattern[2])
|
|
1505
|
+
)
|
|
1506
|
+
|
|
1525
1507
|
def _clear_cache(self):
|
|
1526
1508
|
"""Clear cached properties."""
|
|
1527
1509
|
self._factor_view = None
|
|
@@ -1590,9 +1572,10 @@ cdef class CholeskyFactor:
|
|
|
1590
1572
|
@property
|
|
1591
1573
|
def colcount(self):
|
|
1592
1574
|
if self._colcount is None:
|
|
1593
|
-
self._colcount =
|
|
1594
|
-
self._factor.ColCount, self._factor.n, self
|
|
1575
|
+
self._colcount = _ndarray_copy_from_intptr(
|
|
1576
|
+
self._factor.ColCount, self._factor.n, self._use_int32
|
|
1595
1577
|
)
|
|
1578
|
+
self._colcount.flags.writeable = False
|
|
1596
1579
|
return self._colcount
|
|
1597
1580
|
|
|
1598
1581
|
@property
|
|
@@ -1607,14 +1590,21 @@ cdef class CholeskyFactor:
|
|
|
1607
1590
|
@property
|
|
1608
1591
|
def perm(self):
|
|
1609
1592
|
if self._perm is None:
|
|
1610
|
-
self._perm =
|
|
1593
|
+
self._perm = _ndarray_copy_from_intptr(
|
|
1594
|
+
self._factor.Perm, self._factor.n, self._use_int32
|
|
1595
|
+
)
|
|
1596
|
+
self._perm.flags.writeable = False
|
|
1611
1597
|
return self._perm
|
|
1612
1598
|
|
|
1613
1599
|
@property
|
|
1614
1600
|
def factor(self):
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1601
|
+
# NOTE cache a weak reference, since the view has self as its base,
|
|
1602
|
+
# and a reference cycle through a NumPy array is never garbage collected.
|
|
1603
|
+
Lv = None if self._factor_view is None else self._factor_view()
|
|
1604
|
+
if Lv is None:
|
|
1605
|
+
Lv = _csc_view_from_cholmod_factor(self)
|
|
1606
|
+
self._factor_view = weakref.ref(Lv)
|
|
1607
|
+
return Lv
|
|
1618
1608
|
|
|
1619
1609
|
@property
|
|
1620
1610
|
def L(self):
|
|
@@ -1687,6 +1677,7 @@ cdef class CholeskyFactor:
|
|
|
1687
1677
|
cf._stype = self._stype
|
|
1688
1678
|
cf.sym_kind = self.sym_kind
|
|
1689
1679
|
cf.rcond = self.rcond
|
|
1680
|
+
cf._pattern = self._pattern
|
|
1690
1681
|
|
|
1691
1682
|
return cf
|
|
1692
1683
|
|
|
@@ -1722,7 +1713,7 @@ cdef class CholeskyFactor:
|
|
|
1722
1713
|
self._clear_cache()
|
|
1723
1714
|
|
|
1724
1715
|
cdef int to_ll = (kind == "LL")
|
|
1725
|
-
cdef int to_super = self._factor.is_super
|
|
1716
|
+
cdef int to_super = self._factor.is_super and to_ll
|
|
1726
1717
|
cdef int to_packed = True
|
|
1727
1718
|
cdef int to_monotonic = self._factor.is_monotonic
|
|
1728
1719
|
|
|
@@ -1784,16 +1775,20 @@ cdef class CholeskyFactor:
|
|
|
1784
1775
|
if lower is None:
|
|
1785
1776
|
lower = self.is_lower
|
|
1786
1777
|
|
|
1778
|
+
# Convert a copy of the factor if needed, so that this one is unchanged
|
|
1779
|
+
same_kind = self.is_ll == (kind == "LL")
|
|
1780
|
+
cf = self if same_kind and not self.is_super else self.copy()
|
|
1781
|
+
|
|
1787
1782
|
# Drop explicit zeros from returned copies
|
|
1788
1783
|
if kind == "LL":
|
|
1789
|
-
L = _csc_view_from_cholmod_factor(
|
|
1784
|
+
L = _csc_view_from_cholmod_factor(cf, ldl=False).copy()
|
|
1790
1785
|
L.eliminate_zeros()
|
|
1791
1786
|
if not lower:
|
|
1792
1787
|
L = L.T.conj()
|
|
1793
1788
|
return L
|
|
1794
1789
|
else:
|
|
1795
1790
|
# Extract L and D from combined LD factor
|
|
1796
|
-
L = _csc_view_from_cholmod_factor(
|
|
1791
|
+
L = _csc_view_from_cholmod_factor(cf, ldl=True).copy()
|
|
1797
1792
|
D = diags_array(L.diagonal())
|
|
1798
1793
|
L.setdiag(1.0)
|
|
1799
1794
|
L.eliminate_zeros()
|
|
@@ -1887,7 +1882,17 @@ cdef class CholeskyFactor:
|
|
|
1887
1882
|
"""
|
|
1888
1883
|
assert self._factor is not NULL, "The factor has not been initialized."
|
|
1889
1884
|
|
|
1890
|
-
|
|
1885
|
+
# Skip validation of a matrix with exactly the analyzed pattern, which
|
|
1886
|
+
# is canonical, as is common when refactorizing
|
|
1887
|
+
cdef bint same_pattern = (
|
|
1888
|
+
issparse(A) and A.format == "csc" and A.dtype.kind in "fc"
|
|
1889
|
+
and A.indptr.dtype == A.indices.dtype == self.itype
|
|
1890
|
+
and A.data.shape == A.indices.shape and A.data.flags.c_contiguous
|
|
1891
|
+
and self._has_pattern(A)
|
|
1892
|
+
)
|
|
1893
|
+
if not same_pattern:
|
|
1894
|
+
A, _, _ = validate_csc_input(A, ensure_double=False, itype=self.itype)
|
|
1895
|
+
same_pattern = self._has_pattern(A)
|
|
1891
1896
|
|
|
1892
1897
|
if ldl is None:
|
|
1893
1898
|
if self.is_numeric:
|
|
@@ -1898,12 +1903,26 @@ cdef class CholeskyFactor:
|
|
|
1898
1903
|
if not isinstance(ldl, bool):
|
|
1899
1904
|
raise ValueError("ldl must be a boolean value.")
|
|
1900
1905
|
|
|
1906
|
+
# Check A as CHOLMOD does, since CHOLMOD may change the factor (e.g.,
|
|
1907
|
+
# is_ll) before it rejects A, and the factor is converted below
|
|
1908
|
+
n = A.shape[1] if self.sym_kind == "col" else A.shape[0]
|
|
1909
|
+
if n != self.N or (self._stype != 0 and A.shape[0] != A.shape[1]) or (
|
|
1910
|
+
self.is_numeric and A.dtype != self.dtype
|
|
1911
|
+
):
|
|
1912
|
+
raise CholmodInvalidInputError("A does not match the factor.")
|
|
1913
|
+
|
|
1901
1914
|
# Clear cached properties
|
|
1902
1915
|
self._clear_cache()
|
|
1903
1916
|
|
|
1917
|
+
# A supernodal factor is LL.T only, and silently gives a wrong result
|
|
1918
|
+
# for a matrix outside of the analyzed pattern, so use the simplicial
|
|
1919
|
+
# algorithm instead.
|
|
1920
|
+
if self._factor.is_super and ((ldl and self.is_numeric) or not same_pattern):
|
|
1921
|
+
self._to_simplicial()
|
|
1922
|
+
|
|
1904
1923
|
# See CHOLMOD/MATLAB/ldlchol.c and/or lchol.c for details
|
|
1905
1924
|
self._cm.final_asis = False
|
|
1906
|
-
self._cm.final_super =
|
|
1925
|
+
self._cm.final_super = not ldl # keep a supernodal LL.T factor
|
|
1907
1926
|
self._cm.final_ll = not ldl # LL.T for Cholesky, LDL.T for LDL
|
|
1908
1927
|
self._cm.final_pack = True
|
|
1909
1928
|
self._cm.final_monotonic = True
|
|
@@ -2109,7 +2128,7 @@ cdef class CholeskyFactor:
|
|
|
2109
2128
|
|
|
2110
2129
|
cdef int stype = 0
|
|
2111
2130
|
|
|
2112
|
-
b, _, _ = validate_csc_input(b, ensure_double=False)
|
|
2131
|
+
b, _, _ = validate_csc_input(b, ensure_double=False, itype=self.itype)
|
|
2113
2132
|
|
|
2114
2133
|
_cholmod_sparse_from_csc(
|
|
2115
2134
|
b.shape, b.indptr, b.indices, b.data, stype, <uintptr_t>&Bspmatrix
|
|
@@ -2203,7 +2222,7 @@ cdef class CholeskyFactor:
|
|
|
2203
2222
|
C = C.reshape((-1, 1)).tocsc() # (N, 1)
|
|
2204
2223
|
|
|
2205
2224
|
cdef int stype = 0 # use all of C
|
|
2206
|
-
C, _, _ = validate_csc_input(C, ensure_double=False)
|
|
2225
|
+
C, _, _ = validate_csc_input(C, ensure_double=False, itype=self.itype)
|
|
2207
2226
|
|
|
2208
2227
|
cdef cholmod_sparse Cmatrix
|
|
2209
2228
|
cdef cholmod_sparse* Cc = &Cmatrix
|
|
@@ -2256,6 +2275,7 @@ cdef class CholeskyFactor:
|
|
|
2256
2275
|
cholmod_l_free_sparse(&C_perm, self._cm)
|
|
2257
2276
|
|
|
2258
2277
|
if not ok:
|
|
2278
|
+
_handle_errors(self._cm.status)
|
|
2259
2279
|
raise CholmodError("Update or downdate failed.")
|
|
2260
2280
|
|
|
2261
2281
|
return self
|
|
@@ -2313,7 +2333,7 @@ cdef class CholeskyFactor:
|
|
|
2313
2333
|
if C.ndim == 1:
|
|
2314
2334
|
C = C.reshape((-1, 1)).tocsc() # (N, 1)
|
|
2315
2335
|
|
|
2316
|
-
C, _, _ = validate_csc_input(C, ensure_double=False)
|
|
2336
|
+
C, _, _ = validate_csc_input(C, ensure_double=False, itype=self.itype)
|
|
2317
2337
|
_cholmod_sparse_from_csc(
|
|
2318
2338
|
C.shape, C.indptr, C.indices, C.data, stype, <uintptr_t>&Cmatrix
|
|
2319
2339
|
)
|
|
@@ -2327,6 +2347,7 @@ cdef class CholeskyFactor:
|
|
|
2327
2347
|
ok = cholmod_l_rowadd(k, Cc, self._factor, self._cm)
|
|
2328
2348
|
|
|
2329
2349
|
if not ok:
|
|
2350
|
+
_handle_errors(self._cm.status)
|
|
2330
2351
|
raise CholmodError("cholmod_rowadd failed.")
|
|
2331
2352
|
|
|
2332
2353
|
return self
|
|
@@ -2368,6 +2389,7 @@ cdef class CholeskyFactor:
|
|
|
2368
2389
|
ok = cholmod_l_rowdel(k, NULL, self._factor, self._cm)
|
|
2369
2390
|
|
|
2370
2391
|
if not ok:
|
|
2392
|
+
_handle_errors(self._cm.status)
|
|
2371
2393
|
raise CholmodError("cholmod_rowdel failed.")
|
|
2372
2394
|
|
|
2373
2395
|
return self
|
|
@@ -2416,21 +2438,16 @@ cdef class CholeskyFactor:
|
|
|
2416
2438
|
"""
|
|
2417
2439
|
self._require_factorized()
|
|
2418
2440
|
|
|
2419
|
-
cdef bint A_use_int32
|
|
2420
2441
|
# TODO support non-square matrices with sym_kind='row'
|
|
2421
|
-
A,
|
|
2442
|
+
A, _, _ = validate_csc_input(
|
|
2443
|
+
A, require_square=True, ensure_double=False, itype=self.itype
|
|
2444
|
+
)
|
|
2422
2445
|
|
|
2423
2446
|
if A.shape[0] != self.N:
|
|
2424
2447
|
raise ValueError(
|
|
2425
2448
|
"Input matrix A must have the same number of rows as L."
|
|
2426
2449
|
)
|
|
2427
2450
|
|
|
2428
|
-
if self._use_int32 and not A_use_int32:
|
|
2429
|
-
raise ValueError(
|
|
2430
|
-
"A and factor must have the same integer type. "
|
|
2431
|
-
f"Got {A.indptr.dtype=}, but {self._use_int32=}."
|
|
2432
|
-
)
|
|
2433
|
-
|
|
2434
2451
|
# Special Cases
|
|
2435
2452
|
if self.N == 0:
|
|
2436
2453
|
return self
|
|
@@ -2441,6 +2458,8 @@ cdef class CholeskyFactor:
|
|
|
2441
2458
|
# Clear cached properties
|
|
2442
2459
|
self._clear_cache()
|
|
2443
2460
|
|
|
2461
|
+
self._to_simplicial() # CHOLMOD cannot resymbol a supernodal factor
|
|
2462
|
+
|
|
2444
2463
|
# Get sparse *pattern*
|
|
2445
2464
|
cdef cholmod_sparse Amatrix
|
|
2446
2465
|
cdef cholmod_sparse* Ac = &Amatrix
|
|
@@ -2466,6 +2485,7 @@ cdef class CholeskyFactor:
|
|
|
2466
2485
|
else:
|
|
2467
2486
|
cholmod_l_resymbol(Ac, NULL, 0, True, self._factor, self._cm)
|
|
2468
2487
|
|
|
2488
|
+
_handle_errors(self._cm.status)
|
|
2469
2489
|
return self
|
|
2470
2490
|
|
|
2471
2491
|
def logdet(self):
|
|
@@ -2502,12 +2522,25 @@ cdef class CholeskyFactor:
|
|
|
2502
2522
|
.. versionadded:: 0.2
|
|
2503
2523
|
"""
|
|
2504
2524
|
self._require_factorized()
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2525
|
+
cdef cholmod_factor *L = self._factor
|
|
2526
|
+
cdef int it = _np_itypenum_from_cholmod(L.itype)
|
|
2527
|
+
cdef int dt = _np_dtypenum_from_cholmod(L.xtype, L.dtype)
|
|
2528
|
+
# The diagonal of L (or D) is the first entry of each column of
|
|
2529
|
+
# a simplicial factor. A supernodal factor stores each supernode as
|
|
2530
|
+
# a dense column-major block with nsrow rows. See cholmod_rcond.c.
|
|
2531
|
+
if L.is_super:
|
|
2532
|
+
S = cnp.PyArray_SimpleNewFromData(1, [L.nsuper + 1], it, L.super)
|
|
2533
|
+
pi = cnp.PyArray_SimpleNewFromData(1, [L.nsuper + 1], it, L.pi)
|
|
2534
|
+
px = cnp.PyArray_SimpleNewFromData(1, [L.nsuper + 1], it, L.px)
|
|
2535
|
+
x = cnp.PyArray_SimpleNewFromData(1, [L.xsize], dt, L.x)
|
|
2536
|
+
s = np.repeat(np.arange(L.nsuper), np.diff(S))
|
|
2537
|
+
j = np.arange(L.n) - S[s]
|
|
2538
|
+
d = x[px[s] + j * (np.diff(pi)[s] + 1)]
|
|
2508
2539
|
else:
|
|
2509
|
-
|
|
2510
|
-
|
|
2540
|
+
Lp = cnp.PyArray_SimpleNewFromData(1, [L.n + 1], it, L.p)
|
|
2541
|
+
x = cnp.PyArray_SimpleNewFromData(1, [L.nzmax], dt, L.x)
|
|
2542
|
+
d = x[Lp[:-1]]
|
|
2543
|
+
return (2 if self.is_ll else 1) * np.sum(np.log(d))
|
|
2511
2544
|
|
|
2512
2545
|
def slogdet(self):
|
|
2513
2546
|
"""Compute the sign and (natural) log-determinant of the matrix from
|
|
@@ -20,7 +20,7 @@ from scipy.sparse import SparseEfficiencyWarning, csc_array, issparse
|
|
|
20
20
|
_HAS_SCIPY_SORT_BUG = version.parse(scipy_version) < version.parse("1.17.0")
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
def validate_csc_input(A, require_square=False, ensure_double=True):
|
|
23
|
+
def validate_csc_input(A, require_square=False, ensure_double=True, itype=None):
|
|
24
24
|
"""Validate and convert input matrix to CSC format.
|
|
25
25
|
|
|
26
26
|
Integer and boolean data types are converted to float32 by default.
|
|
@@ -39,6 +39,8 @@ def validate_csc_input(A, require_square=False, ensure_double=True):
|
|
|
39
39
|
Otherwise, it will retain its original floating-point precision
|
|
40
40
|
(float32 or complex64), or the minimum precision required to convert
|
|
41
41
|
integer or boolean types.
|
|
42
|
+
itype : dtype, optional
|
|
43
|
+
If given, the index arrays are converted to this integer type.
|
|
42
44
|
|
|
43
45
|
Returns
|
|
44
46
|
-------
|
|
@@ -114,6 +116,12 @@ def validate_csc_input(A, require_square=False, ensure_double=True):
|
|
|
114
116
|
if not (A.has_sorted_indices and A.has_canonical_format):
|
|
115
117
|
raise ValueError("Failed to convert input to canonical CSC format.")
|
|
116
118
|
|
|
119
|
+
# NOTE set the index arrays after construction, since the constructor
|
|
120
|
+
# may choose a different index type.
|
|
121
|
+
if itype is not None and not (A.indptr.dtype == A.indices.dtype == itype):
|
|
122
|
+
A = csc_array((A.data, A.indices, A.indptr), shape=A.shape)
|
|
123
|
+
A.indptr, A.indices = A.indptr.astype(itype), A.indices.astype(itype)
|
|
124
|
+
|
|
117
125
|
# Choose index width: int32 or int64
|
|
118
126
|
use_int32 = A.indptr.dtype == np.int32 and A.indices.dtype == np.int32
|
|
119
127
|
out_itype = np.dtype(np.int32 if use_int32 else np.int64)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|