multipers 2.3.3b7__cp313-cp313-win_amd64.whl → 2.3.5b1__cp313-cp313-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 (34) hide show
  1. multipers/_signed_measure_meta.py +50 -84
  2. multipers/array_api/numpy.py +12 -10
  3. multipers/array_api/torch.py +6 -3
  4. multipers/filtrations/filtrations.py +4 -2
  5. multipers/function_rips.cp313-win_amd64.pyd +0 -0
  6. multipers/grids.cp313-win_amd64.pyd +0 -0
  7. multipers/grids.pyx +51 -30
  8. multipers/gudhi/gudhi/Multi_critical_filtration.h +1 -1
  9. multipers/io.cp313-win_amd64.pyd +0 -0
  10. multipers/mma_structures.cp313-win_amd64.pyd +0 -0
  11. multipers/multi_parameter_rank_invariant/function_rips.h +1 -1
  12. multipers/multiparameter_module_approximation/approximation.h +8 -2
  13. multipers/multiparameter_module_approximation.cp313-win_amd64.pyd +0 -0
  14. multipers/plots.py +27 -12
  15. multipers/point_measure.cp313-win_amd64.pyd +0 -0
  16. multipers/point_measure.pyx +1 -1
  17. multipers/simplex_tree_multi.cp313-win_amd64.pyd +0 -0
  18. multipers/simplex_tree_multi.pxd +2 -2
  19. multipers/simplex_tree_multi.pyx +228 -56
  20. multipers/simplex_tree_multi.pyx.tp +23 -9
  21. multipers/slicer.cp313-win_amd64.pyd +0 -0
  22. multipers/slicer.pxd +40 -40
  23. multipers/slicer.pxd.tp +1 -1
  24. multipers/slicer.pyx +2054 -1139
  25. multipers/slicer.pyx.tp +100 -43
  26. multipers/tbb12.dll +0 -0
  27. multipers/tbbbind_2_5.dll +0 -0
  28. multipers/tbbmalloc.dll +0 -0
  29. multipers/tbbmalloc_proxy.dll +0 -0
  30. {multipers-2.3.3b7.dist-info → multipers-2.3.5b1.dist-info}/METADATA +2 -2
  31. {multipers-2.3.3b7.dist-info → multipers-2.3.5b1.dist-info}/RECORD +34 -34
  32. {multipers-2.3.3b7.dist-info → multipers-2.3.5b1.dist-info}/WHEEL +0 -0
  33. {multipers-2.3.3b7.dist-info → multipers-2.3.5b1.dist-info}/licenses/LICENSE +0 -0
  34. {multipers-2.3.3b7.dist-info → multipers-2.3.5b1.dist-info}/top_level.txt +0 -0
@@ -366,7 +366,7 @@ def rectangle_to_hook_minimal_signed_barcode(pts,w,):
366
366
  # print("horizontal:", pts_H)
367
367
 
368
368
 
369
- new_w = api.cat([-w, w, w, w_proj,w_V,w_H])
369
+ new_w = np.concatenate([-w, w, w, w_proj,w_V,w_H])
370
370
 
371
371
  pts_b0a1 = api.tensor(pts)
372
372
  pts_b0a1[:,3] = pts[:,1]
@@ -117,8 +117,8 @@ cdef extern from "Simplex_tree_multi_interface.h" namespace "Gudhi::multiparamet
117
117
  void to_std(intptr_t, Line[double],int ) nogil
118
118
  void to_std_linear_projection(intptr_t, vector[double]) nogil
119
119
  void squeeze_filtration_inplace(vector[vector[double]] &, bool) nogil
120
- void squeeze_filtration(intptr_t, vector[vector[double]] &) nogil
121
- void unsqueeze_filtration(intptr_t, vector[vector[double]] &) nogil
120
+ void squeeze_filtration(intptr_t, vector[vector[double]] &) except + nogil
121
+ void unsqueeze_filtration(intptr_t, vector[vector[double]] &) except + nogil
122
122
  vector[vector[vector[value_type]]] get_filtration_values(const vector[int]&) nogil
123
123
 
124
124
 
@@ -479,10 +479,9 @@ cdef class SimplexTreeMulti_KFi32:
479
479
  preincrement(it)
480
480
 
481
481
 
482
+ def _get_raw_filtration(self):
483
+ raise NotImplementedError("Not implemented for multicritical filtrations")
482
484
 
483
- def persistence_approximation(self, **kwargs):
484
- from multipers.multiparameter_module_approximation import module_approximation
485
- return module_approximation(self, **kwargs)
486
485
 
