multipers 2.3.1__cp313-cp313-win_amd64.whl → 2.3.2b1__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.
- 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.cp313-win_amd64.pyd +0 -0
- multipers/grids.cp313-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.cp313-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.cp313-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.cp313-win_amd64.pyd +0 -0
- multipers/multiparameter_module_approximation.pyx +22 -6
- multipers/plots.py +1 -0
- multipers/point_measure.cp313-win_amd64.pyd +0 -0
- multipers/point_measure.pyx +6 -2
- multipers/simplex_tree_multi.cp313-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.cp313-win_amd64.pyd +0 -0
- multipers/slicer.pxd +719 -237
- multipers/slicer.pxd.tp +22 -6
- multipers/slicer.pyx +5311 -1364
- 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
multipers/mma_structures.pyx.tp
CHANGED
|
@@ -118,6 +118,11 @@ cdef class PySummand_{{SHORT}}:
|
|
|
118
118
|
return v[0].num_parameters()
|
|
119
119
|
v = self.sum.get_death_list()
|
|
120
120
|
return v[0].num_parameters()
|
|
121
|
+
def __eq__(self, PySummand_{{SHORT}} other):
|
|
122
|
+
return self.sum == other.sum
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
121
126
|
|
|
122
127
|
cdef inline get_summand_filtration_values_{{SHORT}}(Summand[{{CTYPE}}] summand):
|
|
123
128
|
r"""
|
|
@@ -182,6 +187,10 @@ cdef class PyModule_{{SHORT}}:
|
|
|
182
187
|
|
|
183
188
|
cdef set(self, Module[{{CTYPE}}] m):
|
|
184
189
|
self.cmod = m
|
|
190
|
+
|
|
191
|
+
def __eq__(self, PyModule_{{SHORT}} other):
|
|
192
|
+
return self.cmod == other.cmod
|
|
193
|
+
|
|
185
194
|
def merge(self, PyModule_{{SHORT}} other, int dim=-1):
|
|
186
195
|
r"""
|
|
187
196
|
Merges two modules into one
|
|
@@ -197,7 +206,9 @@ cdef class PyModule_{{SHORT}}:
|
|
|
197
206
|
Copy module from a memory pointer. Unsafe.
|
|
198
207
|
"""
|
|
199
208
|
self.cmod = move(dereference(<Module[{{CTYPE}}]*>(module_ptr)))
|
|
200
|
-
def set_box(self,
|
|
209
|
+
def set_box(self, box):
|
|
210
|
+
assert len(box) == 2, "Box format is [low, hight]"
|
|
211
|
+
pybox = PyBox_{{SHORT}}(box[0], box[1])
|
|
201
212
|
cdef Box[{{CTYPE}}] cbox = pybox.box
|
|
202
213
|
with nogil:
|
|
203
214
|
self.cmod.set_box(cbox)
|
|
@@ -982,8 +993,8 @@ cdef dump_summand_{{SHORT}}(Summand[{{CTYPE}}]& summand):
|
|
|
982
993
|
cdef vector[One_critical_filtration[{{CTYPE}}]] births = summand.get_birth_list()
|
|
983
994
|
cdef vector[One_critical_filtration[{{CTYPE}}]] deaths = summand.get_death_list()
|
|
984
995
|
return (
|
|
985
|
-
_vff21cview_{{SHORT}}(births
|
|
986
|
-
_vff21cview_{{SHORT}}(deaths
|
|
996
|
+
np.array(_vff21cview_{{SHORT}}(births)),
|
|
997
|
+
np.array(_vff21cview_{{SHORT}}(deaths)),
|
|
987
998
|
summand.get_dimension(),
|
|
988
999
|
)
|
|
989
1000
|
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
#include <limits>
|
|
29
29
|
#include <oneapi/tbb/parallel_for.h>
|
|
30
30
|
#include <string>
|
|
31
|
+
#include <type_traits>
|
|
31
32
|
#include <utility>
|
|
32
33
|
#include <vector>
|
|
33
34
|
|
|
@@ -88,6 +89,8 @@ class Module {
|
|
|
88
89
|
const bool threshold);
|
|
89
90
|
typename module_type::iterator begin();
|
|
90
91
|
typename module_type::iterator end();
|
|
92
|
+
typename module_type::const_iterator begin() const;
|
|
93
|
+
typename module_type::const_iterator end() const;
|
|
91
94
|
|
|
92
95
|
void clean();
|
|
93
96
|
void fill(const value_type precision);
|
|
@@ -192,6 +195,16 @@ class Module {
|
|
|
192
195
|
|
|
193
196
|
std::vector<int> inline get_degree_splits() const;
|
|
194
197
|
|
|
198
|
+
inline friend bool operator==(const Module &a, const Module &b) {
|
|
199
|
+
if (a.get_dimension() != b.get_dimension()) return false;
|
|
200
|
+
if (a.box_ != b.box_) return false;
|
|
201
|
+
if (a.size() != b.size()) return false;
|
|
202
|
+
for (auto i : std::views::iota(0u, a.size())) {
|
|
203
|
+
if (a[i] != b[i]) return false;
|
|
204
|
+
}
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
195
208
|
private:
|
|
196
209
|
module_type module_;
|
|
197
210
|
Box<value_type> box_;
|
|
@@ -281,6 +294,10 @@ class Summand {
|
|
|
281
294
|
// std::swap(sum1.updateDistance_, sum2.updateDistance_);
|
|
282
295
|
};
|
|
283
296
|
|
|
297
|
+
friend bool operator==(const Summand &a, const Summand &b) {
|
|
298
|
+
return a.dimension_ == b.dimension_ && a.birth_corners_ == b.birth_corners_ && a.death_corners_ == b.death_corners_;
|
|
299
|
+
}
|
|
300
|
+
|
|
284
301
|
bool contains(const filtration_type &x) const;
|
|
285
302
|
|
|
286
303
|
inline Box<value_type> get_bounds() const {
|
|
@@ -812,11 +829,21 @@ inline typename Module<value_type>::module_type::iterator Module<value_type>::be
|
|
|
812
829
|
return module_.begin();
|
|
813
830
|
}
|
|
814
831
|
|
|
832
|
+
template <typename value_type>
|
|
833
|
+
inline typename Module<value_type>::module_type::const_iterator Module<value_type>::begin() const {
|
|
834
|
+
return module_.cbegin();
|
|
835
|
+
}
|
|
836
|
+
|
|
815
837
|
template <typename value_type>
|
|
816
838
|
inline typename Module<value_type>::module_type::iterator Module<value_type>::end() {
|
|
817
839
|
return module_.end();
|
|
818
840
|
}
|
|
819
841
|
|
|
842
|
+
template <typename value_type>
|
|
843
|
+
inline typename Module<value_type>::module_type::const_iterator Module<value_type>::end() const {
|
|
844
|
+
return module_.cend();
|
|
845
|
+
}
|
|
846
|
+
|
|
820
847
|
template <typename value_type>
|
|
821
848
|
inline void Module<value_type>::add_summand(Summand<value_type> summand, int degree) {
|
|
822
849
|
if (degree >= 0) summand.set_dimension(degree);
|
|
@@ -2046,14 +2073,16 @@ const Gudhi::multi_filtration::Multi_critical_filtration<value_type> &Summand<va
|
|
|
2046
2073
|
|
|
2047
2074
|
template <typename value_type>
|
|
2048
2075
|
inline void Summand<value_type>::clean() {
|
|
2049
|
-
// birth_corners_.erase(
|
|
2050
|
-
//
|
|
2051
|
-
//
|
|
2052
|
-
//
|
|
2053
|
-
//
|
|
2054
|
-
//
|
|
2055
|
-
//
|
|
2056
|
-
//
|
|
2076
|
+
// birth_corners_.erase(std::remove_if(birth_corners_.begin(),
|
|
2077
|
+
// birth_corners_.end(),
|
|
2078
|
+
// [](const std::vector<value_type> &bp) {
|
|
2079
|
+
// // return std::any_of(
|
|
2080
|
+
// // bp.begin(), bp.end(),
|
|
2081
|
+
// // [](float value) { return !std::isfinite(value); });
|
|
2082
|
+
// bp.size() == 0;
|
|
2083
|
+
// }),
|
|
2084
|
+
// birth_corners_.end());
|
|
2085
|
+
// birth_corners_.simplify();
|
|
2057
2086
|
// TODO : clean
|
|
2058
2087
|
}
|
|
2059
2088
|
|
|
@@ -2064,14 +2093,15 @@ inline void Summand<value_type>::complete_birth(const value_type precision) {
|
|
|
2064
2093
|
for (std::size_t i = 0; i < birth_corners_.num_generators(); i++) {
|
|
2065
2094
|
for (std::size_t j = i + 1; j < birth_corners_.num_generators(); j++) {
|
|
2066
2095
|
value_type dinf = d_inf(birth_corners_[i], birth_corners_[j]);
|
|
2067
|
-
if (dinf < .99 * precision) {
|
|
2096
|
+
if (dinf < .99 * precision) { // for machine error ?
|
|
2068
2097
|
_factorize_min(birth_corners_[i], birth_corners_[j]);
|
|
2069
|
-
birth_corners_[j]
|
|
2098
|
+
birth_corners_[j] = std::remove_reference_t<decltype(birth_corners_[j])>::inf();
|
|
2070
2099
|
i++;
|
|
2071
2100
|
}
|
|
2072
2101
|
}
|
|
2073
2102
|
}
|
|
2074
|
-
|
|
2103
|
+
birth_corners_.simplify();
|
|
2104
|
+
// _clean(birth_corners_);
|
|
2075
2105
|
}
|
|
2076
2106
|
|
|
2077
2107
|
template <typename value_type>
|
|
@@ -2083,12 +2113,14 @@ inline void Summand<value_type>::complete_death(const value_type precision) {
|
|
|
2083
2113
|
value_type d = d_inf(death_corners_[i], death_corners_[j]);
|
|
2084
2114
|
if (d < .99 * precision) {
|
|
2085
2115
|
_factorize_max(death_corners_[i], death_corners_[j]);
|
|
2086
|
-
death_corners_[j]
|
|
2116
|
+
death_corners_[j] = std::remove_reference_t<decltype(death_corners_[j])>::minus_inf();
|
|
2087
2117
|
i++;
|
|
2088
2118
|
}
|
|
2089
2119
|
}
|
|
2090
2120
|
}
|
|
2091
|
-
|
|
2121
|
+
|
|
2122
|
+
death_corners_.simplify();
|
|
2123
|
+
// _clean(death_corners_);
|
|
2092
2124
|
}
|
|
2093
2125
|
|
|
2094
2126
|
template <typename value_type>
|
|
Binary file
|
|
@@ -14,6 +14,7 @@ import numpy as np
|
|
|
14
14
|
from typing import List
|
|
15
15
|
from joblib import Parallel, delayed
|
|
16
16
|
import sys
|
|
17
|
+
from warnings import warn
|
|
17
18
|
|
|
18
19
|
###########################################################################
|
|
19
20
|
## CPP CLASSES
|
|
@@ -56,15 +57,20 @@ def module_approximation_from_slicer(
|
|
|
56
57
|
bool threshold=False,
|
|
57
58
|
bool verbose=False,
|
|
58
59
|
list[float] direction = [],
|
|
60
|
+
bool warnings = True,
|
|
59
61
|
)->PyModule_type:
|
|
60
62
|
|
|
61
63
|
cdef Module[float] mod_f32
|
|
62
64
|
cdef Module[double] mod_f64
|
|
63
65
|
cdef intptr_t ptr
|
|
64
66
|
if not slicer.is_vine:
|
|
65
|
-
|
|
67
|
+
if warnings:
|
|
68
|
+
warn(r"(copy warning) Got a non-vine slicer as an input. Use `vineyard=True` to remove this copy.")
|
|
66
69
|
from multipers._slicer_meta import Slicer
|
|
67
70
|
slicer = Slicer(slicer, vineyard=True, backend="matrix")
|
|
71
|
+
if slicer.is_squeezed:
|
|
72
|
+
raise ValueError("Got a squeezed slicer. Should have been unsqueezed before !")
|
|
73
|
+
|
|
68
74
|
direction_ = np.asarray(direction, dtype=slicer.dtype)
|
|
69
75
|
if slicer.dtype == np.float32:
|
|
70
76
|
approx_mod = PyModule_f32()
|
|
@@ -96,7 +102,7 @@ def module_approximation(
|
|
|
96
102
|
bool complete=True,
|
|
97
103
|
bool threshold=False,
|
|
98
104
|
bool verbose=False,
|
|
99
|
-
bool
|
|
105
|
+
bool ignore_warnings=False,
|
|
100
106
|
id="",
|
|
101
107
|
list[float] direction = [],
|
|
102
108
|
list[int] swap_box_coords = [],
|
|
@@ -156,10 +162,10 @@ def module_approximation(
|
|
|
156
162
|
if len(input) == 0:
|
|
157
163
|
return PyModule_f64()
|
|
158
164
|
if n_jobs <= 1:
|
|
159
|
-
modules = tuple(module_approximation(slicer, box, max_error, nlines, slicer_backend, minpres, degree, complete, threshold, verbose,
|
|
165
|
+
modules = tuple(module_approximation(slicer, box, max_error, nlines, slicer_backend, minpres, degree, complete, threshold, verbose, ignore_warnings, id, direction, swap_box_coords) for slicer in input)
|
|
160
166
|
else:
|
|
161
167
|
modules = tuple(Parallel(n_jobs=n_jobs, prefer="threads")(
|
|
162
|
-
delayed(module_approximation)(slicer, box, max_error, nlines, slicer_backend, minpres, degree, complete, threshold, verbose,
|
|
168
|
+
delayed(module_approximation)(slicer, box, max_error, nlines, slicer_backend, minpres, degree, complete, threshold, verbose, ignore_warnings, id, direction, swap_box_coords)
|
|
163
169
|
for slicer in input
|
|
164
170
|
))
|
|
165
171
|
mod = PyModule_f64().set_box(PyBox_f64(*modules[0].get_box()))
|
|
@@ -168,6 +174,11 @@ def module_approximation(
|
|
|
168
174
|
return mod
|
|
169
175
|
if len(input) == 0:
|
|
170
176
|
return PyModule_f64()
|
|
177
|
+
if input.is_squeezed:
|
|
178
|
+
if not ignore_warnings:
|
|
179
|
+
warn("(copy warning) Got a squeezed input. ")
|
|
180
|
+
input = input.unsqueeze()
|
|
181
|
+
|
|
171
182
|
if box is None:
|
|
172
183
|
if is_simplextree_multi(input):
|
|
173
184
|
box = input.filtration_bounds()
|
|
@@ -192,11 +203,16 @@ def module_approximation(
|
|
|
192
203
|
if max_error <= 0:
|
|
193
204
|
max_error = (prod/nlines)**(1/(num_parameters-1))
|
|
194
205
|
|
|
195
|
-
if not
|
|
206
|
+
if not ignore_warnings and prod >= 10_000:
|
|
196
207
|
raise ValueError(f"""
|
|
197
208
|
Warning : the number of lines (around {np.round(prod)}) may be too high.
|
|
209
|
+
This may be due to extreme box or filtration bounds :
|
|
210
|
+
|
|
211
|
+
{box=}
|
|
212
|
+
|
|
198
213
|
Try to increase the precision parameter, or set `ignore_warning=True` to compute this module.
|
|
199
|
-
Returning the trivial module.
|
|
214
|
+
Returning the trivial module.
|
|
215
|
+
"""
|
|
200
216
|
)
|
|
201
217
|
if is_simplextree_multi(input):
|
|
202
218
|
from multipers._slicer_meta import Slicer
|
multipers/plots.py
CHANGED
|
@@ -137,6 +137,7 @@ def plot_signed_measure(signed_measure, threshold=None, ax=None, **plt_kwargs):
|
|
|
137
137
|
else:
|
|
138
138
|
pts_ = pts
|
|
139
139
|
threshold = np.max(np.ma.masked_invalid(pts_), axis=0)
|
|
140
|
+
threshold = np.max([threshold, [plt.gca().get_xlim()[1], plt.gca().get_ylim()[1]]], axis=0)
|
|
140
141
|
if isinstance(pts, np.ndarray):
|
|
141
142
|
pass
|
|
142
143
|
else:
|
|
Binary file
|
multipers/point_measure.pyx
CHANGED
|
@@ -89,6 +89,7 @@ def integrate_measure(
|
|
|
89
89
|
grid_strategy:str="regular",
|
|
90
90
|
resolution:int|list[int]=100,
|
|
91
91
|
bool return_grid=False,
|
|
92
|
+
bool plot=False,
|
|
92
93
|
**get_fitration_kwargs,
|
|
93
94
|
):
|
|
94
95
|
"""
|
|
@@ -126,6 +127,9 @@ def integrate_measure(
|
|
|
126
127
|
for i in range(num_pts):
|
|
127
128
|
cone = tuple(slice(c,r) for r,c in zip(resolution,pts_coords[:,i]))
|
|
128
129
|
out[cone] += weights[i]
|
|
130
|
+
if plot:
|
|
131
|
+
from multipers.plots import plot_surface
|
|
132
|
+
plot_surface(filtration_grid, out, discrete_surface=True)
|
|
129
133
|
if return_grid:
|
|
130
134
|
return out,filtration_grid
|
|
131
135
|
return out
|
|
@@ -211,7 +215,7 @@ def zero_out_sm(pts,weights, mass_default):
|
|
|
211
215
|
C = np.concatenate([C, np.ones((C.shape[0],1))], axis=1).astype(np.bool_)
|
|
212
216
|
|
|
213
217
|
# signs of each corner
|
|
214
|
-
Cw = 1-2*((~C).sum(axis=1)
|
|
218
|
+
Cw = 1-2*((~C).sum(axis=1) & 1)
|
|
215
219
|
|
|
216
220
|
# something useless in the end to ensure that the shape is correct (as we added 1 in pts)
|
|
217
221
|
mass_default = np.concatenate([mass_default,[np.nan]])
|
|
@@ -299,7 +303,7 @@ def barcode_from_rank_sm(
|
|
|
299
303
|
return out
|
|
300
304
|
|
|
301
305
|
|
|
302
|
-
def estimate_rank_from_rank_sm(sm:tuple, a, b)
|
|
306
|
+
def estimate_rank_from_rank_sm(sm:tuple, a, b)->np.int64:
|
|
303
307
|
"""
|
|
304
308
|
Given a rank signed measure (sm) and two points (a) and (b),
|
|
305
309
|
estimates the rank between these two points.
|
|
Binary file
|
multipers/simplex_tree_multi.pxd
CHANGED
|
@@ -118,6 +118,7 @@ cdef extern from "Simplex_tree_multi_interface.h" namespace "Gudhi::multiparamet
|
|
|
118
118
|
void to_std_linear_projection(intptr_t, vector[double]) nogil
|
|
119
119
|
void squeeze_filtration_inplace(vector[vector[double]] &, bool) nogil
|
|
120
120
|
void squeeze_filtration(intptr_t, vector[vector[double]] &) nogil
|
|
121
|
+
void unsqueeze_filtration(intptr_t, vector[vector[double]] &) nogil
|
|
121
122
|
vector[vector[vector[value_type]]] get_filtration_values(const vector[int]&) nogil
|
|
122
123
|
|
|
123
124
|
|