Interfaces
Filtration Interface
Ripserer.AbstractFiltration
— TypeAbstractFiltration{I, T}
A filtration is used to find the edges in filtration and to create simplices. An AbstractFiltration{I, T}
's simplex type is expected to return simplices of type <:AbstractSimplex{_, T, I}
.
Interface
nv(::AbstractFiltration)
edges(::AbstractFiltration)
simplex_type(::Type{AbstractFiltration}, dim)
simplex(::AbstractFiltration, ::Val{dim}, vertices, sign)
unsafe_simplex(::AbstractFiltration, ::Val{dim}, vertices, sign)
unsafe_cofacet
(::AbstractFiltration, simplex, vertices, vertex, sign[, edges])
birth(::AbstractFiltration, v)
birth(::AbstractFiltration)
threshold(::AbstractFiltration)
columns_to_reduce(::AbstractFiltration, ::Any)
emergent_pairs(::AbstractFiltration)
postprocess_diagram(::AbstractFiltration, ::Any)
LightGraphs.nv
— Methodnv(::AbstractFiltration)
Return the number of vertices in filtration
.
Example
julia> Ripserer.nv(Rips([1 1; 1 1]))
2
LightGraphs.edges
— Methodedges(::AbstractFiltration)
Get edges (1-simplices) in filtration
. Edges should be of type simplex_type
(filtration, 1)
.
Example
julia> Ripserer.edges(Rips([0 2 1; 2 0 1; 1 1 0], threshold=2))
3-element Array{Simplex{1,Int64,Int64},1}:
+Simplex{1}([2, 1], 2)
+Simplex{1}([3, 1], 1)
+Simplex{1}([3, 2], 1)
PersistenceDiagrams.birth
— Methodbirth(::AbstractFiltration, v)
birth(::AbstractFiltration)
Get the birth time of vertex v
in filtration. Defaults to 0. When v
is not given, return births in an array of same size as vertices(::AbstractFiltration)
.
Examples
julia> flt = Rips([1 1 2; 1 0 1; 2 1 0]);
julia> birth(flt, 1)
1
julia> birth(flt)
3-element Array{Int64,1}:
1
0
0
PersistenceDiagrams.threshold
— Methodthreshold(::AbstractFiltration)
Get the threshold of filtration. This is the maximum diameter a simplex in the filtration can have. Defaults to Inf
.
Examples
julia> threshold(Rips([0 2 1; 2 0 1; 1 1 0]))
1
julia> threshold(Cubical([1 1 2; 3 2 1; 0 0 0]))
3
Ripserer.simplex_type
— Functionsimplex_type(::Type{<:AbstractFiltration}, D)
simplex_type(::AbstractFiltration, D)
Return the D
-dimensional simplex type in the filtration. Only the method for the type needs to be overloaded.
Examples
julia> Ripserer.simplex_type(Rips{Int, Float64}, 1)
Simplex{1,Float64,Int64}
julia> Ripserer.simplex_type(Cubical{2, Float16}, 2)
Cube{2,Float16,2}
Ripserer.simplex
— Function simplex(::AbstractFiltration, ::Val{D}, vertices, sign=1)
Return D
-simplex constructed from vertices
with sign equal to sign
. Return nothing
if simplex is not in filtration. This function is safe to call with vertices that are out of order. Default implementation sorts vertices
and calls unsafe_simplex
.
Example
julia> simplex(Rips([0 2 1; 2 0 1; 1 1 0], threshold=2), Val(1), (1, 2), -1)
1-dimensional Simplex(index=1, birth=2):
-[2, 1]
Ripserer.unsafe_simplex
— Functionunsafe_simplex(::AbstractFiltration, ::Val{D}, vertices, sign=1)
Return D
-simplex constructed from vertices
with sign equal to sign
. Return nothing
if simplex is not in filtration. The unsafe in the name implies that it's up to the caller to ensure vertices are sorted and unique.
Ripserer.unsafe_cofacet
— Functionunsafe_cofacet(filtration, simplex, cofacet_vertices, v, sign[, edges])
unsafe_cofacet(::Type{S}, filtration, simplex, cofacet_vertices, v, sign[, edges])
Return cofacet of simplex
with vertices equal to cofacet_vertices
. v
is the vertex that was added to construct the cofacet. In the case of sparse rips filtrations, an additional argument edges
is used. edges
is a vector that contains the weights on edges connecting the new vertex to old vertices. S
is the simplex type which can be used for dispatch.
The unsafe in the name implies that it's up to the caller to ensure vertices are sorted and unique.
Default implementation uses unsafe_simplex
.
Ripserer.columns_to_reduce
— Functioncolumns_to_reduce(::AbstractFilration, prev_column_itr)
List all columns to reduce in next dimension, possibly computing it from previous columns. Default implementation uses coboundary
with the all cofacets parameter set to Val(false)
.
Example
julia> flt = Rips([0 1 1; 1 0 1; 1 1 0]);
julia> Ripserer.columns_to_reduce(flt, Ripserer.edges(flt)) |> collect
1-element Array{Simplex{2,Int64,Int64},1}:
+Simplex{2}([3, 2, 1], 1)
Ripserer.emergent_pairs
— Functionemergent_pairs(::AbstractFiltration)
Return true
if the emergent pairs optimization is to be performed. Default to returning true
. Should be set to false
for a filtration type that is unable to produce (co)boundary simplices in the correct order.
Ripserer.postprocess_diagram
— Functionpostprocess_diagram(::AbstractFiltration, diagram)
This function is called on each resulting persistence diagram after all intervals have been computed. Defaults to sort!
ing the diagram.
Ripserer.AbstractRipsFiltration
— TypeAbstractRipsFiltration{I<:Signed, T} <: AbstractFiltration{I, T}
An abstract Vietoris-Rips filtration. Its subtypes can only overload dist
and get default implementations for the rest of the filtration interface.
Example
julia> struct MyRips <: Ripserer.AbstractRipsFiltration{Int, Float16} end
julia> Ripserer.dist(::MyRips) = [0 1 1; 1 0 1; 1 1 0]
julia> ripserer(MyRips())
2-element Array{PersistenceDiagrams.PersistenceDiagram,1}:
3-element 0-dimensional PersistenceDiagram
0-element 1-dimensional PersistenceDiagram
Ripserer.dist
— Functiondist(::AbstractRipsFiltration, u, v)
dist(::AbstractRipsFiltration)
Return the distance between vertices u
and v
. If the distance is somehow invalid, it may return missing
instead. If u
and v
are not given, return the distance matrix.
Examples
julia> flt = Rips([1 1 2; 1 0 1; 2 1 0]);
julia> Ripserer.dist(flt, 1, 3)
2
julia> Ripserer.dist(flt)
3×3 Array{Int64,2}:
1 1 2
1 0 1
2 1 0
Ripserer.AbstractCustomFiltration
— Typeabstract type AbstractCustomFiltration{I, T} <: AbstractFiltration{I, T}
This abstract type is for filtrations that have all simplices stored in Dict
s. The dicts should be accessible by the function simplex_dicts
and should be a vector of Dict{I, T}
. A custom filtration should also have adjacency_matrix
defined. This matrix is only used as an adjacency matrix. Its values are ignored.
Ripserer.simplex_dicts
— Functionsimplex_dicts(::AbstractCustomFiltration)
Get the dictionaries used to get simplex birth times. Should return a Vector
of Dict{I, T}
that maps a simplex index to its birth time. The first element of this Vector
corresponds to vertices, second to 1-simplices etc.
LightGraphs.LinAlg.adjacency_matrix
— Methodadjacency_matrix(::AbstractFiltration)
Return the adjacency matrix. For sparse filtrations, this should return a SparseMatrixCSC
.
Examples
julia> Ripserer.adjacency_matrix(Rips([0 2 1; 2 0 1; 1 1 0]))
3×3 Array{Int64,2}:
0 2 1
2 0 1
1 1 0
julia> Ripserer.adjacency_matrix(SparseRips([0 0 1; 0 0 1; 1 1 0]))
3×3 SparseArrays.SparseMatrixCSC{Int64,Int64} with 4 stored entries:
[3, 1] = 1
[3, 2] = 1
[1, 3] = 1
[2, 3] = 1
julia> Ripserer.adjacency_matrix(Custom([(2, 1) => 1, (5, 1) => 2, (3, 4) => 3]))
5×5 SparseArrays.SparseMatrixCSC{Bool,Int64} with 6 stored entries:
[2, 1] = 1
[5, 1] = 1
[1, 2] = 1
[4, 3] = 1
[3, 4] = 1
[1, 5] = 1
Simplex Interface
Ripserer.AbstractSimplex
— TypeAbstractSimplex{D, T, I} <: AbstractVector{I}
An abstract type for representing simplices. A simplex must have a diameter of type T
, which is its birth time. The dimension must be encoded in the type as D
and can be accessed by dim
.
The simplex is expected to act like an array of indices of type I
, but this is not actually needed for the main algorithm.
Interface
AbstractSimplex{D}(::SVector{<:Any, <:Integer}, ::T)
birth(::AbstractSimplex)
index(::AbstractSimplex)
sign(::AbstractSimplex)
coboundary(::Any, ::AbstractSimplex)
boundary(::Any, ::AbstractSimplex)
vertices(::AbstractSimplex)
Base.:-(::AbstractSimplex)
Ripserer.index
— Methodindex(simplex::AbstractSimplex)
Get the combinatorial index of the simplex
. The index can be any type, but should uniquely identify a simplex. It is also used to break ties when comparing simplices with the same birth time.
julia> index(Simplex{2}((3, 2, 1), 3.2))
1
Base.sign
— Methodsign(simplex::AbstractSimplex)
Get the orientation of simplex
. Should return -1 or 1.
Examples
julia> sign(Simplex{2}((3, 2, 1), 3.2))
1
julia> sign(-Simplex{2}((3, 2, 1), 3.2))
-1
Base.:-
— Method-(simplex::AbstractSimplex)
Reverse the simplex orientation.
Example
julia> -Simplex{2}((3, 2, 1), 3.2)
2-dimensional Simplex(index=1, birth=3.2):
-[3, 2, 1]
Ripserer.coboundary
— Methodcoboundary(filtration, simplex[, Val{all_cofacets}])
Iterate over the coboundary of simplex
by decreasing index
. Use the filtration
to determine the diameters and validity of cofacets.
If all_cofacets
is false
, only return cofaces with vertices added to the beginning of vertex list. The method with all_cofacets
only has to be implemented if the filtration does not overload columns_to_reduce
.
Comes with a default implementation.
If cofacets are not returned in decreasing index
order, the algorithm will not work correctly. If there is no avoiding it, define emergent_pairs(...) = false
for your filtration.
Examples
filtration = Rips([0 1 1 1; 1 0 1 1; 1 1 0 1; 1 1 1 0])
for c in Ripserer.coboundary(filtration, Simplex{1}(2, 1))
println(c)
end
# output
+Simplex{2}([4, 3, 1], 1)
-Simplex{2}([3, 2, 1], 1)
for c in Ripserer.coboundary(filtration, Simplex{1}(2, 1), Val(false))
println(c)
end
# output
+Simplex{2}([4, 3, 1], 1)
Ripserer.boundary
— Methodboundary(filtration, simplex[, Val{all_cofacets}])
Iterate over the boundary of simplex
by increasing index
. Use the filtration
to determine the diameters and validity of cofacets.
Comes with a default implementation.
If facets are not returned in increasing index
order, the (homology) algorithm will not work correctly. If there is no avoiding it, define emergent_pairs(...) = false
for your filtration.
Example
filtration = Rips([0 1 1 1; 1 0 1 1; 1 1 0 1; 1 1 1 0])
for f in Ripserer.boundary(filtration, Simplex{2}(2, 1))
println(f)
end
# output
+Simplex{1}([2, 1], 1)
-Simplex{1}([4, 1], 1)
+Simplex{1}([4, 2], 1)