487
486
 
488
487
  def get_skeleton(self, dimension)->Iterable[tuple[np.ndarray,np.ndarray]]:
@@ -625,6 +624,41 @@ cdef class SimplexTreeMulti_KFi32:
625
624
  """
626
625
  return self.get_ptr().prune_above_dimension(dimension)
627
626
 
627
+ def expansion(self, int max_dim)->SimplexTreeMulti_KFi32:
628
+ """Expands the simplex tree containing only its one skeleton
629
+ until dimension max_dim.
630
+
631
+ The expanded simplicial complex until dimension :math:`d`
632
+ attached to a graph :math:`G` is the maximal simplicial complex of
633
+ dimension at most :math:`d` admitting the graph :math:`G` as
634
+ :math:`1`-skeleton.
635
+ The filtration value assigned to a simplex is the maximal filtration
636
+ value of one of its edges.
637
+
638
+ The simplex tree must contain no simplex of dimension bigger than
639
+ 1 when calling the method.
640
+
641
+ :param max_dim: The maximal dimension.
642
+ :type max_dim: int
643
+ """
644
+ with nogil:
645
+ self.get_ptr().expansion(max_dim)
646
+ # This is a fix for multipersistence. FIXME expansion in c++
647
+ self.get_ptr().make_filtration_non_decreasing()
648
+ return self
649
+
650
+ def make_filtration_non_decreasing(self)->bool:
651
+ """This function ensures that each simplex has a higher filtration
652
+ value than its faces by increasing the filtration values.
653
+
654
+ :returns: True if any filtration value was modified,
655
+ False if the filtration was already non-decreasing.
656
+ :rtype: bool
657
+ """
658
+ cdef bool out
659
+ with nogil:
660
+ out = self.get_ptr().make_filtration_non_decreasing()
661
+ return out
628
662
 
629
663
  def reset_filtration(self, filtration, min_dim = 0)->SimplexTreeMulti_KFi32:
630
664
  """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the
@@ -881,7 +915,6 @@ cdef class SimplexTreeMulti_KFi32:
881
915
  self,
882
916
  filtration_grid:np.ndarray|list|None=None,
883
917
  bool coordinate_values=True,
884
- bool force=False,
885
918
  str strategy:_available_strategies = "exact",
886
919
  resolution:Optional[int|list[int]] = None,
887
920
  bool coordinates = False,
@@ -897,8 +930,6 @@ cdef class SimplexTreeMulti_KFi32:
897
930
  :param coordinate_values: If true, the filtrations values of the simplices will be set to the coordinate of the filtration grid.
898
931
  :type coordinate_values: bool
899
932
  """
900
- if not force and self.is_squeezed:
901
- raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
902
933
 
903
934
  if grid_strategy is not None:
904
935
  warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
@@ -908,7 +939,7 @@ cdef class SimplexTreeMulti_KFi32:
908
939
  warn("(copy warning) Squeezing an already squeezed slicer.")
909
940
  temp = self.unsqueeze()
910
941
  subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
911
- return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
942
+ return temp.grid_squeeze(sanitize_grid(subgrid, numpyfy=True), coordinates=coordinates, inplace=inplace)
912
943
 
913
944
  #TODO : multi-critical
914
945
  if filtration_grid is None:
@@ -1742,10 +1773,25 @@ cdef class SimplexTreeMulti_Fi32:
1742
1773
  preincrement(it)
1743
1774
 
1744
1775
 
1776
+ def _get_raw_filtration(self):
1777
+ if self.is_squeezed:
1778
+ raise NotImplementedError("Not implemented for squeezed filtrations")
1779
+ cdef int num_parameters = self.num_parameters
1780
+ cdef int32_t[:,:] current_filtration = np.empty((self.num_simplices, self.num_parameters), dtype=self.dtype)
1781
+
1782
+ cdef Simplex_tree_multi_simplices_iterator[Fi32] it = self.get_ptr().get_simplices_iterator_begin()
1783
+ cdef Simplex_tree_multi_simplices_iterator[Fi32] end = self.get_ptr().get_simplices_iterator_end()
1784
+
1785
+ cdef int i=0
1786
+ with nogil:
1787
+ while it != end:
1788
+ pair_sf = <pair[simplex_type, Fi32*]> self.get_ptr().get_simplex_and_filtration(dereference(it))
1789
+ for j in range(num_parameters):
1790
+ current_filtration[i,j] = dereference(pair_sf.second)[j]
1791
+ preincrement(it)
1792
+ i = i+1
1793
+ return np.asarray(current_filtration, dtype=self.dtype)
1745
1794
 
1746
- def persistence_approximation(self, **kwargs):
1747
- from multipers.multiparameter_module_approximation import module_approximation
1748
- return module_approximation(self, **kwargs)
1749
1795
 
1750
1796
 
1751
1797
  def get_skeleton(self, dimension)->Iterable[tuple[np.ndarray,np.ndarray]]:
@@ -2322,7 +2368,6 @@ cdef class SimplexTreeMulti_Fi32:
2322
2368
  self,
2323
2369
  filtration_grid:np.ndarray|list|None=None,
2324
2370
  bool coordinate_values=True,
2325
- bool force=False,
2326
2371
  str strategy:_available_strategies = "exact",
2327
2372
  resolution:Optional[int|list[int]] = None,
2328
2373
  bool coordinates = False,
@@ -2338,8 +2383,6 @@ cdef class SimplexTreeMulti_Fi32:
2338
2383
  :param coordinate_values: If true, the filtrations values of the simplices will be set to the coordinate of the filtration grid.
2339
2384
  :type coordinate_values: bool
2340
2385
  """
2341
- if not force and self.is_squeezed:
2342
- raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
2343
2386
 
2344
2387
  if grid_strategy is not None:
2345
2388
  warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
@@ -2349,7 +2392,7 @@ cdef class SimplexTreeMulti_Fi32:
2349
2392
  warn("(copy warning) Squeezing an already squeezed slicer.")
2350
2393
  temp = self.unsqueeze()
2351
2394
  subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
2352
- return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
2395
+ return temp.grid_squeeze(sanitize_grid(subgrid, numpyfy=True), coordinates=coordinates, inplace=inplace)
2353
2396
 
2354
2397
  #TODO : multi-critical
2355
2398
  if filtration_grid is None:
@@ -3071,10 +3114,9 @@ cdef class SimplexTreeMulti_KFi64:
3071
3114
  preincrement(it)
3072
3115
 
3073
3116
 
3117
+ def _get_raw_filtration(self):
3118
+ raise NotImplementedError("Not implemented for multicritical filtrations")
3074
3119
 
3075
- def persistence_approximation(self, **kwargs):
3076
- from multipers.multiparameter_module_approximation import module_approximation
3077
- return module_approximation(self, **kwargs)
3078
3120
 
3079
3121
 
3080
3122
  def get_skeleton(self, dimension)->Iterable[tuple[np.ndarray,np.ndarray]]:
@@ -3217,6 +3259,41 @@ cdef class SimplexTreeMulti_KFi64:
3217
3259
  """
3218
3260
  return self.get_ptr().prune_above_dimension(dimension)
3219
3261
 
3262
+ def expansion(self, int max_dim)->SimplexTreeMulti_KFi64:
3263
+ """Expands the simplex tree containing only its one skeleton
3264
+ until dimension max_dim.
3265
+
3266
+ The expanded simplicial complex until dimension :math:`d`
3267
+ attached to a graph :math:`G` is the maximal simplicial complex of
3268
+ dimension at most :math:`d` admitting the graph :math:`G` as
3269
+ :math:`1`-skeleton.
3270
+ The filtration value assigned to a simplex is the maximal filtration
3271
+ value of one of its edges.
3272
+
3273
+ The simplex tree must contain no simplex of dimension bigger than
3274
+ 1 when calling the method.
3275
+
3276
+ :param max_dim: The maximal dimension.
3277
+ :type max_dim: int
3278
+ """
3279
+ with nogil:
3280
+ self.get_ptr().expansion(max_dim)
3281
+ # This is a fix for multipersistence. FIXME expansion in c++
3282
+ self.get_ptr().make_filtration_non_decreasing()
3283
+ return self
3284
+
3285
+ def make_filtration_non_decreasing(self)->bool:
3286
+ """This function ensures that each simplex has a higher filtration
3287
+ value than its faces by increasing the filtration values.
3288
+
3289
+ :returns: True if any filtration value was modified,
3290
+ False if the filtration was already non-decreasing.
3291
+ :rtype: bool
3292
+ """
3293
+ cdef bool out
3294
+ with nogil:
3295
+ out = self.get_ptr().make_filtration_non_decreasing()
3296
+ return out
3220
3297
 
3221
3298
  def reset_filtration(self, filtration, min_dim = 0)->SimplexTreeMulti_KFi64:
3222
3299
  """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the
@@ -3473,7 +3550,6 @@ cdef class SimplexTreeMulti_KFi64:
3473
3550
  self,
