Skip to content

On keeping track on merges? #167

@RaimelMedina

Description

@RaimelMedina

Hi Matija,

I've been trying to see how to add the feature of keeping track which component merged with whom. I have some preliminary (messy code) that does this. I guess this would only work for dim=0 homology since only there these merges make sense.

1.) Do you perhaps have any suggestion on how/what to improve on this?
2.) Would it be worth to add support in Ripserer for this, as well as constructing/plotting the corresponding merge tree?

I haven't found anything that supports this out there so perhaps could be useful

The code below is a simple modification of the zeroth_intervals function

function zeroth_intervals_with_merges(filtration, cutoff::T = T(0); verbose=true) where T <: AbstractFloat
    F = Mod
    reps = false
    V = simplex_type(filtration, 0)
    CE = chain_element_type(V, F)
    dset = DisjointSetsWithBirth(vertices(filtration), births(filtration))
    intervals = PersistenceInterval[]
    
    to_skip      = simplex_type(filtration, 1)[]
    to_reduce = simplex_type(filtration, 1)[]
    simplices  = sort!(edges(filtration))
    

    merged_vertices = Dict()
    persistence_merged_vertices = Dict()

    if verbose
        progbar = Progress(
            length(simplices) + nv(filtration); desc="Computing 0d intervals... "
        )
    end
    for edge in simplices
        u, v = vertices(edge)
        
        i = find_root!(dset, u)
        j = find_root!(dset, v)
        if i ≠ j
            # According to the elder rule, the vertex with the higher birth will die first.
            last_vertex = birth(dset, i) > birth(dset, j) ? i : j
            int = interval(dset, filtration, last_vertex, edge, cutoff, reps)
            btime_last, bvertex_last = birth(dset, last_vertex)
        
            if !isnothing(int)
                push!(intervals, int)
                if last_vertex == i
                    btime_first, bvertex_first = birth(dset, j)
                else
                    btime_first, bvertex_first = birth(dset, i)
                end
                
                merged_vertices[simplex(filtration, Val(0), (bvertex_last,))] = simplex(filtration, Val(0), (bvertex_first,))
                persistence_merged_vertices[simplex(filtration, Val(0), (bvertex_last,))] = persistence(int)
            end
            union!(dset, i, j)
            push!(to_skip, edge)
        else
            push!(to_reduce, edge)
        end
        verbose && next!(progbar; showvalues=((:n_intervals, length(intervals)),))
    end
    for v in vertices(filtration)
        if find_root!(dset, v) == v && !isnothing(simplex(filtration, Val(0), (v,)))
            int = interval(dset, filtration, v, nothing, cutoff, reps)
            push!(intervals, int)
        end
        verbose && next!(progbar; showvalues=((:n_intervals, length(intervals)),))
    end
    reverse!(to_reduce)

    thresh = T(threshold(filtration))
    diagram = PersistenceDiagram(
        sort!(intervals; by=persistence);
        threshold=thresh,
        dim=0,
        field=F,
        filtration=filtration,
    )
    return merged_vertices, Ripserer.postprocess_diagram(filtration, diagram), persistence_merged_vertices
end

I can also share the code to construct and plot the corresponding merge tree if you think it's worthwhile or necessary

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions