Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update from gudhi #20

Merged
merged 10 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions docs/notebooks/degree_rips_interface.ipynb

Large diffs are not rendered by default.

51 changes: 31 additions & 20 deletions docs/notebooks/graph_autodiff.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,20 @@
"execution_count": 4,
"id": "1aa47583-05ef-4171-a46c-2bd9233432ce",
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/hschreiber/micromamba/envs/multipers-old/lib/python3.12/site-packages/torch_geometric/data/dataset.py:238: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",
" if osp.exists(f) and torch.load(f) != _repr(self.pre_transform):\n",
"/home/hschreiber/micromamba/envs/multipers-old/lib/python3.12/site-packages/torch_geometric/data/dataset.py:246: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",
" if osp.exists(f) and torch.load(f) != _repr(self.pre_filter):\n",
"/home/hschreiber/micromamba/envs/multipers-old/lib/python3.12/site-packages/torch_geometric/io/fs.py:215: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",
" return torch.load(f, map_location)\n"
]
}
],
"source": [
"transform = T.Compose([\n",
" # T.GDC(diffusion_kwargs={\n",
Expand Down Expand Up @@ -111,7 +124,7 @@
{
"data": {
"text/plain": [
"(torch.Size([13092, 56]), torch.Size([1534, 56]), torch.Size([14479, 56]))"
"(torch.Size([13092, 56]), torch.Size([1376, 56]), torch.Size([14479, 56]))"
]
},
"execution_count": 6,
Expand Down Expand Up @@ -470,7 +483,7 @@
"output_type": "stream",
"text": [
"[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (d*e)*Exp(-1/2*(c|TensorProd(a-b,a-b))) with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,9,2), d=Var(3,1,2), e=Var(4,1,0) ... OK\n",
"[pyKeOps] Compiling pykeops cpp ad692f20e1 module ... OK\n"
"[pyKeOps] Compiling pykeops cpp fd51638efa module ... OK\n"
]
},
{
Expand Down Expand Up @@ -590,17 +603,17 @@
"output_type": "stream",
"text": [
"[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (d*e)*Exp(-1/2*(c|TensorProd(a-b,a-b))) with a=Var(0,2,0), b=Var(1,2,1), c=Var(2,4,2), d=Var(3,1,2), e=Var(4,1,0) ... OK\n",
"[pyKeOps] Compiling pykeops cpp 009dd433bc module ... OK\n"
"[pyKeOps] Compiling pykeops cpp 947eef4777 module ... OK\n"
]
},
{
"data": {
"text/plain": [
"tensor([[0.5023, 0.4977],\n",
" [0.5425, 0.4575],\n",
" [0.5429, 0.4571],\n",
" [0.5452, 0.4548],\n",
" [0.5418, 0.4582]], grad_fn=<SliceBackward0>)"
"tensor([[0.6072, 0.3928],\n",
" [0.3750, 0.6250],\n",
" [0.3767, 0.6233],\n",
" [0.3420, 0.6580],\n",
" [0.3752, 0.6248]], grad_fn=<SliceBackward0>)"
]
},
"execution_count": 20,
Expand Down Expand Up @@ -637,38 +650,36 @@
"cell_type": "code",
"execution_count": 22,
"id": "2ce73fcb-0570-43ca-914e-81b37e3702e2",
"metadata": {
"scrolled": true
},
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Current acc 0.783, loss 0.6672385334968567, constant to 0: 0%| | 0/200 [00:00<?, ?it/s]"
"Current acc 0.214, loss 0.8241797685623169, : 0%| | 0/200 [00:01<?, ?it/s]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-1/2*((f*(d*e))*(MatVecMult(c,a-b)+VecMatMult(a-b,c))))*Exp(-1/2*(c|TensorProd(a-b,a-b))) with a=Var(0,2,0), b=Var(1,2,1), c=Var(2,4,2), d=Var(3,1,2), e=Var(4,1,0), f=Var(5,1,1) ... OK\n",
"[pyKeOps] Compiling pykeops cpp 1f55a92ec3 module ... OK\n",
"[pyKeOps] Compiling pykeops cpp c836920a74 module ... OK\n",
"[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (1/2*((f*(d*e))*(MatVecMult(c,a-b)+VecMatMult(a-b,c))))*Exp(-1/2*(c|TensorProd(a-b,a-b))) with a=Var(0,2,0), b=Var(1,2,1), c=Var(2,4,2), d=Var(3,1,2), e=Var(4,1,0), f=Var(5,1,1) ... OK\n",
"[pyKeOps] Compiling pykeops cpp 866cdcb56f module ... OK\n",
"[pyKeOps] Compiling pykeops cpp dd41e8c2a6 module ... OK\n",
"[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (-1/2*((f*(d*e))*TensorProd(a-b,a-b)))*Exp(-1/2*(c|TensorProd(a-b,a-b))) with a=Var(0,2,0), b=Var(1,2,1), c=Var(2,4,2), d=Var(3,1,2), e=Var(4,1,0), f=Var(5,1,1) ... OK\n",
"[pyKeOps] Compiling pykeops cpp 0e50e41c48 module ... OK\n",
"[pyKeOps] Compiling pykeops cpp d4f9325c2b module ... OK\n",
"[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (e*f)*Exp(-1/2*(c|TensorProd(a-b,a-b))) with a=Var(0,2,0), b=Var(1,2,1), c=Var(2,4,2), e=Var(4,1,0), f=Var(5,1,1) ... OK\n",
"[pyKeOps] Compiling pykeops cpp 307f250184 module ... OK\n",
"[pyKeOps] Compiling pykeops cpp e25a464c96 module ... OK\n",
"[KeOps] Generating code for Sum_Reduction reduction (with parameters 0) of formula (d*f)*Exp(-1/2*(c|TensorProd(a-b,a-b))) with a=Var(0,2,0), b=Var(1,2,1), c=Var(2,4,2), d=Var(3,1,2), f=Var(5,1,1) ... OK\n",
"[pyKeOps] Compiling pykeops cpp 6bc3bf3286 module ... OK\n"
"[pyKeOps] Compiling pykeops cpp b01d4ec1ad module ... OK\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Current acc 0.931, loss 0.38253268599510193, : 100%|████████████████████████████████████████████████████████████████████████| 200/200 [06:28<00:00, 1.94s/it]\n"
"Current acc 0.783, loss 0.5174151062965393, constant to 0: 100%|████████████████████████████████████████████████████████████| 200/200 [06:03<00:00, 1.82s/it]\n"
]
}
],
Expand Down Expand Up @@ -704,7 +715,7 @@
{
"data": {
"text/plain": [
"(tensor(0.5871, grad_fn=<DivBackward1>), tensor(0.7317))"
"(tensor(0.4847, grad_fn=<DivBackward1>), tensor(0.9268))"
]
},
"execution_count": 23,
Expand Down
16 changes: 8 additions & 8 deletions docs/notebooks/graph_classification.ipynb

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions docs/notebooks/molecular_embedding.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"/home/hschreiber/micromamba/envs/tmp/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
"/home/hschreiber/micromamba/envs/multipers-old/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n"
]
}
Expand Down Expand Up @@ -74,7 +74,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"Applying pipeline: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████| 23/23 [00:04<00:00, 5.29it/s]\n"
"Applying pipeline: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████| 23/23 [00:05<00:00, 4.16it/s]\n"
]
}
],
Expand Down Expand Up @@ -123,14 +123,14 @@
"text": [
"[KeOps] Warning : cuda was detected, but driver API could not be initialized. Switching to cpu only.\n",
"[KeOps] Generating code for Sum_Reduction reduction (with parameters 1) of formula (Exp(-1/2*Sum((a-b)**2))/c)*d with a=Var(0,3,0), b=Var(1,3,1), c=Var(2,1,2), d=Var(3,1,0) ... OK\n",
"[pyKeOps] Compiling pykeops cpp eb72609303 module ... OK\n"
"[pyKeOps] Compiling pykeops cpp 80a3564d3f module ... OK\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Applying pipeline: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████| 23/23 [00:07<00:00, 3.13it/s]\n"
"Applying pipeline: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████| 23/23 [00:08<00:00, 2.75it/s]\n"
]
},
{
Expand Down Expand Up @@ -186,7 +186,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"Applying pipeline: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████| 23/23 [00:05<00:00, 4.09it/s]\n"
"Applying pipeline: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████| 23/23 [00:06<00:00, 3.30it/s]\n"
]
},
{
Expand Down
24 changes: 13 additions & 11 deletions docs/notebooks/multipers_intro.ipynb

Large diffs are not rendered by default.

62 changes: 31 additions & 31 deletions docs/notebooks/rips_density_autodiff.ipynb

Large diffs are not rendered by default.

34 changes: 17 additions & 17 deletions docs/notebooks/simplex_tree_by_hand.ipynb

Large diffs are not rendered by default.

29 changes: 9 additions & 20 deletions docs/notebooks/time_series_classification.ipynb

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions multipers/filtration_conversions.pxd.tp
hschreiber marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Original file line number Diff line number Diff line change
Expand Up @@ -61,23 +61,25 @@ cdef inline vector[One_critical_filtration[{{CTYPE}}]] _py2v1c_{{SHORT}}(object


## CYTHON BUG: using tuples here will cause some weird issues.
cdef inline _ff21cview_{{SHORT}}(One_critical_filtration[{{CTYPE}}]* x, bool copy=False):
cdef inline _ff21cview_{{SHORT}}(One_critical_filtration[{{CTYPE}}]* x, bool copy=False, int duplicate=0):
cdef Py_ssize_t num_parameters = dereference(x).num_parameters()
if copy and duplicate and not dereference(x).is_finite():
return np.full(shape=duplicate, fill_value=dereference(x)[0])
cdef {{CTYPE}}[:] x_view = <{{CTYPE}}[:num_parameters]>(&(dereference(x)[0]))
return np.array(x_view) if copy else np.asarray(x_view)

cdef inline _ff2kcview_{{SHORT}}(Multi_critical_filtration[{{CTYPE}}]* x, bool copy=False):
cdef inline _ff2kcview_{{SHORT}}(Multi_critical_filtration[{{CTYPE}}]* x, bool copy=False, int duplicate=0):
cdef Py_ssize_t k = dereference(x).num_generators()
return [_ff21cview_{{SHORT}}(&(dereference(x)[i]), copy=copy) for i in range(k)]
return [_ff21cview_{{SHORT}}(&(dereference(x)[i]), copy=copy, duplicate=duplicate) for i in range(k)]


cdef inline _vff21cview_{{SHORT}}(vector[One_critical_filtration[{{CTYPE}}]]& x, bool copy = False):
cdef inline _vff21cview_{{SHORT}}(vector[One_critical_filtration[{{CTYPE}}]]& x, bool copy = False, int duplicate=0):
cdef Py_ssize_t num_stuff = x.size()
return [_ff21cview_{{SHORT}}(&(x[i]), copy=copy) for i in range(num_stuff)]
return [_ff21cview_{{SHORT}}(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]

cdef inline _vff2kcview_{{SHORT}}(vector[Multi_critical_filtration[{{CTYPE}}]]& x, bool copy = False):
cdef inline _vff2kcview_{{SHORT}}(vector[Multi_critical_filtration[{{CTYPE}}]]& x, bool copy = False, int duplicate=0):
cdef Py_ssize_t num_stuff = x.size()
return [_ff2kcview_{{SHORT}}(&(x[i]), copy=copy) for i in range(num_stuff)]
return [_ff2kcview_{{SHORT}}(&(x[i]), copy=copy, duplicate=duplicate) for i in range(num_stuff)]

{{endfor}}

4 changes: 2 additions & 2 deletions multipers/filtrations.pxd
hschreiber marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,13 @@ cdef extern from "gudhi/One_critical_filtration.h" namespace "Gudhi::multi_filtr
One_critical_filtration(int) nogil
One_critical_filtration& operator=(const One_critical_filtration&) except +
@staticmethod
vector[vector[value_type]] to_python(vector[One_critical_filtration]&) nogil const
@staticmethod
vector[value_type]& vector[value_type]() nogil

void push_to_least_common_upper_bound(One_critical_filtration[T]&) nogil
void pull_to_greatest_common_lower_bound(One_critical_filtration[T]&) nogil

bool is_finite() nogil


cdef extern from "gudhi/Multi_critical_filtration.h" namespace "Gudhi::multi_filtration":
cdef cppclass Multi_critical_filtration[T=*]:
Expand Down
33 changes: 19 additions & 14 deletions multipers/mma_structures.pyx.tp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import gudhi as gd
import numpy as np
from typing import List, Union
import pickle as pk
from math import isinf

###########################################################################
## CPP CLASSES
Expand Down Expand Up @@ -74,11 +73,11 @@ cdef class PySummand_{{SHORT}}:

def get_birth_list(self):
cdef vector[One_critical_filtration[{{CTYPE}}]] v = self.sum.get_birth_list()
return _vff21cview_{{SHORT}}(v, copy = True)
return _vff21cview_{{SHORT}}(v, copy = True, duplicate = self.num_parameters())

def get_death_list(self):
cdef vector[One_critical_filtration[{{CTYPE}}]] v = self.sum.get_death_list()
return _vff21cview_{{SHORT}}(v, copy = True)
return _vff21cview_{{SHORT}}(v, copy = True, duplicate = self.num_parameters())
@property
def degree(self)->int:
return self.sum.get_dimension()
Expand All @@ -95,25 +94,31 @@ cdef class PySummand_{{SHORT}}:
def dtype(self):
return {{PYTYPE}}

def num_parameters(self):
cdef vector[One_critical_filtration[{{CTYPE}}]] v = self.sum.get_birth_list()
if v[0].is_finite():
return v[0].num_parameters()
v = self.sum.get_death_list()
return v[0].num_parameters()

cdef inline get_summand_filtration_values_{{SHORT}}(Summand[{{CTYPE}}] summand):
"""
Returns a list (over parameter) of the filtrations values of this parameter.
"""
cdef vector[One_critical_filtration[{{CTYPE}}]] v = summand.get_birth_list()
births = _vff21cview_{{SHORT}}(v, copy=True)
v = summand.get_death_list()
deaths = _vff21cview_{{SHORT}}(v, copy=True)
cdef vector[One_critical_filtration[{{CTYPE}}]] vb = summand.get_birth_list()
cdef vector[One_critical_filtration[{{CTYPE}}]] vd = summand.get_death_list()

if len(births) == 1 and births[0].size == 1 and isinf(births[0][0]):
if len(deaths) == 1 and deaths[0].size == 1 and isinf(deaths[0][0]):
return []
if vb[0].is_finite():
if vd[0].is_finite():
pts = np.concatenate([_vff21cview_{{SHORT}}(vb, copy=True),
_vff21cview_{{SHORT}}(vd, copy=True)],axis=0)
else:
pts = np.array(deaths)
pts = np.array(_vff21cview_{{SHORT}}(vb, copy=True))
else:
if len(deaths) == 1 and deaths[0].size == 1 and isinf(deaths[0][0]):
pts = np.array(births)
if vd[0].is_finite():
pts = np.array(_vff21cview_{{SHORT}}(vd, copy=True))
else:
pts = np.concatenate([births,deaths],axis=0)
return []

num_parameters = pts.shape[1]
out = [np.unique(pts[:,parameter]) for parameter in range(num_parameters)]
Expand Down
6 changes: 3 additions & 3 deletions multipers/slicer.pyx.tp
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ cdef class {{PYTHON_TYPE}}:
Returns the current filtration values of the slicer.
"""
cdef vector[One_critical_filtration[{{C_VALUE_TYPE}}]] v = self.truc.get_filtration_values()
out = _vff21cview_{{SHORT}}(v, copy=True)
out = _vff21cview_{{SHORT}}(v, copy=True, duplicate=self.num_parameters)
return np.asarray(out)
def get_filtration_grid(self,grid_strategy:str="exact", **infer_grid_kwargs):
return mpg.compute_grid(
Expand All @@ -331,9 +331,9 @@ cdef class {{PYTHON_TYPE}}:
Returns a view of the filtration values, as a list of numpy arrays.
"""
{{if IS_KCRITICAL}}
return _vff2kcview_{{SHORT}}(self.truc.get_filtrations(), copy=True)
return _vff2kcview_{{SHORT}}(self.truc.get_filtrations(), copy=True, duplicate=self.num_parameters)
{{else}}
return _vff21cview_{{SHORT}}(self.truc.get_filtrations(), copy=True)
return _vff21cview_{{SHORT}}(self.truc.get_filtrations(), copy=True, duplicate=self.num_parameters)
{{endif}}

def get_dimensions(self)-> np.ndarray:
Expand Down
2 changes: 1 addition & 1 deletion multipers/tests/test_mma.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def test_1():
st.insert([0, 1], [1, 1])
mma_pymodule = st.persistence_approximation()
assert np.array_equal(mma_pymodule[0].get_birth_list(), [[0.0, 1.0], [1.0, 0.0]])
assert np.array_equal(mma_pymodule[0].get_death_list(), [[np.inf]])
assert np.array_equal(mma_pymodule[0].get_death_list(), [[np.inf, np.inf]])


def test_img():
Expand Down