3474
3551
  filtration_grid:np.ndarray|list|None=None,
3475
3552
  bool coordinate_values=True,
3476
- bool force=False,
3477
3553
  str strategy:_available_strategies = "exact",
3478
3554
  resolution:Optional[int|list[int]] = None,
3479
3555
  bool coordinates = False,
@@ -3489,8 +3565,6 @@ cdef class SimplexTreeMulti_KFi64:
3489
3565
  :param coordinate_values: If true, the filtrations values of the simplices will be set to the coordinate of the filtration grid.
3490
3566
  :type coordinate_values: bool
3491
3567
  """
3492
- if not force and self.is_squeezed:
3493
- raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
3494
3568
 
3495
3569
  if grid_strategy is not None:
3496
3570
  warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
@@ -3500,7 +3574,7 @@ cdef class SimplexTreeMulti_KFi64:
3500
3574
  warn("(copy warning) Squeezing an already squeezed slicer.")
3501
3575
  temp = self.unsqueeze()
3502
3576
  subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
3503
- return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
3577
+ return temp.grid_squeeze(sanitize_grid(subgrid, numpyfy=True), coordinates=coordinates, inplace=inplace)
3504
3578
 
3505
3579
  #TODO : multi-critical
3506
3580
  if filtration_grid is None:
@@ -4334,10 +4408,25 @@ cdef class SimplexTreeMulti_Fi64:
4334
4408
  preincrement(it)
4335
4409
 
4336
4410
 
4411
+ def _get_raw_filtration(self):
4412
+ if self.is_squeezed:
4413
+ raise NotImplementedError("Not implemented for squeezed filtrations")
4414
+ cdef int num_parameters = self.num_parameters
4415
+ cdef int64_t[:,:] current_filtration = np.empty((self.num_simplices, self.num_parameters), dtype=self.dtype)
4416
+
4417
+ cdef Simplex_tree_multi_simplices_iterator[Fi64] it = self.get_ptr().get_simplices_iterator_begin()
4418
+ cdef Simplex_tree_multi_simplices_iterator[Fi64] end = self.get_ptr().get_simplices_iterator_end()
4419
+
4420
+ cdef int i=0
4421
+ with nogil:
4422
+ while it != end:
4423
+ pair_sf = <pair[simplex_type, Fi64*]> self.get_ptr().get_simplex_and_filtration(dereference(it))
4424
+ for j in range(num_parameters):
4425
+ current_filtration[i,j] = dereference(pair_sf.second)[j]
4426
+ preincrement(it)
4427
+ i = i+1
4428
+ return np.asarray(current_filtration, dtype=self.dtype)
4337
4429
 
4338
- def persistence_approximation(self, **kwargs):
4339
- from multipers.multiparameter_module_approximation import module_approximation
4340
- return module_approximation(self, **kwargs)
4341
4430
 
4342
4431
 
4343
4432
  def get_skeleton(self, dimension)->Iterable[tuple[np.ndarray,np.ndarray]]:
@@ -4914,7 +5003,6 @@ cdef class SimplexTreeMulti_Fi64:
4914
5003
  self,
4915
5004
  filtration_grid:np.ndarray|list|None=None,
4916
5005
  bool coordinate_values=True,
4917
- bool force=False,
4918
5006
  str strategy:_available_strategies = "exact",
4919
5007
  resolution:Optional[int|list[int]] = None,
4920
5008
  bool coordinates = False,
@@ -4930,8 +5018,6 @@ cdef class SimplexTreeMulti_Fi64:
4930
5018
  :param coordinate_values: If true, the filtrations values of the simplices will be set to the coordinate of the filtration grid.
4931
5019
  :type coordinate_values: bool
4932
5020
  """
4933
- if not force and self.is_squeezed:
4934
- raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
4935
5021
 
4936
5022
  if grid_strategy is not None:
4937
5023
  warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
@@ -4941,7 +5027,7 @@ cdef class SimplexTreeMulti_Fi64:
4941
5027
  warn("(copy warning) Squeezing an already squeezed slicer.")
4942
5028
  temp = self.unsqueeze()
4943
5029
  subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
4944
- return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
5030
+ return temp.grid_squeeze(sanitize_grid(subgrid, numpyfy=True), coordinates=coordinates, inplace=inplace)
4945
5031
 
4946
5032
  #TODO : multi-critical
4947
5033
  if filtration_grid is None:
@@ -5663,10 +5749,9 @@ cdef class SimplexTreeMulti_KFf32:
5663
5749
  preincrement(it)
5664
5750
 
5665
5751
 
