Skip to content

Commit

Permalink
Some cleanup in matroid code to avoid code duplication and improve ty…
Browse files Browse the repository at this point in the history
…pe stability (#3031)
  • Loading branch information
benlorenz authored Nov 23, 2023
1 parent 8484e83 commit 43ef558
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 65 deletions.
31 changes: 21 additions & 10 deletions src/Combinatorics/Matroids/matroids.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,23 @@ end
# function that generates the dictionary which maps the groundset to integers
create_gs2num(E::GroundsetType) = Dict(zip(E, 1:length(E)))

_pmset_to_indices(A::Polymake.Array{<:Polymake.Set{<:Integer}}) = collect.(Int, Polymake.to_one_based_indexing(A))
_pmset_to_indices(A::Polymake.Set{<:Integer}) = collect(Int, Polymake.to_one_based_indexing(A))

_indices_to_gs(A::AbstractVector{<:AbstractVector{<:Integer}}, gs::AbstractVector) = [gs[S] for S in A]
_indices_to_gs(A::AbstractVector{<:Integer}, gs::AbstractVector) = gs[A]

_gs_to_indices(s::GroundsetType, gs2num::Dict; type::Type=Vector{Int}) = type(collect(Int, gs2num[i] for i in collect(s)))
_gs_to_pmindices(s::GroundsetType, gs2num::Dict; type::Type=Vector{Int}) = Polymake.to_zero_based_indexing(_gs_to_indices(s, gs2num; type=type))

_property_to_gs(M::Matroid, p::Symbol) = _indices_to_gs(_pmset_to_indices(getproperty(pm_object(M), p)), M.groundset)

@doc raw"""
Matroid(pm_matroid::Polymake.BigObjectAllocated, [E::GroundsetType])
Construct a `matroid` from a `polymake` matroid `M` on the default ground set `{1,...,n}`.
"""
function Matroid(pm_matroid::Polymake.BigObjectAllocated, E::GroundsetType=Vector{Integer}(1:pm_matroid.N_ELEMENTS))
function Matroid(pm_matroid::Polymake.BigObjectAllocated, E::GroundsetType=collect(1:pm_matroid.N_ELEMENTS))
return Matroid(pm_matroid, E, create_gs2num(E))
end

Expand Down Expand Up @@ -99,7 +110,7 @@ function matroid_from_bases(bases::Union{AbstractVector{T},AbstractSet{T}}, grou
end

gs2num = create_gs2num(groundset)
pm_bases = Vector{Int}[[gs2num[i]-1 for i in B] for B in bases]
pm_bases = _gs_to_pmindices.(bases, Ref(gs2num))
M = Polymake.matroid.Matroid(BASES=pm_bases,N_ELEMENTS=length(groundset))
if check && !Polymake.matroid.check_basis_exchange_axiom(M.BASES)
error("Input is not a collection of bases")
Expand Down Expand Up @@ -155,7 +166,7 @@ function matroid_from_nonbases(nonbases::Union{AbstractVector{T},AbstractSet{T}}

gs2num = create_gs2num(groundset)

pm_nonbases = [[gs2num[i]-1 for i in B] for B in nonbases]
pm_nonbases = _gs_to_pmindices.(nonbases, Ref(gs2num))
M = Polymake.matroid.Matroid(NON_BASES=pm_nonbases,N_ELEMENTS=length(groundset))
if check && !Polymake.matroid.check_basis_exchange_axiom(M.BASES)
error("Input is not a collection of nonbases")
Expand Down Expand Up @@ -208,7 +219,7 @@ function matroid_from_circuits(circuits::Union{AbstractVector{T},AbstractSet{T}}
end

gs2num = create_gs2num(groundset)
pm_circuits = [[gs2num[i]-1 for i in C] for C in circuits]
pm_circuits = _gs_to_pmindices.(circuits, Ref(gs2num))
M = Polymake.matroid.Matroid(CIRCUITS=pm_circuits,N_ELEMENTS=length(groundset))
#TODO check_circuit_exchange_axiom (requires an update of polymake)
#if check && !Polymake.matroid.check_circuit_exchange_axiom(M.CIRCUITS)
Expand Down Expand Up @@ -260,7 +271,7 @@ function matroid_from_hyperplanes(hyperplanes::Union{AbstractVector{T},AbstractS

groundset = collect(groundset)
gs2num = create_gs2num(groundset)
pm_hyperplanes = [[gs2num[i]-1 for i in H] for H in hyperplanes]
pm_hyperplanes = _gs_to_pmindices.(hyperplanes, Ref(gs2num))
M = Polymake.matroid.Matroid(MATROID_HYPERPLANES=pm_hyperplanes,N_ELEMENTS=length(groundset))
#TODO implement a check if these are actually the hyperplanes of a matroid
return Matroid(M,groundset,gs2num)
Expand Down Expand Up @@ -453,7 +464,7 @@ function direct_sum(M::Matroid, N::Matroid)
gsN[i] = string(gsN[i],'\'')
end
end
return Matroid(Polymake.matroid.direct_sum(M.pm_matroid,N.pm_matroid),[M.groundset;gsN],create_gs2num([M.groundset;gsN]))
return Matroid(Polymake.matroid.direct_sum(pm_object(M), N.pm_matroid), [M.groundset; gsN], create_gs2num([M.groundset; gsN]))
end

direct_sum(comp::Vector{Matroid}) = foldl(direct_sum, comp)
Expand Down Expand Up @@ -499,7 +510,7 @@ function deletion(M::Matroid,set::GroundsetType)
if !all([e in M.groundset for e in set])
error("The set of deleted element must be a subset of the groundset.")
end
sort_set = Vector(undef,length(M.groundset)-length(set))
sort_set = similar(M.groundset, length(M.groundset)-length(set))
gs2num = typeof(M.gs2num)()
i = 1
for elem in M.groundset
Expand All @@ -509,7 +520,7 @@ function deletion(M::Matroid,set::GroundsetType)
i+=1
end
end
pm_del = Polymake.matroid.deletion(M.pm_matroid, Set([M.gs2num[i]-1 for i in set]))
pm_del = Polymake.matroid.deletion(pm_object(M), _gs_to_pmindices(set, M.gs2num; type=Set))
return Matroid(pm_del, sort_set, gs2num)
end

Expand Down Expand Up @@ -633,8 +644,8 @@ function principal_extension(M::Matroid, set::GroundsetType, elem::ElementType)
ktype = keytype(M.gs2num)
gs2num = Dict{Union{ktype, ElementType}, Int}(M.gs2num)
gs2num[elem] = length(M.groundset)+1
pm_set = Set{Int}([gs2num[i]-1 for i in set])
return Matroid(Polymake.matroid.principal_extension(M.pm_matroid, pm_set),[M.groundset;elem],gs2num)
pm_set = _gs_to_pmindices(set, gs2num; type=Set)
return Matroid(Polymake.matroid.principal_extension(pm_object(M), pm_set),[M.groundset;elem],gs2num)
end

@doc raw"""
Expand Down
Loading

0 comments on commit 43ef558

Please sign in to comment.