multipers 2.3.1__cp310-cp310-win_amd64.whl → 2.3.2__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/filtrations/density.py +23 -12
- multipers/filtrations/filtrations.py +74 -15
- 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 +35 -0
- multipers/gudhi/gudhi/Multi_persistence/Box.h +3 -0
- multipers/gudhi/gudhi/One_critical_filtration.h +17 -9
- multipers/gudhi/mma_interface_matrix.h +5 -3
- multipers/gudhi/truc.h +488 -42
- multipers/io.cp310-win_amd64.pyd +0 -0
- multipers/io.pyx +16 -86
- multipers/ml/mma.py +4 -4
- multipers/ml/signed_measures.py +60 -62
- multipers/mma_structures.cp310-win_amd64.pyd +0 -0
- multipers/mma_structures.pxd +2 -1
- multipers/mma_structures.pyx +56 -12
- multipers/mma_structures.pyx.tp +14 -3
- multipers/multiparameter_module_approximation/approximation.h +45 -13
- multipers/multiparameter_module_approximation.cp310-win_amd64.pyd +0 -0
- multipers/multiparameter_module_approximation.pyx +24 -7
- multipers/plots.py +1 -0
- 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 +535 -113
- multipers/simplex_tree_multi.pyx.tp +79 -19
- multipers/slicer.cp310-win_amd64.pyd +0 -0
- multipers/slicer.pxd +719 -237
- multipers/slicer.pxd.tp +22 -6
- multipers/slicer.pyx +5315 -1365
- multipers/slicer.pyx.tp +202 -46
- multipers/tbb12.dll +0 -0
- multipers/tbbbind_2_5.dll +0 -0
- multipers/tbbmalloc.dll +0 -0
- multipers/tbbmalloc_proxy.dll +0 -0
- multipers/tests/__init__.py +9 -4
- multipers/torch/diff_grids.py +30 -7
- {multipers-2.3.1.dist-info → multipers-2.3.2.dist-info}/METADATA +4 -25
- {multipers-2.3.1.dist-info → multipers-2.3.2.dist-info}/RECORD +49 -46
- {multipers-2.3.1.dist-info → multipers-2.3.2.dist-info}/WHEEL +1 -1
- {multipers-2.3.1.dist-info → multipers-2.3.2.dist-info/licenses}/LICENSE +0 -0
- {multipers-2.3.1.dist-info → multipers-2.3.2.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,8 +99,8 @@ 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)
|
|
@@ -182,7 +183,7 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
182
183
|
self.thisptr = <intptr_t>(new Simplex_tree_multi_interface[{{FSHORT}}, {{CTYPE}}]())
|
|
183
184
|
self.set_num_parameter(num_parameters)
|
|
184
185
|
self._is_function_simplextree = False
|
|
185
|
-
self.filtration_grid=[
|
|
186
|
+
self.filtration_grid=[]
|
|
186
187
|
|
|
187
188
|
def __dealloc__(self):
|
|
188
189
|
cdef Simplex_tree_multi_interface[{{FSHORT}},{{CTYPE}}]* ptr = self.get_ptr()
|
|
@@ -971,7 +972,16 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
971
972
|
out = self.get_ptr().get_edge_list()
|
|
972
973
|
return out
|
|
973
974
|
|
|
974
|
-
def collapse_edges(
|
|
975
|
+
def collapse_edges(
|
|
976
|
+
self,
|
|
977
|
+
int num=1,
|
|
978
|
+
int max_dimension = 0,
|
|
979
|
+
bool progress=False,
|
|
980
|
+
bool strong=True,
|
|
981
|
+
bool full=False,
|
|
982
|
+
bool ignore_warning=False,
|
|
983
|
+
bool auto_clean=True,
|
|
984
|
+
)->SimplexTreeMulti_{{FSHORT}}:
|
|
975
985
|
"""Edge collapse for 1-critical 2-parameter clique complex (see https://arxiv.org/abs/2211.05574).
|
|
976
986
|
It uses the code from the github repository https://github.com/aj-alonso/filtration_domination .
|
|
977
987
|
|
|
@@ -1021,6 +1031,8 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
1021
1031
|
edges = _collapse_edge_list(edges, num=num, full=full, strong=strong, progress=progress)
|
|
1022
1032
|
# Retrieves the collapsed simplicial complex
|
|
1023
1033
|
self._reconstruct_from_edge_list(edges, swap=True, expand_dimension=max_dimension)
|
|
1034
|
+
if self.is_squeezed and auto_clean:
|
|
1035
|
+
self._clean_filtration_grid()
|
|
1024
1036
|
return self
|
|
1025
1037
|
|
|
1026
1038
|
@cython.inline
|
|
@@ -1257,11 +1269,26 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
1257
1269
|
out = self.get_ptr().get_filtration_values(degrees)
|
|
1258
1270
|
filtrations_values = [np.asarray(filtration) for filtration in out]
|
|
1259
1271
|
# Removes infs
|
|
1260
|
-
if inf_to_nan:
|
|
1272
|
+
if inf_to_nan and np.dtype(filtrations_values[0].dtype).kind == 'f':
|
|
1261
1273
|
for i,f in enumerate(filtrations_values):
|
|
1262
1274
|
filtrations_values[i][f == np.inf] = np.nan
|
|
1263
1275
|
filtrations_values[i][f == - np.inf] = np.nan
|
|
1264
1276
|
return filtrations_values
|
|
1277
|
+
def _clean_filtration_grid(self):
|
|
1278
|
+
"""
|
|
1279
|
+
Removes the values in filtration_grid that are not linked to any splx.
|
|
1280
|
+
"""
|
|
1281
|
+
if not self.is_squeezed:
|
|
1282
|
+
raise ValueError("No grid to clean.")
|
|
1283
|
+
F = self.filtration_grid
|
|
1284
|
+
self.filtration_grid=None
|
|
1285
|
+
cleaned_coordinates = compute_grid(self)
|
|
1286
|
+
new_st = self.grid_squeeze(cleaned_coordinates)
|
|
1287
|
+
|
|
1288
|
+
self.thisptr, new_st.thisptr = new_st.thisptr, self.thisptr
|
|
1289
|
+
self.filtration_grid = tuple(f[g] for f,g in zip(F,cleaned_coordinates))
|
|
1290
|
+
return self
|
|
1291
|
+
|
|
1265
1292
|
|
|
1266
1293
|
|
|
1267
1294
|
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]:
|
|
@@ -1297,8 +1324,16 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
1297
1324
|
return compute_grid(filtrations_values, resolution=resolution,strategy=grid_strategy,drop_quantiles=drop_quantiles)
|
|
1298
1325
|
|
|
1299
1326
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1327
|
+
def grid_squeeze(
|
|
1328
|
+
self,
|
|
1329
|
+
filtration_grid:np.ndarray|list|None=None,
|
|
1330
|
+
bool coordinate_values=True,
|
|
1331
|
+
bool force=False,
|
|
1332
|
+
str strategy:_available_strategies = "exact",
|
|
1333
|
+
grid_strategy=None,
|
|
1334
|
+
bool inplace=False,
|
|
1335
|
+
**filtration_grid_kwargs
|
|
1336
|
+
)->SimplexTreeMulti_{{FSHORT[:-3] + "i32"}} | SimplexTreeMulti_{{FSHORT}}:
|
|
1302
1337
|
"""
|
|
1303
1338
|
Fit the filtration of the simplextree to a grid.
|
|
1304
1339
|
|
|
@@ -1309,26 +1344,50 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
1309
1344
|
"""
|
|
1310
1345
|
if not force and self.is_squeezed:
|
|
1311
1346
|
raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
|
|
1347
|
+
|
|
1348
|
+
if grid_strategy is not None:
|
|
1349
|
+
warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
|
|
1350
|
+
strategy=grid_strategy
|
|
1351
|
+
|
|
1352
|
+
if self.is_squeezed:
|
|
1353
|
+
warn("(copy warning) Squeezing an already squeezed slicer.")
|
|
1354
|
+
temp = self.unsqueeze()
|
|
1355
|
+
subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
|
|
1356
|
+
return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
|
|
1357
|
+
|
|
1312
1358
|
#TODO : multi-critical
|
|
1313
1359
|
if filtration_grid is None:
|
|
1314
|
-
filtration_grid = self.get_filtration_grid(grid_strategy=
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1360
|
+
filtration_grid = self.get_filtration_grid(grid_strategy=strategy, **filtration_grid_kwargs)
|
|
1361
|
+
else:
|
|
1362
|
+
filtration_grid = sanitize_grid(filtration_grid)
|
|
1363
|
+
if len(filtration_grid) != self.num_parameters:
|
|
1364
|
+
raise ValueError(f"Invalid grid to squeeze onto. Got {len(filtration_grid)=} != {self.num_parameters=}.")
|
|
1365
|
+
api = api_from_tensor(filtration_grid[0])
|
|
1366
|
+
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
|
|
1318
1367
|
if coordinate_values and inplace:
|
|
1319
|
-
self.filtration_grid =
|
|
1368
|
+
self.filtration_grid = filtration_grid
|
|
1320
1369
|
if inplace or not coordinate_values:
|
|
1321
1370
|
self.get_ptr().squeeze_filtration_inplace(c_filtration_grid, coordinate_values)
|
|
1322
1371
|
else:
|
|
1323
1372
|
out = SimplexTreeMulti_{{FSHORT[:-3] + "i32"}}(num_parameters=self.num_parameters)
|
|
1324
1373
|
self.get_ptr().squeeze_filtration(out.thisptr, c_filtration_grid)
|
|
1325
|
-
out.filtration_grid =
|
|
1374
|
+
out.filtration_grid = filtration_grid
|
|
1326
1375
|
return out
|
|
1327
1376
|
return self
|
|
1328
1377
|
|
|
1378
|
+
def unsqueeze(self, grid=None)->SimplexTreeMulti_{{FSHORT[:-3] + "f64"}}:
|
|
1379
|
+
from multipers.grids import sanitize_grid
|
|
1380
|
+
grid = self.filtration_grid if grid is None else grid
|
|
1381
|
+
|
|
1382
|
+
cdef vector[vector[double]] cgrid = sanitize_grid(grid, numpyfy=True)
|
|
1383
|
+
new_slicer = SimplexTreeMulti_{{FSHORT[:-3] + "f64"}}()
|
|
1384
|
+
new_slicer.get_ptr().unsqueeze_filtration(self.thisptr, cgrid)
|
|
1385
|
+
|
|
1386
|
+
return new_slicer
|
|
1387
|
+
|
|
1329
1388
|
@property
|
|
1330
1389
|
def is_squeezed(self)->bool:
|
|
1331
|
-
return self.num_vertices > 0 and len(self.filtration_grid)>0 and len(self.filtration_grid[0]) > 0
|
|
1390
|
+
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
|
|
1332
1391
|
|
|
1333
1392
|
@property
|
|
1334
1393
|
def dtype(self)->type:
|
|
@@ -1812,7 +1871,8 @@ def _euler_signed_measure(simplextree, mass_default=None, bool verbose=False):
|
|
|
1812
1871
|
`[signed_measure_of_degree for degree in degrees]`
|
|
1813
1872
|
with `signed_measure_of_degree` of the form `(dirac location, dirac weights)`.
|
|
1814
1873
|
"""
|
|
1815
|
-
|
|
1874
|
+
if not simplextree.is_squeezed:
|
|
1875
|
+
raise ValueError("Squeeze grid first.")
|
|
1816
1876
|
cdef bool zero_pad = mass_default is not None
|
|
1817
1877
|
# assert simplextree.num_parameters == 2
|
|
1818
1878
|
grid_shape = np.array([len(f) for f in simplextree.filtration_grid])
|
|
@@ -1906,9 +1966,9 @@ def _rank_signed_measure(simplextree, vector[indices_type] degrees, mass_default
|
|
|
1906
1966
|
else:
|
|
1907
1967
|
mass_default = np.asarray(mass_default)
|
|
1908
1968
|
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,)"
|
|
1909
|
-
if zero_pad:
|
|
1910
|
-
|
|
1911
|
-
|
|
1969
|
+
# if zero_pad:
|
|
1970
|
+
# for i, _ in enumerate(grid_shape):
|
|
1971
|
+
# grid_shape[i] += 1 # adds a 0
|
|
1912
1972
|
# grid_conversion = tuple(np.concatenate([f, [mass_default[i]]]) for i,f in enumerate(grid_conversion))
|
|
1913
1973
|
|
|
1914
1974
|
assert len(grid_shape) == simplextree.num_parameters, "Grid shape size has to be the number of parameters."
|
|
Binary file
|