5752
+ def _get_raw_filtration(self):
5753
+ raise NotImplementedError("Not implemented for multicritical filtrations")
5666
5754
 
5667
- def persistence_approximation(self, **kwargs):
5668
- from multipers.multiparameter_module_approximation import module_approximation
5669
- return module_approximation(self, **kwargs)
5670
5755
 
5671
5756
 
5672
5757
  def get_skeleton(self, dimension)->Iterable[tuple[np.ndarray,np.ndarray]]:
@@ -5809,6 +5894,41 @@ cdef class SimplexTreeMulti_KFf32:
5809
5894
  """
5810
5895
  return self.get_ptr().prune_above_dimension(dimension)
5811
5896
 
5897
+ def expansion(self, int max_dim)->SimplexTreeMulti_KFf32:
5898
+ """Expands the simplex tree containing only its one skeleton
5899
+ until dimension max_dim.
5900
+
5901
+ The expanded simplicial complex until dimension :math:`d`
5902
+ attached to a graph :math:`G` is the maximal simplicial complex of
5903
+ dimension at most :math:`d` admitting the graph :math:`G` as
5904
+ :math:`1`-skeleton.
5905
+ The filtration value assigned to a simplex is the maximal filtration
5906
+ value of one of its edges.
5907
+
5908
+ The simplex tree must contain no simplex of dimension bigger than
5909
+ 1 when calling the method.
5910
+
5911
+ :param max_dim: The maximal dimension.
5912
+ :type max_dim: int
5913
+ """
5914
+ with nogil:
5915
+ self.get_ptr().expansion(max_dim)
5916
+ # This is a fix for multipersistence. FIXME expansion in c++
5917
+ self.get_ptr().make_filtration_non_decreasing()
5918
+ return self
5919
+
5920
+ def make_filtration_non_decreasing(self)->bool:
5921
+ """This function ensures that each simplex has a higher filtration
5922
+ value than its faces by increasing the filtration values.
5923
+
5924
+ :returns: True if any filtration value was modified,
5925
+ False if the filtration was already non-decreasing.
5926
+ :rtype: bool
5927
+ """
5928
+ cdef bool out
5929
+ with nogil:
5930
+ out = self.get_ptr().make_filtration_non_decreasing()
5931
+ return out
5812
5932
 
5813
5933
  def reset_filtration(self, filtration, min_dim = 0)->SimplexTreeMulti_KFf32:
5814
5934
  """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the
@@ -6065,7 +6185,6 @@ cdef class SimplexTreeMulti_KFf32:
6065
6185
  self,
6066
6186
  filtration_grid:np.ndarray|list|None=None,
6067
6187
  bool coordinate_values=True,
6068
- bool force=False,
6069
6188
  str strategy:_available_strategies = "exact",
6070
6189
  resolution:Optional[int|list[int]] = None,
6071
6190
  bool coordinates = False,
@@ -6081,8 +6200,6 @@ cdef class SimplexTreeMulti_KFf32:
6081
6200
  :param coordinate_values: If true, the filtrations values of the simplices will be set to the coordinate of the filtration grid.
6082
6201
  :type coordinate_values: bool
