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

Matroid serialisation and matroid encodings #3886

Merged
merged 19 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
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
2 changes: 2 additions & 0 deletions docs/src/Combinatorics/matroids.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ bond_matroid(g::Graph)
cocycle_matroid(g::Graph)
Matroid(pm_matroid::Polymake.BigObjectAllocated, E::GroundsetType=Vector{Integer}(1:pm_matroid.N_ELEMENTS))
matroid_from_revlex_basis_encoding(rvlx::String, r::IntegerUnion, n::IntegerUnion)
matroid_from_matroid_hex(str::AbstractString)
```

## Examples
Expand Down Expand Up @@ -112,6 +113,7 @@ reduced_characteristic_polynomial(M::Matroid)
revlex_basis_encoding(M::Matroid)
is_isomorphic(M1::Matroid, M2::Matroid)
is_minor(M::Matroid, N::Matroid)
matroid_hex(M::Matroid)
automorphism_group(M::Matroid)
matroid_base_polytope(M::Matroid)
```
Expand Down
52 changes: 52 additions & 0 deletions src/Combinatorics/Matroids/properties.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,58 @@ function min_revlex_basis_encoding(M::Matroid)
return _revlex_basis_from_vector(min_rvlx)
end

@doc raw"""
matroid_hex(M::Matroid)

Stores a matroid as a string of hex characters. The first part of the string is "r" followed by the rank of the matroid. This is followed by "n" and the number of elements. The rest of the string is the revlex basis encoding. The encoding is done by converting the basis encoding to a vector of bits and then to a string of characters. The bits are padded to a multiple of 4 and then converted to hex characters.

# Examples
To get the hex encoding of the fano matroid write:
```jldoctest
julia> matroid_hex(fano_matroid())
"r3n7_3f7eefd6f"

```
"""
function matroid_hex(M::Matroid)::String
rvlx = min_revlex_basis_encoding(M)
r,n = rank(M), length(M)

v = _revlex_basis_to_vector(rvlx)
for _ in 1:(4-length(v)%4)
pushfirst!(v,0)
end
v = reshape(v,4,:)
v = [string(parse(Int, join(v[:, j]), base=2), base=16) for j in 1:size(v)[2]]

return "r$(r)n$(n)_" * join(v)
end

@doc raw"""
matroid_from_matroid_hex(str::AbstractString)

Returns a matroid from a string of hex characters.

# Examples
To retrieve the fano matroid from its hex encoding write:

```jldoctest
julia> matroid_from_matroid_hex("r3n7_3f7eefd6f")
Matroid of rank 3 on 7 elements

```
"""
function matroid_from_matroid_hex(str::AbstractString)::Matroid
sep = split(str,"_")
(r,n) = parse.(Int,split(sep[1][2:end],"n"))
antonydellavecchia marked this conversation as resolved.
Show resolved Hide resolved

v = [digits(parse(Int,x,base=16),base=2,pad=4) |> reverse for x in sep[2]]
v = foldl(append!,v)
v = v[(length(v)-binomial(n,r)+1):end]

return matroid_from_revlex_basis_encoding(_revlex_basis_from_vector(v),r,n)
end

@doc raw"""
is_isomorphic(M1::Matroid, M2::Matroid)

Expand Down
24 changes: 24 additions & 0 deletions src/Serialization/Combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,30 @@ function load_object(s::DeserializerState, g::Type{Graph{T}}) where T <: Union{D
return g(smallobj)
end

###############################################################################
## Matroid
###############################################################################
@register_serialization_type Matroid "Matroid"

function save_object(s::SerializerState, m::Matroid)
@req m.groundset isa Vector{Int} "Groundset must be a Vector{Int}"
Sequenzer marked this conversation as resolved.
Show resolved Hide resolved

save_data_dict(s) do
save_object(s, pm_object(m), :matroid)
save_object(s, matroid_groundset(m), :groundset)
save_object(s, create_gs2num(m), :gs2num)
end
end


function load_object(s::DeserializerState, m::Type{Matroid})
mt = load_object(s, Polymake.BigObject, :matroid)
grds = load_object(s, Vector{Int}, :groundset)
gs2num = load_object(s, Dict{Int,Int}, :gs2num)
return m(mt, grds, gs2num)
end


###############################################################################
## IncidenceMatrix
###############################################################################
Expand Down
4 changes: 4 additions & 0 deletions src/Serialization/containers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,10 @@ function load_object(s::DeserializerState, ::Type{Dict{String, Int}})
return Dict{String, Int}(string(k) => parse(Int, v) for (k,v) in s.obj)
end

function load_object(s::DeserializerState, ::Type{Dict{Int, Int}})
return Dict{Int, Int}(parse(Int,string(k)) => parse(Int, v) for (k,v) in s.obj)
end

function load_object(s::DeserializerState, ::Type{<:Dict}, params::Dict{Symbol, Any})
key_type = params[:key_type]
value_type = haskey(params, :value_type) ? params[:value_type] : Any
Expand Down
2 changes: 2 additions & 0 deletions src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -977,12 +977,14 @@ export mathieu_group
export matrix_group
export matrix_kernel
export matrix_ordering
export matroid_hex
export matroid_base_polytope
export matroid_from_bases
export matroid_from_circuits
export matroid_from_hyperplanes
export matroid_from_matrix_columns
export matroid_from_matrix_rows
export matroid_from_matroid_hex
export matroid_from_nonbases
export matroid_from_prime_ideal
export matroid_from_revlex_basis_encoding
Expand Down
10 changes: 10 additions & 0 deletions test/Combinatorics/Matroids/Matroids.jl
Original file line number Diff line number Diff line change
Expand Up @@ -368,4 +368,14 @@
@test_throws ArgumentError is_quotient(M2, M1)
@test_throws ArgumentError is_quotient(Q2, M2)
end

@testset "matroid_hex" begin
M = fano_matroid()
N = uniform_matroid(2, 4)

M1 = matroid_from_matroid_hex(matroid_hex(M))
N1 = matroid_from_matroid_hex(matroid_hex(N))
@test is_isomorphic(M, M1)
@test is_isomorphic(N, N1)
end
lgoettgens marked this conversation as resolved.
Show resolved Hide resolved
end
19 changes: 19 additions & 0 deletions test/Serialization/PolyhedralGeometry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,25 @@ using Oscar: _integer_variables
end
end

@testset "Matroid" begin
@testset "Fano" begin
M = fano_matroid()
test_save_load_roundtrip(path, M) do loaded
@test sort(bases(M)) == sort(bases(loaded))
@test length(M) == length(loaded)
@test rank(M) == rank(loaded)
end
end
@testset "uniform" begin
M = uniform_matroid(2, 4)
test_save_load_roundtrip(path, M) do loaded
@test sort(bases(M)) == sort(bases(loaded))
@test length(M) == length(loaded)
@test rank(M) == rank(loaded)
end
end
end

@testset "Cone" begin
C = positive_hull([1 0; 0 1])
test_save_load_roundtrip(path, C) do loaded
Expand Down
Loading