multipers 2.3.1__cp312-cp312-win_amd64.whl → 2.3.2b1__cp312-cp312-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.cp312-win_amd64.pyd +0 -0
- multipers/grids.cp312-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.cp312-win_amd64.pyd +0 -0
- multipers/io.pyx +16 -86
- multipers/ml/mma.py +3 -3
- multipers/ml/signed_measures.py +60 -62
- multipers/mma_structures.cp312-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.cp312-win_amd64.pyd +0 -0
- multipers/multiparameter_module_approximation.pyx +22 -6
- multipers/plots.py +1 -0
- multipers/point_measure.cp312-win_amd64.pyd +0 -0
- multipers/point_measure.pyx +6 -2
- multipers/simplex_tree_multi.cp312-win_amd64.pyd +0 -0
- multipers/simplex_tree_multi.pxd +1 -0
- multipers/simplex_tree_multi.pyx +487 -109
- multipers/simplex_tree_multi.pyx.tp +67 -18
- multipers/slicer.cp312-win_amd64.pyd +0 -0
- multipers/slicer.pxd +719 -237
- multipers/slicer.pxd.tp +22 -6
- multipers/slicer.pyx +5312 -1365
- multipers/slicer.pyx.tp +199 -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.2b1.dist-info}/METADATA +4 -25
- {multipers-2.3.1.dist-info → multipers-2.3.2b1.dist-info}/RECORD +49 -46
- {multipers-2.3.1.dist-info → multipers-2.3.2b1.dist-info}/WHEEL +1 -1
- {multipers-2.3.1.dist-info → multipers-2.3.2b1.dist-info/licenses}/LICENSE +0 -0
- {multipers-2.3.1.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,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()
|
|
@@ -1257,11 +1258,26 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
1257
1258
|
out = self.get_ptr().get_filtration_values(degrees)
|
|
1258
1259
|
filtrations_values = [np.asarray(filtration) for filtration in out]
|
|
1259
1260
|
# Removes infs
|
|
1260
|
-
if inf_to_nan:
|
|
1261
|
+
if inf_to_nan and np.dtype(filtrations_values[0].dtype).kind == 'f':
|
|
1261
1262
|
for i,f in enumerate(filtrations_values):
|
|
1262
1263
|
filtrations_values[i][f == np.inf] = np.nan
|
|
1263
1264
|
filtrations_values[i][f == - np.inf] = np.nan
|
|
1264
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
|
+
|
|
1265
1281
|
|
|
1266
1282
|
|
|
1267
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]:
|
|
@@ -1297,8 +1313,16 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
1297
1313
|
return compute_grid(filtrations_values, resolution=resolution,strategy=grid_strategy,drop_quantiles=drop_quantiles)
|
|
1298
1314
|
|
|
1299
1315
|
|
|
1300
|
-
|
|
1301
|
-
|
|
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}}:
|
|
1302
1326
|
"""
|
|
1303
1327
|
Fit the filtration of the simplextree to a grid.
|
|
1304
1328
|
|
|
@@ -1309,26 +1333,50 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
|
|
|
1309
1333
|
"""
|
|
1310
1334
|
if not force and self.is_squeezed:
|
|
1311
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
|
+
|
|
1312
1347
|
#TODO : multi-critical
|
|
1313
1348
|
if filtration_grid is None:
|
|
1314
|
-
filtration_grid = self.get_filtration_grid(grid_strategy=
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
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
|
|
1318
1356
|
if coordinate_values and inplace:
|
|
1319
|
-
self.filtration_grid =
|
|
1357
|
+
self.filtration_grid = filtration_grid
|
|
1320
1358
|
if inplace or not coordinate_values:
|
|
1321
1359
|
self.get_ptr().squeeze_filtration_inplace(c_filtration_grid, coordinate_values)
|
|
1322
1360
|
else:
|
|
1323
1361
|
out = SimplexTreeMulti_{{FSHORT[:-3] + "i32"}}(num_parameters=self.num_parameters)
|
|
1324
1362
|
self.get_ptr().squeeze_filtration(out.thisptr, c_filtration_grid)
|
|
1325
|
-
out.filtration_grid =
|
|
1363
|
+
out.filtration_grid = filtration_grid
|
|
1326
1364
|
return out
|
|
1327
1365
|
return self
|
|
1328
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
|
+
|
|
1329
1377
|
@property
|
|
1330
1378
|
def is_squeezed(self)->bool:
|
|
1331
|
-
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
|
|
1332
1380
|
|
|
1333
1381
|
@property
|
|
1334
1382
|
def dtype(self)->type:
|
|
@@ -1812,7 +1860,8 @@ def _euler_signed_measure(simplextree, mass_default=None, bool verbose=False):
|
|
|
1812
1860
|
`[signed_measure_of_degree for degree in degrees]`
|
|
1813
1861
|
with `signed_measure_of_degree` of the form `(dirac location, dirac weights)`.
|
|
1814
1862
|
"""
|
|
1815
|
-
|
|
1863
|
+
if not simplextree.is_squeezed:
|
|
1864
|
+
raise ValueError("Squeeze grid first.")
|
|
1816
1865
|
cdef bool zero_pad = mass_default is not None
|
|
1817
1866
|
# assert simplextree.num_parameters == 2
|
|
1818
1867
|
grid_shape = np.array([len(f) for f in simplextree.filtration_grid])
|
|
@@ -1906,9 +1955,9 @@ def _rank_signed_measure(simplextree, vector[indices_type] degrees, mass_default
|
|
|
1906
1955
|
else:
|
|
1907
1956
|
mass_default = np.asarray(mass_default)
|
|
1908
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,)"
|
|
1909
|
-
if zero_pad:
|
|
1910
|
-
|
|
1911
|
-
|
|
1958
|
+
# if zero_pad:
|
|
1959
|
+
# for i, _ in enumerate(grid_shape):
|
|
1960
|
+
# grid_shape[i] += 1 # adds a 0
|
|
1912
1961
|
# grid_conversion = tuple(np.concatenate([f, [mass_default[i]]]) for i,f in enumerate(grid_conversion))
|
|
1913
1962
|
|
|
1914
1963
|
assert len(grid_shape) == simplextree.num_parameters, "Grid shape size has to be the number of parameters."
|
|
Binary file
|