6083
6202
  """
6084
- if not force and self.is_squeezed:
6085
- raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
6086
6203
 
6087
6204
  if grid_strategy is not None:
6088
6205
  warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
@@ -6092,7 +6209,7 @@ cdef class SimplexTreeMulti_KFf32:
6092
6209
  warn("(copy warning) Squeezing an already squeezed slicer.")
6093
6210
  temp = self.unsqueeze()
6094
6211
  subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
6095
- return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
6212
+ return temp.grid_squeeze(sanitize_grid(subgrid, numpyfy=True), coordinates=coordinates, inplace=inplace)
6096
6213
 
6097
6214
  #TODO : multi-critical
6098
6215
  if filtration_grid is None:
@@ -6926,10 +7043,25 @@ cdef class SimplexTreeMulti_Ff32:
6926
7043
  preincrement(it)
6927
7044
 
6928
7045
 
7046
+ def _get_raw_filtration(self):
7047
+ if self.is_squeezed:
7048
+ raise NotImplementedError("Not implemented for squeezed filtrations")
7049
+ cdef int num_parameters = self.num_parameters
7050
+ cdef float[:,:] current_filtration = np.empty((self.num_simplices, self.num_parameters), dtype=self.dtype)
7051
+
7052
+ cdef Simplex_tree_multi_simplices_iterator[Ff32] it = self.get_ptr().get_simplices_iterator_begin()
7053
+ cdef Simplex_tree_multi_simplices_iterator[Ff32] end = self.get_ptr().get_simplices_iterator_end()
7054
+
7055
+ cdef int i=0
7056
+ with nogil:
7057
+ while it != end:
7058
+ pair_sf = <pair[simplex_type, Ff32*]> self.get_ptr().get_simplex_and_filtration(dereference(it))
7059
+ for j in range(num_parameters):
7060
+ current_filtration[i,j] = dereference(pair_sf.second)[j]
7061
+ preincrement(it)
7062
+ i = i+1
7063
+ return np.asarray(current_filtration, dtype=self.dtype)
6929
7064
 
6930
- def persistence_approximation(self, **kwargs):
6931
- from multipers.multiparameter_module_approximation import module_approximation
6932
- return module_approximation(self, **kwargs)
6933
7065
 
6934
7066
 
6935
7067
  def get_skeleton(self, dimension)->Iterable[tuple[np.ndarray,np.ndarray]]:
@@ -7506,7 +7638,6 @@ cdef class SimplexTreeMulti_Ff32:
7506
7638
  self,
7507
7639
  filtration_grid:np.ndarray|list|None=None,
7508
7640
  bool coordinate_values=True,
7509
- bool force=False,
7510
7641
  str strategy:_available_strategies = "exact",
7511
7642
  resolution:Optional[int|list[int]] = None,
7512
7643
  bool coordinates = False,
@@ -7522,8 +7653,6 @@ cdef class SimplexTreeMulti_Ff32:
7522
7653
  :param coordinate_values: If true, the filtrations values of the simplices will be set to the coordinate of the filtration grid.
7523
7654
  :type coordinate_values: bool
7524
7655
  """
7525
- if not force and self.is_squeezed:
7526
- raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
7527
7656
 
7528
7657
  if grid_strategy is not None:
7529
7658
  warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
@@ -7533,7 +7662,7 @@ cdef class SimplexTreeMulti_Ff32:
7533
7662
  warn("(copy warning) Squeezing an already squeezed slicer.")
7534
7663
  temp = self.unsqueeze()
7535
7664
  subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
7536
- return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
7665
+ return temp.grid_squeeze(sanitize_grid(subgrid, numpyfy=True), coordinates=coordinates, inplace=inplace)
7537
7666
 
7538
7667
  #TODO : multi-critical
7539
7668
  if filtration_grid is None:
@@ -8255,10 +8384,9 @@ cdef class SimplexTreeMulti_KFf64:
8255
8384
  preincrement(it)
8256
8385
 
8257
8386
 
8387
+ def _get_raw_filtration(self):
8388
+ raise NotImplementedError("Not implemented for multicritical filtrations")
8258
8389
 
8259
- def persistence_approximation(self, **kwargs):
8260
- from multipers.multiparameter_module_approximation import module_approximation
8261
- return module_approximation(self, **kwargs)
8262
8390
 
8263
8391
 
8264
8392
  def get_skeleton(self, dimension)->Iterable[tuple[np.ndarray,np.ndarray]]:
@@ -8401,6 +8529,41 @@ cdef class SimplexTreeMulti_KFf64:
8401
8529
  """
8402
8530
  return self.get_ptr().prune_above_dimension(dimension)
8403
8531
 
8532
+ def expansion(self, int max_dim)->SimplexTreeMulti_KFf64:
8533
+ """Expands the simplex tree containing only its one skeleton
8534
+ until dimension max_dim.
8535
+
8536
+ The expanded simplicial complex until dimension :math:`d`
8537
+ attached to a graph :math:`G` is the maximal simplicial complex of
8538
+ dimension at most :math:`d` admitting the graph :math:`G` as
8539
+ :math:`1`-skeleton.
8540
+ The filtration value assigned to a simplex is the maximal filtration
8541
+ value of one of its edges.
8542
+
8543
+ The simplex tree must contain no simplex of dimension bigger than
8544
+ 1 when calling the method.
8545
+
8546
+ :param max_dim: The maximal dimension.
8547
+ :type max_dim: int
8548
+ """
8549
+ with nogil:
8550
+ self.get_ptr().expansion(max_dim)
8551
+ # This is a fix for multipersistence. FIXME expansion in c++
8552
+ self.get_ptr().make_filtration_non_decreasing()
8553
+ return self
8554
+
8555
+ def make_filtration_non_decreasing(self)->bool:
8556
+ """This function ensures that each simplex has a higher filtration
8557
+ value than its faces by increasing the filtration values.
8558
+
8559
+ :returns: True if any filtration value was modified,
8560
+ False if the filtration was already non-decreasing.
8561
+ :rtype: bool
8562
+ """
8563
+ cdef bool out
8564
+ with nogil:
8565
+ out = self.get_ptr().make_filtration_non_decreasing()
8566
+ return out
8404
8567
 
8405
8568
  def reset_filtration(self, filtration, min_dim = 0)->SimplexTreeMulti_KFf64:
8406
8569
  """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the
