multipers 2.3.1__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.

Files changed (49) hide show
  1. multipers/_signed_measure_meta.py +71 -65
  2. multipers/array_api/__init__.py +39 -0
  3. multipers/array_api/numpy.py +34 -0
  4. multipers/array_api/torch.py +35 -0
  5. multipers/distances.py +6 -2
  6. multipers/filtrations/density.py +23 -12
  7. multipers/filtrations/filtrations.py +74 -15
  8. multipers/function_rips.cp310-win_amd64.pyd +0 -0
  9. multipers/grids.cp310-win_amd64.pyd +0 -0
  10. multipers/grids.pyx +144 -61
  11. multipers/gudhi/Simplex_tree_multi_interface.h +35 -0
  12. multipers/gudhi/gudhi/Multi_persistence/Box.h +3 -0
  13. multipers/gudhi/gudhi/One_critical_filtration.h +17 -9
  14. multipers/gudhi/mma_interface_matrix.h +5 -3
  15. multipers/gudhi/truc.h +488 -42
  16. multipers/io.cp310-win_amd64.pyd +0 -0
  17. multipers/io.pyx +16 -86
  18. multipers/ml/mma.py +3 -3
  19. multipers/ml/signed_measures.py +60 -62
  20. multipers/mma_structures.cp310-win_amd64.pyd +0 -0
  21. multipers/mma_structures.pxd +2 -1
  22. multipers/mma_structures.pyx +56 -12
  23. multipers/mma_structures.pyx.tp +14 -3
  24. multipers/multiparameter_module_approximation/approximation.h +45 -13
  25. multipers/multiparameter_module_approximation.cp310-win_amd64.pyd +0 -0
  26. multipers/multiparameter_module_approximation.pyx +22 -6
  27. multipers/plots.py +1 -0
  28. multipers/point_measure.cp310-win_amd64.pyd +0 -0
  29. multipers/point_measure.pyx +6 -2
  30. multipers/simplex_tree_multi.cp310-win_amd64.pyd +0 -0
  31. multipers/simplex_tree_multi.pxd +1 -0
  32. multipers/simplex_tree_multi.pyx +487 -109
  33. multipers/simplex_tree_multi.pyx.tp +67 -18
  34. multipers/slicer.cp310-win_amd64.pyd +0 -0
  35. multipers/slicer.pxd +699 -217
  36. multipers/slicer.pxd.tp +22 -6
  37. multipers/slicer.pyx +5311 -1364
  38. multipers/slicer.pyx.tp +199 -46
  39. multipers/tbb12.dll +0 -0
  40. multipers/tbbbind_2_5.dll +0 -0
  41. multipers/tbbmalloc.dll +0 -0
  42. multipers/tbbmalloc_proxy.dll +0 -0
  43. multipers/tests/__init__.py +9 -4
  44. multipers/torch/diff_grids.py +30 -7
  45. {multipers-2.3.1.dist-info → multipers-2.3.2b1.dist-info}/METADATA +4 -25
  46. {multipers-2.3.1.dist-info → multipers-2.3.2b1.dist-info}/RECORD +49 -46
  47. {multipers-2.3.1.dist-info → multipers-2.3.2b1.dist-info}/WHEEL +1 -1
  48. {multipers-2.3.1.dist-info → multipers-2.3.2b1.dist-info/licenses}/LICENSE +0 -0
  49. {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 vector[vector[double]] filtration_grid
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=[[]*num_parameters]
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
- def grid_squeeze(self, filtration_grid:np.ndarray|list|None=None, bool coordinate_values=True, force=False, grid_strategy:_available_strategies = "exact", inplace=False, **filtration_grid_kwargs):
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=grid_strategy, **filtration_grid_kwargs)
1315
- cdef vector[vector[double]] c_filtration_grid = filtration_grid
1316
- assert <int>c_filtration_grid.size() == self.get_ptr().get_number_of_parameters(), f"Grid has to be of size {self.num_parameters}, got {filtration_grid.size()}"
1317
- cdef intptr_t ptr = self.thisptr
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 = c_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 = c_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
- assert len(simplextree.filtration_grid[0]) > 0, "Squeeze grid first."
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
- for i, _ in enumerate(grid_shape):
1911
- grid_shape[i] += 1 # adds a 0
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