diff options
author | vrouvrea <vrouvrea@636b058d-ea47-450e-bf9e-a15bfbe3eedb> | 2016-08-12 12:51:23 +0000 |
---|---|---|
committer | vrouvrea <vrouvrea@636b058d-ea47-450e-bf9e-a15bfbe3eedb> | 2016-08-12 12:51:23 +0000 |
commit | 359411b63f1d4698cca3413c0f00822f80243786 (patch) | |
tree | 607be22fce275298e8078423f50e9204d47805b4 /src | |
parent | 92751f7bb87d45469e260b7e5161bf6e375bf231 (diff) |
Fix tests and documentation
Add OFF file read for Alpha complex
Add PeriodicCubicalComplex
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/ST_cythonize@1432 636b058d-ea47-450e-bf9e-a15bfbe3eedb
Former-commit-id: 5a769f5402522fae801ebafee4d398d47d657be8
Diffstat (limited to 'src')
-rw-r--r-- | src/cython/doc/source/alpha_complex_user.rst | 2 | ||||
-rw-r--r-- | src/cython/doc/source/biblio.rst | 9 | ||||
-rw-r--r-- | src/cython/doc/source/cgal_citation.rst | 8 | ||||
-rw-r--r-- | src/cython/doc/source/cubical_complex_sum.rst | 3 | ||||
-rw-r--r-- | src/cython/doc/source/cubical_complex_user.rst | 144 | ||||
-rw-r--r-- | src/cython/doc/source/periodic_cubical_complex_ref.rst | 9 | ||||
-rw-r--r-- | src/cython/doc/source/persistent_cohomology_user.rst | 99 | ||||
-rw-r--r-- | src/cython/doc/source/simplex_tree_user.rst | 60 | ||||
-rw-r--r-- | src/cython/doc/source/witness_complex_sum.rst | 26 | ||||
-rw-r--r-- | src/cython/doc/source/witness_complex_user.rst | 23 | ||||
-rw-r--r-- | src/cython/gudhi.pyx.in | 1 | ||||
-rw-r--r-- | src/cython/src/cpp/Alpha_complex_interface.h | 5 | ||||
-rw-r--r-- | src/cython/src/cython/alpha_complex.pyx | 29 | ||||
-rw-r--r-- | src/cython/src/cython/cubical_complex.pyx | 21 | ||||
-rw-r--r-- | src/cython/src/cython/periodic_cubical_complex.pyx | 181 | ||||
-rw-r--r-- | src/cython/src/cython/rips_complex.pyx | 3 |
16 files changed, 594 insertions, 29 deletions
diff --git a/src/cython/doc/source/alpha_complex_user.rst b/src/cython/doc/source/alpha_complex_user.rst index c2a3c5bb..07bfcabf 100644 --- a/src/cython/doc/source/alpha_complex_user.rst +++ b/src/cython/doc/source/alpha_complex_user.rst @@ -153,7 +153,7 @@ Then, it is asked to display information about the alpha complex: .. testcode:: import gudhi - alpha_complex = gudhi.AlphaComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], + alpha_complex = gudhi.AlphaComplex(off_file='source/alphacomplexdoc.off', max_alpha_square=59.0) result_str = 'Alpha complex is of dimension ' + repr(alpha_complex.dimension()) + ' - ' + \ repr(alpha_complex.num_simplices()) + ' simplices - ' + \ diff --git a/src/cython/doc/source/biblio.rst b/src/cython/doc/source/biblio.rst index 66709265..b8e733ed 100644 --- a/src/cython/doc/source/biblio.rst +++ b/src/cython/doc/source/biblio.rst @@ -1,10 +1,7 @@ - - +============ +Bibliography +============ .. bibliography:: bibliography.bib :filter: docnames - :style: alpha - -.. bibliography:: how_to_cite_cgal.bib - :filter: docnames :style: unsrt diff --git a/src/cython/doc/source/cgal_citation.rst b/src/cython/doc/source/cgal_citation.rst new file mode 100644 index 00000000..bbc4ef9e --- /dev/null +++ b/src/cython/doc/source/cgal_citation.rst @@ -0,0 +1,8 @@ +============== +CGAL citations +============== + +.. + bibliography:: how_to_cite_cgal.bib + :filter: docnames + :style: unsrt diff --git a/src/cython/doc/source/cubical_complex_sum.rst b/src/cython/doc/source/cubical_complex_sum.rst index 60b47f54..4008a1fd 100644 --- a/src/cython/doc/source/cubical_complex_sum.rst +++ b/src/cython/doc/source/cubical_complex_sum.rst @@ -7,5 +7,6 @@ | img/Cubical_complex_representation.png | computational mathematics (specially rigorous numerics) and image | | | analysis. | +---------------------------------------------+----------------------------------------------------------------------+ -| :doc:`cubical_complex_user` | :doc:`cubical_complex_ref` | +| :doc:`cubical_complex_user` | * :doc:`cubical_complex_ref` | +| | * :doc:`periodic_cubical_complex_ref` | +---------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/source/cubical_complex_user.rst b/src/cython/doc/source/cubical_complex_user.rst index 2efff680..38ff978c 100644 --- a/src/cython/doc/source/cubical_complex_user.rst +++ b/src/cython/doc/source/cubical_complex_user.rst @@ -4,5 +4,147 @@ Cubical complex user manual Definition ---------- -.. include:: cubical_complex_sum.rst +===================================== ===================================== ===================================== +:Author: Pawel Dlotko :Introduced in: GUDHI PYTHON 1.4.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== ++---------------------------------------------+----------------------------------------------------------------------+ +| :doc:`cubical_complex_user` | * :doc:`cubical_complex_ref` | +| | * :doc:`periodic_cubical_complex_ref` | ++---------------------------------------------+----------------------------------------------------------------------+ + +The cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous +numerics) and image analysis. + +An *elementary interval* is an interval of a form :math:`[n,n+1]`, or :math:`[n,n]`, for :math:`n \in \mathcal{Z}`. +The first one is called *non-degenerate*, while the second one is a *degenerate* interval. A +*boundary of a elementary interval* is a chain :math:`\partial [n,n+1] = [n+1,n+1]-[n,n]` in case of +non-degenerated elementary interval and :math:`\partial [n,n] = 0` in case of degenerate elementary interval. An +*elementary cube* :math:`C` is a product of elementary intervals, :math:`C=I_1 \times \ldots \times I_n`. +*Embedding dimension* of a cube is n, the number of elementary intervals (degenerate or not) in the product. +A *dimension of a cube* :math:`C=I_1 \times ... \times I_n` is the number of non degenerate elementary +intervals in the product. A *boundary of a cube* :math:`C=I_1 \times \ldots \times I_n` is a chain obtained +in the following way: + +.. math:: + + \partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n). + +A *cubical complex* :math:`\mathcal{K}` is a collection of cubes closed under operation of taking boundary +(i.e. boundary of every cube from the collection is in the collection). A cube :math:`C` in cubical complex +:math:`\mathcal{K}` is *maximal* if it is not in a boundary of any other cube in :math:`\mathcal{K}`. A +*support* of a cube :math:`C` is the set in :math:`\mathbb{R}^n` occupied by :math:`C` (:math:`n` is the embedding +dimension of :math:`C`). + +Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical +complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may +be a set of two elements). + +For further details and theory of cubical complexes, please consult :cite:`kaczynski2004computational` as well as the +following paper :cite:`peikert2012topological`. + +Data structure. +--------------- + +The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in +:math:`\mathbb{R}^n`. This extra assumption allows for a memory efficient way of storing cubical complexes in a form +of so called bitmaps. Let +:math:`R = [b_1,e_1] \times \ldots \times [b_n,e_n]`, for :math:`b_1,...b_n,e_1,...,e_n \in \mathbb{Z}`, +:math:`b_i \leq d_i` be the considered rectangular region and let :math:`\mathcal{K}` be a filtered +cubical complex having the rectangle :math:`R` as its support. Note that the structure of the coordinate system gives +a way a lexicographical ordering of cells of :math:`\mathcal{K}`. This ordering is a base of the presented +bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector of the values +of filtration. This, together with dimension of :math:`\mathcal{K}` and the sizes of :math:`\mathcal{K}` in all +directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube +:math:`C \in \mathcal{K}`. + +.. image:: + img/Cubical_complex_representation.png + :align: center + :alt: Cubical complex. + +Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical +complexes in :math:`\mathbb{R}`. The number of all cubes in each direction is equal :math:`2n+1`, where :math:`n` is +the number of maximal cubes in the considered direction. Let us consider a cube at the position :math:`k` in the +bitmap. +Knowing the sizes of the bitmap, by a series of modulo operation, we can determine which elementary intervals are +present in the product that gives the cube :math:`C`. In a similar way, we can compute boundary and the coboundary of +each cube. Further details can be found in the literature. + +Input Format. +------------- + +In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star +filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users +who want to use the code directly. They can be found in the :doc:`cubical_complex_ref`. +Currently one input from a text file is used. It uses a format used already in +`Perseus software <http://www.sas.upenn.edu/~vnanda/perseus/>`_ by Vidit Nanda. +Below we are providing a description of the format. The first line contains a number d begin the dimension of the +bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each dimensions (3 and 3 +in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8 +20 4 7 6 5 in the example below). + +.. image:: + img/exampleBitmap.png + :align: center + :alt: Example of a input data. + +The input file for the following complex is: + +.. literalinclude:: cubicalcomplexdoc.txt + +.. centered:: cubicalcomplexdoc.txt + +.. testcode:: + + import gudhi + cubical_complex = gudhi.CubicalComplex(perseus_file='source/cubicalcomplexdoc.txt') + result_str = 'Cubical complex is of dimension ' + repr(cubical_complex.dimension()) + ' - ' + \ + repr(cubical_complex.num_simplices()) + ' simplices.' + print(result_str) + +the program output is: + +.. testoutput:: + + Cubical complex is of dimension 2 - 49 simplices. + +Periodic boundary conditions. +----------------------------- + +Often one would like to impose periodic boundary conditions to the cubical complex (cf. +:doc:`periodic_cubical_complex_ref`). +Let :math:`I_1\times ... \times I_n` be a box that is decomposed with a cubical complex :math:`\mathcal{K}`. +Imposing periodic boundary conditions in the direction i, means that the left and the right side of a complex +:math:`\mathcal{K}` are considered the same. In particular, if for a bitmap :math:`\mathcal{K}` periodic boundary +conditions are imposed in all directions, then complex :math:`\mathcal{K}` became n-dimensional torus. One can use +various constructors from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical +complex with periodic boundary conditions. One can also use Perseus style input files. To indicate periodic boundary +conditions in a given direction, then number of top dimensional cells in this direction have to be multiplied by -1. +For instance: + +.. literalinclude:: periodiccubicalcomplexdoc.txt + +.. centered:: periodiccubicalcomplexdoc.txt + +Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. + +.. testcode:: + + import gudhi + periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='source/periodiccubicalcomplexdoc.txt') + result_str = 'Periodic cubical complex is of dimension ' + repr(periodic_cc.dimension()) + ' - ' + \ + repr(periodic_cc.num_simplices()) + ' simplices.' + print(result_str) + +the program output is: + +.. testoutput:: + + Periodic cubical complex is of dimension 2 - 42 simplices. + +Examples. +--------- + +End user programs are available in cython/example/ folder. diff --git a/src/cython/doc/source/periodic_cubical_complex_ref.rst b/src/cython/doc/source/periodic_cubical_complex_ref.rst new file mode 100644 index 00000000..c6190a1b --- /dev/null +++ b/src/cython/doc/source/periodic_cubical_complex_ref.rst @@ -0,0 +1,9 @@ +Periodic cubical complex reference manual +######################################### + +.. autoclass:: gudhi.PeriodicCubicalComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.PeriodicCubicalComplex.__init__ diff --git a/src/cython/doc/source/persistent_cohomology_user.rst b/src/cython/doc/source/persistent_cohomology_user.rst index 41b6a3e3..33b19ce2 100644 --- a/src/cython/doc/source/persistent_cohomology_user.rst +++ b/src/cython/doc/source/persistent_cohomology_user.rst @@ -3,5 +3,102 @@ Persistent cohomology user manual ================================= Definition ---------- +===================================== ===================================== ===================================== +:Author: Clément Maria :Introduced in: GUDHI PYTHON 1.4.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== -.. include:: persistent_cohomology_sum.rst ++---------------------------------------------+----------------------------------------------------------------------+ +| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence | +| | feature for reference: | +| | | +| | * :doc:`alpha_complex_ref` | +| | * :doc:`cubical_complex_ref` | +| | * :doc:`simplex_tree_ref` | +| | * :doc:`witness_complex_ref` | ++---------------------------------------------+----------------------------------------------------------------------+ + + +Computation of persistent cohomology using the algorithm of :cite:`DBLP:journals/dcg/SilvaMV11` and +:cite:`DBLP:journals/corr/abs-1208-5018` and the Compressed Annotation Matrix implementation of +:cite:`DBLP:conf/esa/BoissonnatDM13`. + +The theory of homology consists in attaching to a topological space a sequence of (homology) groups, capturing global +topological features like connected components, holes, cavities, etc. Persistent homology studies the evolution -- +birth, life and death -- of these features when the topological space is changing. Consequently, the theory is +essentially composed of three elements: + +* topological spaces +* their homology groups +* an evolution scheme. + +Topological Spaces +------------------ + +Topological spaces are represented by simplicial complexes. +Let :math:`V = \{1, \cdots ,|V|\}` be a set of *vertices*. +A *simplex* :math:`\sigma` is a subset of vertices :math:`\sigma \subseteq V`. +A *simplicial complex* :math:`\mathbf{K}` on :math:`V` is a collection of simplices :math:`\{\sigma\}`, +:math:`\sigma \subseteq V`, such that :math:`\tau \subseteq \sigma \in \mathbf{K} \Rightarrow \tau \in \mathbf{K}`. +The dimension :math:`n=|\sigma|-1` of :math:`\sigma` is its number of elements minus 1. +A *filtration* of a simplicial complex is a function :math:`f:\mathbf{K} \rightarrow \mathbb{R}` satisfying +:math:`f(\tau)\leq f(\sigma)` whenever :math:`\tau \subseteq \sigma`. + +Homology +-------- + +For a ring :math:`\mathcal{R}`, the group of *n-chains*, denoted :math:`\mathbf{C}_n(\mathbf{K},\mathcal{R})`, of +:math:`\mathbf{K}` is the group of formal sums of n-simplices with :math:`\mathcal{R}` coefficients. The +*boundary operator* is a linear operator +:math:`\partial_n: \mathbf{C}_n(\mathbf{K},\mathcal{R}) \rightarrow \mathbf{C}_{n-1}(\mathbf{K},\mathcal{R})` +such that :math:`\partial_n \sigma = \partial_n [v_0, \cdots , v_n] = \sum_{i=0}^n (-1)^{i}[v_0,\cdots ,\widehat{v_i}, \cdots,v_n]`, +where :math:`\widehat{v_i}` means :math:`v_i` is omitted from the list. The chain groups form a sequence: + +.. math:: + + \cdots \ \ \mathbf{C}_n(\mathbf{K},\mathcal{R}) \xrightarrow{\ \partial_n\ } + \mathbf{C}_{n-1}(\mathbf{K},\mathcal{R}) \xrightarrow{\partial_{n-1}} \cdots \xrightarrow{\ \partial_2 \ } + \mathbf{C}_1(\mathbf{K},\mathcal{R}) \xrightarrow{\ \partial_1 \ } \mathbf{C}_0(\mathbf{K},\mathcal{R}) + +of finitely many groups :math:`\mathbf{C}_n(\mathbf{K},\mathcal{R})` and homomorphisms :math:`\partial_n`, indexed by +the dimension :math:`n \geq 0`. The boundary operators satisfy the property :math:`\partial_n \circ \partial_{n+1}=0` +for every :math:`n > 0` and we define the homology groups: + +.. math:: + + \mathbf{H}_n(\mathbf{K},\mathcal{R}) = \ker \partial_n / \mathrm{im} \ \partial_{n+1} + +We refer to :cite:`Munkres-elementsalgtop1984` for an introduction to homology +theory and to :cite:`DBLP:books/daglib/0025666` for an introduction to persistent homology. + +Indexing Scheme +--------------- + +"Changing" a simplicial complex consists in applying a simplicial map. An *indexing scheme* is a directed graph +together with a traversal order, such that two consecutive nodes in the graph are connected by an arrow (either forward +or backward). +The nodes represent simplicial complexes and the directed edges simplicial maps. + +From the computational point of view, there are two types of indexing schemes of interest in persistent homology: + +* linear ones + :math:`\bullet \longrightarrow \bullet \longrightarrow \cdots \longrightarrow \bullet \longrightarrow \bullet` + in persistent homology :cite:`DBLP:journals/dcg/ZomorodianC05`, +* zigzag ones + :math:`\bullet \longrightarrow \bullet \longleftarrow \cdots \longrightarrow \bullet \longleftarrow \bullet` + in zigzag persistent homology :cite:`DBLP:journals/focm/CarlssonS10`. + +These indexing schemes have a natural left-to-right traversal order, and we describe them with ranges and iterators. +In the current release of the Gudhi library, only the linear case is implemented. + +In the following, we consider the case where the indexing scheme is induced by a filtration. + +Ordering the simplices by increasing filtration values (breaking ties so as a simplex appears after its subsimplices of +same filtration value) provides an indexing scheme. + +Examples +-------- + +We provide several example files: run these examples with -h for details on their use. + +.. todo:: + examples for persistence diff --git a/src/cython/doc/source/simplex_tree_user.rst b/src/cython/doc/source/simplex_tree_user.rst index b07bd449..3a00f1ac 100644 --- a/src/cython/doc/source/simplex_tree_user.rst +++ b/src/cython/doc/source/simplex_tree_user.rst @@ -5,3 +5,63 @@ Definition ---------- .. include:: simplex_tree_sum.rst + +A simplicial complex :math:`\mathbf{K}` on a set of vertices :math:`V = \{1, \cdots ,|V|\}` is a collection of +simplices :math:`\{\sigma\}`, :math:`\sigma \subseteq V` such that +:math:`\tau \subseteq \sigma \in \mathbf{K} \rightarrow \tau \in \mathbf{K}`. The dimension :math:`n=|\sigma|-1` of +:math:`\sigma` is its number of elements minus `1`. + +A filtration of a simplicial complex is a function :math:`f:\mathbf{K} \rightarrow \mathbb{R}` satisfying +:math:`f(\tau)\leq f(\sigma)` whenever :math:`\tau \subseteq \sigma`. Ordering the simplices by increasing filtration +values (breaking ties so as a simplex appears after its subsimplices of same filtration value) provides an indexing +scheme. + + +Implementation +-------------- + +There are two implementation of complexes. The first on is the Simplex_tree data structure. +The simplex tree is an efficient and flexible data structure for representing general (filtered) simplicial complexes. +The data structure is described in :cite`boissonnatmariasimplextreealgorithmica`. + +The second one is the Hasse_complex. The Hasse complex is a data structure representing explicitly all co-dimension 1 +incidence relations in a complex. It is consequently faster when accessing the boundary of a simplex, but is less +compact and harder to construct from scratch. + +Example +------- + +.. testcode:: + + import gudhi + st = gudhi.SimplexTree() + if st.insert([0, 1]): + print("[0, 1] inserted") + if st.insert([0, 1, 2], filtration=4.0): + print("[0, 1, 2] inserted") + if st.find([0, 1]): + print("[0, 1] found") + print("num_vertices=", st.num_vertices()) + print("num_simplices=", st.num_simplices()) + print("skeleton_tree(2) =") + for sk_value in st.get_skeleton_tree(2): + print(sk_value) + + +The output is: + +.. testoutput:: + + [0, 1] inserted + [0, 1, 2] inserted + [0, 1] found + ('num_vertices=', 3) + ('num_simplices=', 7) + skeleton_tree(2) = + ([0, 1, 2], 4.0) + ([0, 1], 0.0) + ([0, 2], 4.0) + ([0], 0.0) + ([1, 2], 4.0) + ([1], 0.0) + ([2], 4.0) diff --git a/src/cython/doc/source/witness_complex_sum.rst b/src/cython/doc/source/witness_complex_sum.rst index a91ff01b..0d65d420 100644 --- a/src/cython/doc/source/witness_complex_sum.rst +++ b/src/cython/doc/source/witness_complex_sum.rst @@ -3,19 +3,23 @@ ===================================== ===================================== ===================================== +---------------------------------------------+----------------------------------------------------------------------+ -| .. image:: | Alpha_complex is a simplicial complex constructed from the finite | -| img/Witness_complex_representation.png | cells of a Delaunay Triangulation. | +| .. image:: | Witness complex :math:`Wit(W,L)` is a simplicial complex defined on | +| img/Witness_complex_representation.png | two sets of points in :math:`\mathbb{R}^D`:Wit(W,L)` is a simplicial | +| | complex defined on two sets of points in :math:`\mathbb{R}^D`: | | | | -| | The filtration value of each simplex is computed as the square of the| -| | circumradius of the simplex if the circumsphere is empty (the simplex| -| | is then said to be Gabriel), and as the minimum of the filtration | -| | values of the codimension 1 cofaces that make it not Gabriel | -| | otherwise. All simplices that have a filtration value strictly | -| | greater than a given alpha squared value are not inserted into the | -| | complex. | +| | * :math:`W` set of **witnesses** and | +| | * :math:`L \subseteq W` set of **landmarks**. | | | | -| | This package requires having CGAL version 4.7 or higher (4.8.1 is | -| | advised for better perfomances). | +| | The simplices are based on landmarks and a simplex belongs to the | +| | witness complex if and only if it is witnessed, that is: | +| | | +| | :math:`\sigma \subset L` is witnessed if there exists a point | +| | :math:`w \in W` such that w is closer to the vertices of | +| | :math:`\sigma` than other points in :math:`L` and all of its faces | +| | are witnessed as well. | +| | | +| | The data structure is described in | +| | :cite:`boissonnatmariasimplextreealgorithmica`. | +---------------------------------------------+----------------------------------------------------------------------+ | :doc:`witness_complex_user` | :doc:`witness_complex_ref` | +---------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/source/witness_complex_user.rst b/src/cython/doc/source/witness_complex_user.rst index 698e5441..604c7357 100644 --- a/src/cython/doc/source/witness_complex_user.rst +++ b/src/cython/doc/source/witness_complex_user.rst @@ -6,3 +6,26 @@ Definition .. include:: witness_complex_sum.rst +Implementation +-------------- + +The principal class of this module is Gudhi::Witness_complex. + +In both cases, the constructor for this class takes a {witness}x{closest_landmarks} table, where each row represents a +witness and consists of landmarks sorted by distance to this witness. + +.. todo:: + This table can be constructed by two additional classes Landmark_choice_by_furthest_point and + Landmark_choice_by_random_point also included in the module. + +.. figure:: + img/bench_Cy8.png + :align: center + + Running time as function on number of landmarks. + +.. figure:: + img/bench_sphere.png + :align: center + + Running time as function on number of witnesses for |L|=300. diff --git a/src/cython/gudhi.pyx.in b/src/cython/gudhi.pyx.in index a67c8a21..5f7809d6 100644 --- a/src/cython/gudhi.pyx.in +++ b/src/cython/gudhi.pyx.in @@ -28,6 +28,7 @@ include "src/cython/simplex_tree.pyx" include "src/cython/mini_simplex_tree.pyx" include "src/cython/rips_complex.pyx" include "src/cython/cubical_complex.pyx" +include "src/cython/periodic_cubical_complex.pyx" include "src/cython/persistence_graphical_tools.py" include "src/cython/witness_complex.pyx" @GUDHI_CYTHON_ALPHA_COMPLEX@ diff --git a/src/cython/src/cpp/Alpha_complex_interface.h b/src/cython/src/cpp/Alpha_complex_interface.h index ee5ab823..e2e6d100 100644 --- a/src/cython/src/cpp/Alpha_complex_interface.h +++ b/src/cython/src/cpp/Alpha_complex_interface.h @@ -49,6 +49,11 @@ class Alpha_complex_interface : public Alpha_complex< CGAL::Epick_d< CGAL::Dynam : Alpha_complex(points, max_alpha_square) { } + // bool from_file is a workaround fro cython to find the correct signature + Alpha_complex_interface(const std::string& off_file, double max_alpha_square, bool from_file) + : Alpha_complex(off_file, max_alpha_square) { + } + bool find_simplex(const Simplex& vh) { return (Alpha_complex::find(vh) != Alpha_complex::null_simplex()); } diff --git a/src/cython/src/cython/alpha_complex.pyx b/src/cython/src/cython/alpha_complex.pyx index 33fc06ef..44da8c9d 100644 --- a/src/cython/src/cython/alpha_complex.pyx +++ b/src/cython/src/cython/alpha_complex.pyx @@ -1,6 +1,9 @@ from cython cimport numeric from libcpp.vector cimport vector from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +import os """This file is part of the Gudhi Library. The Gudhi library (Geometric Understanding in Higher Dimensions) is a generic C++ @@ -31,6 +34,8 @@ __license__ = "GPL v3" cdef extern from "Alpha_complex_interface.h" namespace "Gudhi": cdef cppclass Alpha_complex_interface "Gudhi::alphacomplex::Alpha_complex_interface": Alpha_complex_interface(vector[vector[double]] points, double max_alpha_square) + # bool from_file is a workaround fro cython to find the correct signature + Alpha_complex_interface(string off_file, double max_alpha_square, bool from_file) double filtration() double simplex_filtration(vector[int] simplex) void set_filtration(double filtration) @@ -82,19 +87,33 @@ cdef class AlphaComplex: cdef Alpha_complex_persistence_interface * pcohptr # Fake constructor that does nothing but documenting the constructor - def __init__(self, points=[], max_alpha_square=float('inf')): + def __init__(self, points=None, off_file='', max_alpha_square=float('inf')): """AlphaComplex constructor. :param points: A list of points in d-Dimension. :type points: list of list of double - :param max_alpha_square: Maximum Alpha square value. + + Or + + :param off_file: An OFF file style name. + :type off_file: string + + :param max_alpha_square: Maximum Alpha square value. Default is :math:`\infty` :type max_alpha_square: double """ # The real cython constructor - def __cinit__(self, points=[], max_alpha_square=float('inf')): - self.thisptr = new Alpha_complex_interface(points, - max_alpha_square) + def __cinit__(self, points=[], off_file='', max_alpha_square=float('inf')): + if off_file is not '': + if os.path.isfile(off_file): + self.thisptr = new Alpha_complex_interface(off_file, + max_alpha_square, True) + else: + print("file " + off_file + " not found.") + else: + self.thisptr = new Alpha_complex_interface(points, + max_alpha_square) + def __dealloc__(self): if self.thisptr != NULL: diff --git a/src/cython/src/cython/cubical_complex.pyx b/src/cython/src/cython/cubical_complex.pyx index fe286dc6..3441b2e9 100644 --- a/src/cython/src/cython/cubical_complex.pyx +++ b/src/cython/src/cython/cubical_complex.pyx @@ -32,8 +32,10 @@ __license__ = "GPL v3" cdef extern from "Cubical_complex_interface.h" namespace "Gudhi": cdef cppclass Bitmap_cubical_complex_base_interface "Gudhi::Cubical_complex::Cubical_complex_interface<>": - Bitmap_cubical_complex_base_interface(vector[unsigned] dimensions, vector[double] top_dimensional_cells) - Bitmap_cubical_complex_base_interface(string perseus_file) + Bitmap_cubical_complex_base_interface(vector[unsigned] dimensions, vector[double] top_dimensional_cells) + Bitmap_cubical_complex_base_interface(string perseus_file) + int num_simplices() + int dimension() cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Cubical_complex_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Cubical_complex::Cubical_complex_interface<>>": @@ -104,6 +106,21 @@ cdef class CubicalComplex: """ return self.pcohptr != NULL + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: int -- the simplicial complex number of simplices. + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: int -- the simplicial complex dimension. + """ + return self.thisptr.dimension() + def persistence(self, homology_coeff_field=11, min_persistence=0): """This function returns the persistence of the simplicial complex. diff --git a/src/cython/src/cython/periodic_cubical_complex.pyx b/src/cython/src/cython/periodic_cubical_complex.pyx new file mode 100644 index 00000000..d56eb5b1 --- /dev/null +++ b/src/cython/src/cython/periodic_cubical_complex.pyx @@ -0,0 +1,181 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +import os + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): Vincent Rouvreau + + Copyright (C) 2016 INRIA + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Cubical_complex_interface.h" namespace "Gudhi": + cdef cppclass Periodic_cubical_complex_base_interface "Gudhi::Cubical_complex::Cubical_complex_interface<Gudhi::cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base<double>>": + Periodic_cubical_complex_base_interface(vector[unsigned] dimensions, vector[double] top_dimensional_cells) + Periodic_cubical_complex_base_interface(string perseus_file) + int num_simplices() + int dimension() + +cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": + cdef cppclass Periodic_cubical_complex_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Cubical_complex::Cubical_complex_interface<Gudhi::cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base<double>>>": + Periodic_cubical_complex_persistence_interface(Periodic_cubical_complex_base_interface * st) + vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[int] betti_numbers() + vector[int] persistent_betti_numbers(double from_value, double to_value) + + +# PeriodicCubicalComplex python interface +cdef class PeriodicCubicalComplex: + """The PeriodicCubicalComplex is an example of a structured complex useful + in computational mathematics (specially rigorous numerics) and image + analysis. + """ + cdef Periodic_cubical_complex_base_interface * thisptr + + cdef Periodic_cubical_complex_persistence_interface * pcohptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, dimensions=None, top_dimensional_cells=None, + perseus_file=''): + """PeriodicCubicalComplex constructor from dimensions and + top_dimensional_cells or from a perseus file style name. + + :param dimensions: A list of number of top dimensional cells. + :type dimensions: list of int + :param top_dimensional_cells: A list of top dimensional cells. + :type top_dimensional_cells: list of double + + Or + + :param perseus_file: A perseus file style name. + :type perseus_file: string + """ + + # The real cython constructor + def __cinit__(self, dimensions=None, top_dimensional_cells=None, + perseus_file=''): + if ((dimensions is not None) or (top_dimensional_cells is not None) and + (perseus_file is not '')): + print("PeriodicCubicalComplex can be constructed from dimensions" + " and top_dimensional_cells or from a perseus file style " + "name.") + else: + if dimensions is not None: + if top_dimensional_cells is not None: + self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, top_dimensional_cells) + else: + if perseus_file is not '': + if os.path.isfile(perseus_file): + self.thisptr = new Periodic_cubical_complex_base_interface(perseus_file) + else: + print("file " + perseus_file + " not found.") + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + if self.pcohptr != NULL: + del self.pcohptr + + def __is_defined(self): + """Returns true if PeriodicCubicalComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def __is_persistence_defined(self): + """Returns true if Persistence pointer is not NULL. + """ + return self.pcohptr != NULL + + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: int -- the simplicial complex number of simplices. + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: int -- the simplicial complex dimension. + """ + return self.thisptr.dimension() + + def persistence(self, homology_coeff_field=11, min_persistence=0): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :returns: list of pairs(dimension, pair(birth, death)) -- the + persistence of the simplicial complex. + """ + if self.pcohptr != NULL: + del self.pcohptr + if self.thisptr != NULL: + self.pcohptr = new Periodic_cubical_complex_persistence_interface(self.thisptr) + cdef vector[pair[int, pair[double, double]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence) + return persistence_result + + def betti_numbers(self): + """This function returns the Betti numbers of the simplicial complex. + + :returns: list of int -- The Betti numbers ([B0, B1, ..., Bn]). + + :note: betti_numbers function requires persistence function to be + launched first. + """ + cdef vector[int] bn_result + if self.pcohptr != NULL: + bn_result = self.pcohptr.betti_numbers() + return bn_result + + def persistent_betti_numbers(self, from_value, to_value): + """This function returns the persistent Betti numbers of the + simplicial complex. + + :param from_value: The persistence birth limit to be added in the + numbers (persistent birth <= from_value). + :type from_value: float. + :param to_value: The persistence death limit to be added in the + numbers (persistent death > to_value). + :type to_value: float. + + :returns: list of int -- The persistent Betti numbers ([B0, B1, ..., + Bn]). + + :note: persistent_betti_numbers function requires persistence + function to be launched first. + """ + cdef vector[int] pbn_result + if self.pcohptr != NULL: + pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value) + return pbn_result diff --git a/src/cython/src/cython/rips_complex.pyx b/src/cython/src/cython/rips_complex.pyx index bed1aa4a..ee4c34b0 100644 --- a/src/cython/src/cython/rips_complex.pyx +++ b/src/cython/src/cython/rips_complex.pyx @@ -79,7 +79,8 @@ cdef class RipsComplex: cdef Rips_complex_persistence_interface * pcohptr # Fake constructor that does nothing but documenting the constructor - def __init__(self, points=[], max_alpha_square=float('inf')): + def __init__(self, points=[], max_dimension=3, + max_edge_length=float('inf')): """RipsComplex constructor. :param points: A list of points in d-Dimension. |