@@ -8657,7 +8820,6 @@ cdef class SimplexTreeMulti_KFf64:
8657
8820
  self,
8658
8821
  filtration_grid:np.ndarray|list|None=None,
8659
8822
  bool coordinate_values=True,
8660
- bool force=False,
8661
8823
  str strategy:_available_strategies = "exact",
8662
8824
  resolution:Optional[int|list[int]] = None,
8663
8825
  bool coordinates = False,
@@ -8673,8 +8835,6 @@ cdef class SimplexTreeMulti_KFf64:
8673
8835
  :param coordinate_values: If true, the filtrations values of the simplices will be set to the coordinate of the filtration grid.
8674
8836
  :type coordinate_values: bool
8675
8837
  """
8676
- if not force and self.is_squeezed:
8677
- raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
8678
8838
 
8679
8839
  if grid_strategy is not None:
8680
8840
  warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
@@ -8684,7 +8844,7 @@ cdef class SimplexTreeMulti_KFf64:
8684
8844
  warn("(copy warning) Squeezing an already squeezed slicer.")
8685
8845
  temp = self.unsqueeze()
8686
8846
  subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
8687
- return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
8847
+ return temp.grid_squeeze(sanitize_grid(subgrid, numpyfy=True), coordinates=coordinates, inplace=inplace)
8688
8848
 
8689
8849
  #TODO : multi-critical
8690
8850
  if filtration_grid is None:
@@ -9518,10 +9678,25 @@ cdef class SimplexTreeMulti_Ff64:
9518
9678
  preincrement(it)
9519
9679
 
9520
9680
 
9681
+ def _get_raw_filtration(self):
9682
+ if self.is_squeezed:
9683
+ raise NotImplementedError("Not implemented for squeezed filtrations")
9684
+ cdef int num_parameters = self.num_parameters
9685
+ cdef double[:,:] current_filtration = np.empty((self.num_simplices, self.num_parameters), dtype=self.dtype)
9686
+
9687
+ cdef Simplex_tree_multi_simplices_iterator[Ff64] it = self.get_ptr().get_simplices_iterator_begin()
9688
+ cdef Simplex_tree_multi_simplices_iterator[Ff64] end = self.get_ptr().get_simplices_iterator_end()
9689
+
9690
+ cdef int i=0
9691
+ with nogil:
9692
+ while it != end:
9693
+ pair_sf = <pair[simplex_type, Ff64*]> self.get_ptr().get_simplex_and_filtration(dereference(it))
9694
+ for j in range(num_parameters):
9695
+ current_filtration[i,j] = dereference(pair_sf.second)[j]
9696
+ preincrement(it)
9697
+ i = i+1
9698
+ return np.asarray(current_filtration, dtype=self.dtype)
9521
9699
 
9522
- def persistence_approximation(self, **kwargs):
9523
- from multipers.multiparameter_module_approximation import module_approximation
9524
- return module_approximation(self, **kwargs)
9525
9700
 
9526
9701
 
9527
9702
  def get_skeleton(self, dimension)->Iterable[tuple[np.ndarray,np.ndarray]]:
@@ -10098,7 +10273,6 @@ cdef class SimplexTreeMulti_Ff64:
10098
10273
  self,
10099
10274
  filtration_grid:np.ndarray|list|None=None,
10100
10275
  bool coordinate_values=True,
10101
- bool force=False,
10102
10276
  str strategy:_available_strategies = "exact",
10103
10277
  resolution:Optional[int|list[int]] = None,
10104
10278
  bool coordinates = False,
@@ -10114,8 +10288,6 @@ cdef class SimplexTreeMulti_Ff64:
10114
10288
  :param coordinate_values: If true, the filtrations values of the simplices will be set to the coordinate of the filtration grid.
10115
10289
  :type coordinate_values: bool
10116
10290
  """
10117
- if not force and self.is_squeezed:
10118
- raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
10119
10291
 
10120
10292
  if grid_strategy is not None:
10121
10293
  warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
@@ -10125,7 +10297,7 @@ cdef class SimplexTreeMulti_Ff64:
10125
10297
  warn("(copy warning) Squeezing an already squeezed slicer.")
