multipers 2.3.0__cp310-cp310-win_amd64.whl → 2.3.2b1__cp310-cp310-win_amd64.whl
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.
Potentially problematic release.
This version of multipers might be problematic. Click here for more details.
- multipers/_signed_measure_meta.py +71 -65
- multipers/array_api/__init__.py +39 -0
- multipers/array_api/numpy.py +34 -0
- multipers/array_api/torch.py +35 -0
- multipers/distances.py +6 -2
- multipers/{ml/convolutions.py → filtrations/density.py} +67 -13
- multipers/filtrations/filtrations.py +76 -17
- multipers/function_rips.cp310-win_amd64.pyd +0 -0
- multipers/grids.cp310-win_amd64.pyd +0 -0
- multipers/grids.pyx +144 -61
- multipers/gudhi/Simplex_tree_multi_interface.h +36 -1
- multipers/gudhi/gudhi/Multi_persistence/Box.h +3 -0
- multipers/gudhi/gudhi/One_critical_filtration.h +18 -9
- multipers/gudhi/mma_interface_h0.h +1 -1
- multipers/gudhi/mma_interface_matrix.h +10 -1
- multipers/gudhi/naive_merge_tree.h +1 -1
- multipers/gudhi/truc.h +555 -42
- multipers/io.cp310-win_amd64.pyd +0 -0
- multipers/io.pyx +26 -93
- multipers/ml/mma.py +3 -3
- multipers/ml/point_clouds.py +2 -2
- multipers/ml/signed_measures.py +63 -65
- multipers/mma_structures.cp310-win_amd64.pyd +0 -0
- multipers/mma_structures.pxd +2 -1
- multipers/mma_structures.pyx +56 -16
- multipers/mma_structures.pyx.tp +14 -5
- multipers/multiparameter_module_approximation/approximation.h +48 -14
- multipers/multiparameter_module_approximation.cp310-win_amd64.pyd +0 -0
- multipers/multiparameter_module_approximation.pyx +25 -7
- multipers/plots.py +2 -1
- multipers/point_measure.cp310-win_amd64.pyd +0 -0
- multipers/point_measure.pyx +6 -2
- multipers/simplex_tree_multi.cp310-win_amd64.pyd +0 -0
- multipers/simplex_tree_multi.pxd +1 -0
- multipers/simplex_tree_multi.pyx +584 -142
- multipers/simplex_tree_multi.pyx.tp +80 -23
- multipers/slicer.cp310-win_amd64.pyd +0 -0
- multipers/slicer.pxd +799 -197
- multipers/slicer.pxd.tp +24 -5
- multipers/slicer.pyx +5653 -1426
- multipers/slicer.pyx.tp +208 -48
- multipers/tbb12.dll +0 -0
- multipers/tbbbind_2_5.dll +0 -0
- multipers/tbbmalloc.dll +0 -0
- multipers/tbbmalloc_proxy.dll +0 -0
- multipers/tensor/tensor.h +1 -1
- multipers/tests/__init__.py +9 -4
- multipers/torch/diff_grids.py +30 -7
- multipers/torch/rips_density.py +1 -1
- {multipers-2.3.0.dist-info → multipers-2.3.2b1.dist-info}/METADATA +4 -25
- {multipers-2.3.0.dist-info → multipers-2.3.2b1.dist-info}/RECORD +54 -51
- {multipers-2.3.0.dist-info → multipers-2.3.2b1.dist-info}/WHEEL +1 -1
- {multipers-2.3.0.dist-info → multipers-2.3.2b1.dist-info/licenses}/LICENSE +0 -0
- {multipers-2.3.0.dist-info → multipers-2.3.2b1.dist-info}/top_level.txt +0 -0
|
@@ -66,7 +66,8 @@ cimport cython
|
|
|
66
66
|
from gudhi.simplex_tree import SimplexTree ## Small hack for typing
|
|
67
67
|
from typing import Iterable,Literal,Optional
|
|
68
68
|
from tqdm import tqdm
|
|
69
|
-
from multipers.grids import Lstrategies, compute_grid
|
|
69
|
+
from multipers.grids import Lstrategies, compute_grid, sanitize_grid
|
|
70
|
+
from multipers.array_api import api_from_tensor
|
|
70
71
|
from multipers.point_measure import signed_betti, rank_decomposition_by_rectangles, sparsify
|
|
71
72
|
|
|
72
73
|
from warnings import warn
|
|
@@ -98,15 +99,15 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
98
99
|
"""
|
|
99
100
|
cdef public intptr_t thisptr
|
|
100
101
|
|
|
101
|
-
cdef public
|
|
102
|
-
cdef public bool _is_function_simplextree
|
|
102
|
+
cdef public object filtration_grid
|
|
103
|
+
cdef public bool _is_function_simplextree # TODO : deprecate
|
|
103
104
|
# Get the pointer casted as it should be
|
|
104
105
|
cdef Simplex_tree_multi_interface[{{FSHORT}}, {{CTYPE}}]* get_ptr(self) noexcept nogil:
|
|
105
106
|
return <Simplex_tree_multi_interface[{{FSHORT}}, {{CTYPE}}]*>(self.thisptr)
|
|
106
107
|
|
|
107
108
|
# cdef Simplex_tree_persistence_interface * pcohptr
|
|
108
109
|
# Fake constructor that does nothing but documenting the constructor
|
|
109
|
-
def __init__(self, other = None, num_parameters:int
|
|
110
|
+
def __init__(self, other = None, num_parameters:int=-1,default_values=[], safe_conversion=False):
|
|
110
111
|
"""SimplexTreeMulti constructor.
|
|
111
112
|
|
|
112
113
|
:param other: If `other` is `None` (default value), an empty `SimplexTreeMulti` is created.
|
|
@@ -139,7 +140,7 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
139
140
|
def is_kcritical(self)->bool:
|
|
140
141
|
return {{is_kcritical}}
|
|
141
142
|
# The real cython constructor
|
|
142
|
-
def __cinit__(self, other = None, int num_parameters
|
|
143
|
+
def __cinit__(self, other = None, int num_parameters=-1,
|
|
143
144
|
default_values=np.asarray([SimplexTreeMulti_{{FSHORT}}.T_minus_inf()]), # I'm not sure why `[]` does not work. Cython bug ?
|
|
144
145
|
bool safe_conversion=False,
|
|
145
146
|
): #TODO doc
|
|
@@ -156,10 +157,13 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
156
157
|
if isinstance(other, SimplexTreeMulti_{{FSHORT}}):
|
|
157
158
|
other_ptr = other.thisptr
|
|
158
159
|
self.thisptr = <intptr_t>(new Simplex_tree_multi_interface[{{FSHORT}}, {{CTYPE}}](dereference(<Simplex_tree_multi_interface[{{FSHORT}}, {{CTYPE}}]*>other_ptr))) ## prevents calling destructor of other
|
|
159
|
-
num_parameters
|
|
160
|
+
if num_parameters <=0:
|
|
161
|
+
num_parameters = other.num_parameters
|
|
160
162
|
self.filtration_grid = other.filtration_grid
|
|
161
163
|
elif isinstance(other, SimplexTree): # Constructs a SimplexTreeMulti from a SimplexTree
|
|
162
164
|
self.thisptr = <intptr_t>(new Simplex_tree_multi_interface[{{FSHORT}}, {{CTYPE}}]())
|
|
165
|
+
if num_parameters <= 0:
|
|
166
|
+
num_parameters = 1
|
|
163
167
|
if safe_conversion or SAFE_CONVERSION:
|
|
164
168
|
new_st_multi = _safe_simplextree_multify_{{FSHORT}}(other, num_parameters = num_parameters, default_values=np.asarray(default_values))
|
|
165
169
|
self.thisptr, new_st_multi.thisptr = new_st_multi.thisptr, self.thisptr
|
|
@@ -174,10 +178,12 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
174
178
|
else:
|
|
175
179
|
raise TypeError("`other` argument requires to be of type `SimplexTree`, `SimplexTreeMulti`, or `None`.")
|
|
176
180
|
else:
|
|
181
|
+
if num_parameters <=0:
|
|
182
|
+
num_parameters = 2 # I don't know how dangerous this is, but this is mostly used.
|
|
177
183
|
self.thisptr = <intptr_t>(new Simplex_tree_multi_interface[{{FSHORT}}, {{CTYPE}}]())
|
|
178
|
-
self.
|
|
184
|
+
self.set_num_parameter(num_parameters)
|
|
179
185
|
self._is_function_simplextree = False
|
|
180
|
-
self.filtration_grid=[
|
|
186
|
+
self.filtration_grid=[]
|
|
181
187
|
|
|
182
188
|
def __dealloc__(self):
|
|
183
189
|
cdef Simplex_tree_multi_interface[{{FSHORT}},{{CTYPE}}]* ptr = self.get_ptr()
|
|
@@ -187,6 +193,9 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
187
193
|
|
|
188
194
|
def __repr__(self):
|
|
189
195
|
return f"SimplexTreeMulti[dtype={np.dtype(self.dtype).name},num_param={self.num_parameters},kcritical={self.is_kcritical},is_squeezed={self.is_squeezed},max_dim={self.dimension}]"
|
|
196
|
+
def __len__(self):
|
|
197
|
+
return self.num_simplices
|
|
198
|
+
|
|
190
199
|
def __getstate__(self):
|
|
191
200
|
""":returns: Serialized (or flattened) SimplexTree data structure in order to pickle SimplexTree.
|
|
192
201
|
:rtype: numpy.array of shape (n,)
|
|
@@ -1249,11 +1258,26 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
1249
1258
|
out = self.get_ptr().get_filtration_values(degrees)
|
|
1250
1259
|
filtrations_values = [np.asarray(filtration) for filtration in out]
|
|
1251
1260
|
# Removes infs
|
|
1252
|
-
if inf_to_nan:
|
|
1261
|
+
if inf_to_nan and np.dtype(filtrations_values[0].dtype).kind == 'f':
|
|
1253
1262
|
for i,f in enumerate(filtrations_values):
|
|
1254
1263
|
filtrations_values[i][f == np.inf] = np.nan
|
|
1255
1264
|
filtrations_values[i][f == - np.inf] = np.nan
|
|
1256
1265
|
return filtrations_values
|
|
1266
|
+
def _clean_filtration_grid(self):
|
|
1267
|
+
"""
|
|
1268
|
+
Removes the values in filtration_grid that are not linked to any splx.
|
|
1269
|
+
"""
|
|
1270
|
+
if not self.is_squeezed:
|
|
1271
|
+
raise ValueError("No grid to clean.")
|
|
1272
|
+
F = self.filtration_grid
|
|
1273
|
+
self.filtration_grid=None
|
|
1274
|
+
cleaned_coordinates = compute_grid(self)
|
|
1275
|
+
new_st = self.grid_squeeze(cleaned_coordinates)
|
|
1276
|
+
|
|
1277
|
+
self.thisptr, new_st.thisptr = new_st.thisptr, self.thisptr
|
|
1278
|
+
self.filtration_grid = tuple(f[g] for f,g in zip(F,cleaned_coordinates))
|
|
1279
|
+
return self
|
|
1280
|
+
|
|
1257
1281
|
|
|
1258
1282
|
|
|
1259
1283
|
def get_filtration_grid(self, resolution:Iterable[int]|None=None, degrees:Iterable[int]|None=None, drop_quantiles:float|tuple=0, grid_strategy:_available_strategies="exact")->Iterable[np.ndarray]:
|
|
@@ -1289,8 +1313,16 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
1289
1313
|
return compute_grid(filtrations_values, resolution=resolution,strategy=grid_strategy,drop_quantiles=drop_quantiles)
|
|
1290
1314
|
|
|
1291
1315
|
|
|
1292
|
-
|
|
1293
|
-
|
|
1316
|
+
def grid_squeeze(
|
|
1317
|
+
self,
|
|
1318
|
+
filtration_grid:np.ndarray|list|None=None,
|
|
1319
|
+
bool coordinate_values=True,
|
|
1320
|
+
force=False,
|
|
1321
|
+
strategy:_available_strategies = "exact",
|
|
1322
|
+
grid_strategy=None,
|
|
1323
|
+
inplace=False,
|
|
1324
|
+
**filtration_grid_kwargs
|
|
1325
|
+
)->SimplexTreeMulti_{{FSHORT[:-3] + "i32"}} | SimplexTreeMulti_{{FSHORT}}:
|
|
1294
1326
|
"""
|
|
1295
1327
|
Fit the filtration of the simplextree to a grid.
|
|
1296
1328
|
|
|
@@ -1301,26 +1333,50 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
1301
1333
|
"""
|
|
1302
1334
|
if not force and self.is_squeezed:
|
|
1303
1335
|
raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
|
|
1336
|
+
|
|
1337
|
+
if grid_strategy is not None:
|
|
1338
|
+
warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
|
|
1339
|
+
strategy=grid_strategy
|
|
1340
|
+
|
|
1341
|
+
if self.is_squeezed:
|
|
1342
|
+
warn("(copy warning) Squeezing an already squeezed slicer.")
|
|
1343
|
+
temp = self.unsqueeze()
|
|
1344
|
+
subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
|
|
1345
|
+
return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
|
|
1346
|
+
|
|
1304
1347
|
#TODO : multi-critical
|
|
1305
1348
|
if filtration_grid is None:
|
|
1306
|
-
filtration_grid = self.get_filtration_grid(grid_strategy=
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1349
|
+
filtration_grid = self.get_filtration_grid(grid_strategy=strategy, **filtration_grid_kwargs)
|
|
1350
|
+
else:
|
|
1351
|
+
filtration_grid = sanitize_grid(filtration_grid)
|
|
1352
|
+
if len(filtration_grid) != self.num_parameters:
|
|
1353
|
+
raise ValueError(f"Invalid grid to squeeze onto. Got {len(filtration_grid)=} != {self.num_parameters=}.")
|
|
1354
|
+
api = api_from_tensor(filtration_grid[0])
|
|
1355
|
+
cdef vector[vector[double]] c_filtration_grid = tuple(api.asnumpy(f).astype(np.float64) for f in filtration_grid) # may be faster with loop on views
|
|
1310
1356
|
if coordinate_values and inplace:
|
|
1311
|
-
self.filtration_grid =
|
|
1357
|
+
self.filtration_grid = filtration_grid
|
|
1312
1358
|
if inplace or not coordinate_values:
|
|
1313
1359
|
self.get_ptr().squeeze_filtration_inplace(c_filtration_grid, coordinate_values)
|
|
1314
1360
|
else:
|
|
1315
1361
|
out = SimplexTreeMulti_{{FSHORT[:-3] + "i32"}}(num_parameters=self.num_parameters)
|
|
1316
1362
|
self.get_ptr().squeeze_filtration(out.thisptr, c_filtration_grid)
|
|
1317
|
-
out.filtration_grid =
|
|
1363
|
+
out.filtration_grid = filtration_grid
|
|
1318
1364
|
return out
|
|
1319
1365
|
return self
|
|
1320
1366
|
|
|
1367
|
+
def unsqueeze(self, grid=None)->SimplexTreeMulti_{{FSHORT[:-3] + "f64"}}:
|
|
1368
|
+
from multipers.grids import sanitize_grid
|
|
1369
|
+
grid = self.filtration_grid if grid is None else grid
|
|
1370
|
+
|
|
1371
|
+
cdef vector[vector[double]] cgrid = sanitize_grid(grid, numpyfy=True)
|
|
1372
|
+
new_slicer = SimplexTreeMulti_{{FSHORT[:-3] + "f64"}}()
|
|
1373
|
+
new_slicer.get_ptr().unsqueeze_filtration(self.thisptr, cgrid)
|
|
1374
|
+
|
|
1375
|
+
return new_slicer
|
|
1376
|
+
|
|
1321
1377
|
@property
|
|
1322
1378
|
def is_squeezed(self)->bool:
|
|
1323
|
-
return self.num_vertices > 0 and len(self.filtration_grid)>0 and len(self.filtration_grid[0]) > 0
|
|
1379
|
+
return self.num_vertices > 0 and self.filtration_grid is not None and len(self.filtration_grid)>0 and len(self.filtration_grid[0]) > 0
|
|
1324
1380
|
|
|
1325
1381
|
@property
|
|
1326
1382
|
def dtype(self)->type:
|
|
@@ -1632,7 +1688,7 @@ def is_simplextree_multi(input)->bool:
|
|
|
1632
1688
|
|
|
1633
1689
|
|
|
1634
1690
|
|
|
1635
|
-
def SimplexTreeMulti(input=None, int num_parameters
|
|
1691
|
+
def SimplexTreeMulti(input=None, int num_parameters=-1, dtype:type = np.float64, bool kcritical = False,**kwargs) -> SimplexTreeMulti_type:
|
|
1636
1692
|
"""SimplexTreeMulti constructor.
|
|
1637
1693
|
|
|
1638
1694
|
:param other: If `other` is `None` (default value), an empty `SimplexTreeMulti` is created.
|
|
@@ -1804,7 +1860,8 @@ def _euler_signed_measure(simplextree, mass_default=None, bool verbose=False):
|
|
|
1804
1860
|
`[signed_measure_of_degree for degree in degrees]`
|
|
1805
1861
|
with `signed_measure_of_degree` of the form `(dirac location, dirac weights)`.
|
|
1806
1862
|
"""
|
|
1807
|
-
|
|
1863
|
+
if not simplextree.is_squeezed:
|
|
1864
|
+
raise ValueError("Squeeze grid first.")
|
|
1808
1865
|
cdef bool zero_pad = mass_default is not None
|
|
1809
1866
|
# assert simplextree.num_parameters == 2
|
|
1810
1867
|
grid_shape = np.array([len(f) for f in simplextree.filtration_grid])
|
|
@@ -1898,9 +1955,9 @@ def _rank_signed_measure(simplextree, vector[indices_type] degrees, mass_default
|
|
|
1898
1955
|
else:
|
|
1899
1956
|
mass_default = np.asarray(mass_default)
|
|
1900
1957
|
assert mass_default.ndim == 1 and mass_default.shape[0] == simplextree.num_parameters, "Mass default has to be an array like of shape (num_parameters,)"
|
|
1901
|
-
if zero_pad:
|
|
1902
|
-
|
|
1903
|
-
|
|
1958
|
+
# if zero_pad:
|
|
1959
|
+
# for i, _ in enumerate(grid_shape):
|
|
1960
|
+
# grid_shape[i] += 1 # adds a 0
|
|
1904
1961
|
# grid_conversion = tuple(np.concatenate([f, [mass_default[i]]]) for i,f in enumerate(grid_conversion))
|
|
1905
1962
|
|
|
1906
1963
|
assert len(grid_shape) == simplextree.num_parameters, "Grid shape size has to be the number of parameters."
|
|
Binary file
|