10126
10298
  temp = self.unsqueeze()
10127
10299
  subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
10128
- return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
10300
+ return temp.grid_squeeze(sanitize_grid(subgrid, numpyfy=True), coordinates=coordinates, inplace=inplace)
10129
10301
 
10130
10302
  #TODO : multi-critical
10131
10303
  if filtration_grid is None:
@@ -715,10 +715,29 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
715
715
  preincrement(it)
716
716
 
717
717
 
718
+ def _get_raw_filtration(self):
719
+ {{if is_kcritical}}
720
+ raise NotImplementedError("Not implemented for multicritical filtrations")
721
+ {{else}}
722
+ if self.is_squeezed:
723
+ raise NotImplementedError("Not implemented for squeezed filtrations")
724
+ cdef int num_parameters = self.num_parameters
725
+ cdef {{CTYPE}}[:,:] current_filtration = np.empty((self.num_simplices, self.num_parameters), dtype=self.dtype)
726
+
727
+ cdef Simplex_tree_multi_simplices_iterator[{{FSHORT}}] it = self.get_ptr().get_simplices_iterator_begin()
728
+ cdef Simplex_tree_multi_simplices_iterator[{{FSHORT}}] end = self.get_ptr().get_simplices_iterator_end()
729
+
730
+ cdef int i=0
731
+ with nogil:
732
+ while it != end:
733
+ pair_sf = <pair[simplex_type, {{FSHORT}}*]> self.get_ptr().get_simplex_and_filtration(dereference(it))
734
+ for j in range(num_parameters):
735
+ current_filtration[i,j] = dereference(pair_sf.second)[j]
736
+ preincrement(it)
737
+ i = i+1
738
+ return np.asarray(current_filtration, dtype=self.dtype)
739
+ {{endif}}
718
740
 
719
- def persistence_approximation(self, **kwargs):
720
- from multipers.multiparameter_module_approximation import module_approximation
721
- return module_approximation(self, **kwargs)
722
741
 
723
742
 
724
743
  def get_skeleton(self, dimension)->Iterable[tuple[np.ndarray,np.ndarray]]:
@@ -869,7 +888,6 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
869
888
  """
870
889
  return self.get_ptr().prune_above_dimension(dimension)
871
890
 
872
- {{if not is_kcritical}}
873
891
  def expansion(self, int max_dim)->SimplexTreeMulti_{{FSHORT}}:
874
892
  """Expands the simplex tree containing only its one skeleton
875
893
  until dimension max_dim.
@@ -905,7 +923,6 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
905
923
  with nogil:
906
924
  out = self.get_ptr().make_filtration_non_decreasing()
907
925
  return out
908
- {{endif}}
909
926
 
910
927
  def reset_filtration(self, filtration, min_dim = 0)->SimplexTreeMulti_{{FSHORT}}:
911
928
  """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the
@@ -1328,7 +1345,6 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
1328
1345
  self,
1329
1346
  filtration_grid:np.ndarray|list|None=None,
1330
1347
  bool coordinate_values=True,
1331
- bool force=False,
1332
1348
  str strategy:_available_strategies = "exact",
1333
1349
  resolution:Optional[int|list[int]] = None,
1334
1350
  bool coordinates = False,
@@ -1344,8 +1360,6 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
1344
1360
  :param coordinate_values: If true, the filtrations values of the simplices will be set to the coordinate of the filtration grid.
1345
1361
  :type coordinate_values: bool
1346
1362
  """
1347
- if not force and self.is_squeezed:
1348
- raise Exception("SimplexTree already squeezed, use `force=True` if that's really what you want to do.")
1349
1363
 
1350
1364
  if grid_strategy is not None:
1351
1365
  warn("`grid_strategy` is deprecated, use `strategy` instead.",DeprecationWarning)
@@ -1355,7 +1369,7 @@ cdef class SimplexTreeMulti_{{FSHORT}}:
1355
1369
  warn("(copy warning) Squeezing an already squeezed slicer.")
1356
1370
  temp = self.unsqueeze()
1357
1371
  subgrid = compute_grid(self.filtration_grid, strategy=strategy, resolution=resolution)
1358
- return temp.grid_squeeze(subgrid, coordinates=coordinates, inplace=inplace)
1372
+ return temp.grid_squeeze(sanitize_grid(subgrid, numpyfy=True), coordinates=coordinates, inplace=inplace)
1359
1373
 
1360
1374
  #TODO : multi-critical
1361
1375
  if filtration_grid is None:
Binary file