From c614c2644ef599e70dd87577ac5e45babce0efdd Mon Sep 17 00:00:00 2001 From: etienneINSA Date: Thu, 2 May 2024 15:09:13 +0200 Subject: [PATCH 1/3] add matrix argument --- Project.toml | 2 + src/blossomv.jl | 19 ++ test/runtests.jl | 503 ++++++++++++++++++++++++----------------------- 3 files changed, 273 insertions(+), 251 deletions(-) diff --git a/Project.toml b/Project.toml index 5783ce8..64e7d05 100644 --- a/Project.toml +++ b/Project.toml @@ -11,6 +11,7 @@ JuMP = "4076af6c-e467-56ae-b986-b466b2749572" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +StaticGraphs = "4c8beaf5-199b-59a0-a7f2-21d17de635b6" [compat] BlossomV = "0.4" @@ -18,6 +19,7 @@ Graphs = "1.4, 1.7" Hungarian = "0.4, 0.6" JuMP = "1" MathOptInterface = "1" +StaticGraphs = "0.3.0" julia = "1" [extras] diff --git a/src/blossomv.jl b/src/blossomv.jl index da1e2d4..8a7d25e 100644 --- a/src/blossomv.jl +++ b/src/blossomv.jl @@ -68,3 +68,22 @@ function minimum_weight_perfect_matching(g::Graph, w::Dict{E,U}) where {U<:Integ end return MatchingResult(totweight, mate) end + +function minimum_weight_perfect_matching(g::Graph, w::AbstractMatrix{U}, cutoff, kws...) where {U <: Real} + wnew = Dict{Edge, U}() + for e in edges(g) + c = w[src(e), dst(e)] + if c <= cutoff + wnew[e] = c + end + end + return minimum_weight_perfect_matching(g, wnew; kws...) +end + +function minimum_weight_perfect_matching(g::Graph, w::AbstractMatrix{U} = default_weights(g), kws...) where {U <: Real} + wnew = Dict{Edge, U}() + for e in edges(g) + wnew[e] = w[src(e), dst(e)] + end + return minimum_weight_perfect_matching(g, wnew; kws...) +end diff --git a/test/runtests.jl b/test/runtests.jl index 0beb14f..0e0375e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -6,255 +6,256 @@ using JuMP using LinearAlgebra: I @testset "GraphsMatching" begin - -@testset "maximum_weight_matching" begin - g = complete_graph(3) - w = [ - 1 2 1 - 1 1 1 - 3 1 1 - ] - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) - @test match.mate[1] == 3 - @test match.weight ≈ 3 - - g = complete_graph(3) - w = zeros(3,3) - w[1,2] = 1 - w[3,2] = 1 - w[1,3] = 1 - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0),w) - @test match.weight ≈ 1 - - - g = Graph(4) - add_edge!(g, 1,3) - add_edge!(g, 1,4) - add_edge!(g, 2,4) - - w =zeros(4,4) - w[1,3] = 1 - w[1,4] = 3 - w[2,4] = 1 - - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0),w) - @test match.weight ≈ 3 - @test match.mate[1] == 4 - @test match.mate[2] == -1 - @test match.mate[3] == -1 - @test match.mate[4] == 1 - - g = Graph(4) - add_edge!(g, 1,2) - add_edge!(g, 2,3) - add_edge!(g, 3,1) - add_edge!(g, 3,4) - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0)) - @test match.weight ≈ 2 - @test match.mate[1] == 2 - @test match.mate[2] == 1 - @test match.mate[3] == 4 - @test match.mate[4] == 3 - - w = zeros(4,4) - w[1,2] = 1 - w[2,3] = 1 - w[1,3] = 1 - w[3,4] = 1 - - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) - @test match.weight ≈ 2 - @test match.mate[1] == 2 - @test match.mate[2] == 1 - @test match.mate[3] == 4 - @test match.mate[4] == 3 - - w = zeros(4,4) - w[1,2] = 1 - w[2,3] = 1 - w[1,3] = 5 - w[3,4] = 1 - - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0),w) - @test match.weight ≈ 5 - @test match.mate[1] == 3 - @test match.mate[2] == -1 - @test match.mate[3] == 1 - @test match.mate[4] == -1 -end - - -@testset "maximum_weight_maximal_matching" begin - - g = complete_bipartite_graph(2,2) - w = zeros(4,4) - w[1,3] = 10. - w[1,4] = 1. - w[2,3] = 2. - w[2,4] = 11. - match = maximum_weight_maximal_matching(g, w, algorithm=LPAlgorithm(), optimizer=optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0)) - @test match.weight ≈ 21 - @test match.mate[1] == 3 - @test match.mate[3] == 1 - @test match.mate[2] == 4 - @test match.mate[4] == 2 - - g =complete_bipartite_graph(2,4) - w =zeros(6,6) - w[1,3] = 10 - w[1,4] = 0.5 - w[2,3] = 11 - w[2,4] = 1 - match = maximum_weight_maximal_matching(g, w, algorithm=LPAlgorithm(), optimizer=optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0)) - @test match.weight ≈ 11.5 - @test match.mate[1] == 4 - @test match.mate[4] == 1 - @test match.mate[2] == 3 - @test match.mate[3] == 2 - - g =complete_bipartite_graph(2,6) - w =zeros(8,8) - w[1,3] = 10 - w[1,4] = 0.5 - w[2,3] = 11 - w[2,4] = 1 - w[2,5] = -1 - w[2,6] = -1 - match = maximum_weight_maximal_matching(g, w, algorithm=LPAlgorithm(), optimizer=optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), cutoff=0) - @test match.weight ≈ 11.5 - @test match.mate[1] == 4 - @test match.mate[4] == 1 - @test match.mate[2] == 3 - @test match.mate[3] == 2 - - g =complete_bipartite_graph(4,2) - w = zeros(6,6) - w[3,5] = 10 - w[3,6] = 0.5 - w[2,5] = 11 - w[1,6] = 1 - w[1,5] = -1 - - match = maximum_weight_maximal_matching(g, w, algorithm=LPAlgorithm(), optimizer=optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), cutoff=0) - @test match.weight ≈ 12 - @test match.mate[1] == 6 - @test match.mate[2] == 5 - @test match.mate[3] == -1 - @test match.mate[4] == -1 - @test match.mate[5] == 2 - @test match.mate[6] == 1 - - - g = complete_bipartite_graph(2, 2) - w = zeros(4, 4) - w[1, 3] = 10. - w[1, 4] = 1. - w[2, 3] = 2. - w[2, 4] = 11. - match = maximum_weight_maximal_matching(g, w, algorithm=HungarianAlgorithm()) - @test match.weight ≈ 21 - @test match.mate[1] == 3 - @test match.mate[3] == 1 - @test match.mate[2] == 4 - @test match.mate[4] == 2 - - g = complete_graph(3) - w = zeros(3, 3) - @test ! is_bipartite(g) - @test_throws ErrorException maximum_weight_maximal_matching(g, w, algorithm=HungarianAlgorithm()) - - g = complete_bipartite_graph(2, 4) - w = zeros(6, 6) - w[1, 3] = 10 - w[1, 4] = 0.5 - w[2, 3] = 11 - w[2, 4] = 1 - match = maximum_weight_maximal_matching(g, w, algorithm=HungarianAlgorithm()) - @test match.weight ≈ 11.5 - - g = Graph(4) - add_edge!(g, 1, 3) - add_edge!(g, 1, 4) - add_edge!(g, 2, 4) - w = zeros(4, 4) - w[1, 3] = 1 - w[1, 4] = 3 - w[2, 4] = 1 - match = maximum_weight_maximal_matching(g, w, algorithm=HungarianAlgorithm()) - @test match.weight ≈ 2 - -end - - - -@testset "minimum_weight_perfect_matching" begin - - w = Dict(Edge(1,2)=> 500) - g =Graph(2) - add_edge!(g,1,2) - match = minimum_weight_perfect_matching(g, w) - @test match.mate[1] == 2 - - - w=Dict( Edge(1,2)=>500, - Edge(1,3)=>600, - Edge(2,3)=>700, - Edge(3,4)=>100, - Edge(2,4)=>1000) - - g = complete_graph(4) - match = minimum_weight_perfect_matching(g, w) - @test match.mate[1] == 2 - @test match.mate[2] == 1 - @test match.mate[3] == 4 - @test match.mate[4] == 3 - @test match.weight ≈ 600 - - w = Dict( - Edge(1, 2) => 500, - Edge(1, 3) => 400, - Edge(2, 3) => 300, - Edge(3, 4) => 1000, - Edge(2, 4) => 1000 - ) - g = complete_graph(4) - match = minimum_weight_perfect_matching(g, w) - @test match.mate[1] == 3 - @test match.mate[2] == 4 - @test match.mate[3] == 1 - @test match.mate[4] == 2 - @test match.weight ≈ 1400 - - g =complete_bipartite_graph(2,2) - w =Dict{Edge,Float64}() - w[Edge(1,3)] = -10 - w[Edge(1,4)] = -0.5 - w[Edge(2,3)] = -11 - w[Edge(2,4)] = -1 - - match = minimum_weight_perfect_matching(g, w) - @test match.mate[1] == 4 - @test match.mate[4] == 1 - @test match.mate[2] == 3 - @test match.mate[3] == 2 - @test match.weight ≈ -11.5 - - - g = complete_graph(4) - w = Dict{Edge,Float64}() - w[Edge(1,3)] = 10 - w[Edge(1,4)] = 0.5 - w[Edge(2,3)] = 11 - w[Edge(2,4)] = 2 - w[Edge(1,2)] = 100 - - match = minimum_weight_perfect_matching(g, w, 50) - @test match.mate[1] == 4 - @test match.mate[4] == 1 - @test match.mate[2] == 3 - @test match.mate[3] == 2 - @test match.weight ≈ 11.5 -end - - + @testset "maximum_weight_matching" begin + g = complete_graph(3) + w = [ + 1 2 1 + 1 1 1 + 3 1 1 + ] + match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) + @test match.mate[1] == 3 + @test match.weight ≈ 3 + + g = complete_graph(3) + w = zeros(3, 3) + w[1, 2] = 1 + w[3, 2] = 1 + w[1, 3] = 1 + match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) + @test match.weight ≈ 1 + + g = Graph(4) + add_edge!(g, 1, 3) + add_edge!(g, 1, 4) + add_edge!(g, 2, 4) + + w = zeros(4, 4) + w[1, 3] = 1 + w[1, 4] = 3 + w[2, 4] = 1 + + match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) + @test match.weight ≈ 3 + @test match.mate[1] == 4 + @test match.mate[2] == -1 + @test match.mate[3] == -1 + @test match.mate[4] == 1 + + g = Graph(4) + add_edge!(g, 1, 2) + add_edge!(g, 2, 3) + add_edge!(g, 3, 1) + add_edge!(g, 3, 4) + match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0)) + @test match.weight ≈ 2 + @test match.mate[1] == 2 + @test match.mate[2] == 1 + @test match.mate[3] == 4 + @test match.mate[4] == 3 + + w = zeros(4, 4) + w[1, 2] = 1 + w[2, 3] = 1 + w[1, 3] = 1 + w[3, 4] = 1 + + match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) + @test match.weight ≈ 2 + @test match.mate[1] == 2 + @test match.mate[2] == 1 + @test match.mate[3] == 4 + @test match.mate[4] == 3 + + w = zeros(4, 4) + w[1, 2] = 1 + w[2, 3] = 1 + w[1, 3] = 5 + w[3, 4] = 1 + + match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) + @test match.weight ≈ 5 + @test match.mate[1] == 3 + @test match.mate[2] == -1 + @test match.mate[3] == 1 + @test match.mate[4] == -1 + end + + @testset "maximum_weight_maximal_matching" begin + g = complete_bipartite_graph(2, 2) + w = zeros(4, 4) + w[1, 3] = 10.0 + w[1, 4] = 1.0 + w[2, 3] = 2.0 + w[2, 4] = 11.0 + match = maximum_weight_maximal_matching(g, w; algorithm = LPAlgorithm(), optimizer = optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0)) + @test match.weight ≈ 21 + @test match.mate[1] == 3 + @test match.mate[3] == 1 + @test match.mate[2] == 4 + @test match.mate[4] == 2 + + g = complete_bipartite_graph(2, 4) + w = zeros(6, 6) + w[1, 3] = 10 + w[1, 4] = 0.5 + w[2, 3] = 11 + w[2, 4] = 1 + match = maximum_weight_maximal_matching(g, w; algorithm = LPAlgorithm(), optimizer = optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0)) + @test match.weight ≈ 11.5 + @test match.mate[1] == 4 + @test match.mate[4] == 1 + @test match.mate[2] == 3 + @test match.mate[3] == 2 + + g = complete_bipartite_graph(2, 6) + w = zeros(8, 8) + w[1, 3] = 10 + w[1, 4] = 0.5 + w[2, 3] = 11 + w[2, 4] = 1 + w[2, 5] = -1 + w[2, 6] = -1 + match = maximum_weight_maximal_matching(g, w; algorithm = LPAlgorithm(), optimizer = optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), cutoff = 0) + @test match.weight ≈ 11.5 + @test match.mate[1] == 4 + @test match.mate[4] == 1 + @test match.mate[2] == 3 + @test match.mate[3] == 2 + + g = complete_bipartite_graph(4, 2) + w = zeros(6, 6) + w[3, 5] = 10 + w[3, 6] = 0.5 + w[2, 5] = 11 + w[1, 6] = 1 + w[1, 5] = -1 + + match = maximum_weight_maximal_matching(g, w; algorithm = LPAlgorithm(), optimizer = optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), cutoff = 0) + @test match.weight ≈ 12 + @test match.mate[1] == 6 + @test match.mate[2] == 5 + @test match.mate[3] == -1 + @test match.mate[4] == -1 + @test match.mate[5] == 2 + @test match.mate[6] == 1 + + g = complete_bipartite_graph(2, 2) + w = zeros(4, 4) + w[1, 3] = 10.0 + w[1, 4] = 1.0 + w[2, 3] = 2.0 + w[2, 4] = 11.0 + match = maximum_weight_maximal_matching(g, w; algorithm = HungarianAlgorithm()) + @test match.weight ≈ 21 + @test match.mate[1] == 3 + @test match.mate[3] == 1 + @test match.mate[2] == 4 + @test match.mate[4] == 2 + + g = complete_graph(3) + w = zeros(3, 3) + @test !is_bipartite(g) + @test_throws ErrorException maximum_weight_maximal_matching(g, w, algorithm = HungarianAlgorithm()) + + g = complete_bipartite_graph(2, 4) + w = zeros(6, 6) + w[1, 3] = 10 + w[1, 4] = 0.5 + w[2, 3] = 11 + w[2, 4] = 1 + match = maximum_weight_maximal_matching(g, w; algorithm = HungarianAlgorithm()) + @test match.weight ≈ 11.5 + + g = Graph(4) + add_edge!(g, 1, 3) + add_edge!(g, 1, 4) + add_edge!(g, 2, 4) + w = zeros(4, 4) + w[1, 3] = 1 + w[1, 4] = 3 + w[2, 4] = 1 + match = maximum_weight_maximal_matching(g, w; algorithm = HungarianAlgorithm()) + @test match.weight ≈ 2 + end + + @testset "minimum_weight_perfect_matching" begin + w = Dict(Edge(1, 2) => 500) + g = Graph(2) + add_edge!(g, 1, 2) + match = minimum_weight_perfect_matching(g, w) + @test match.mate[1] == 2 + + w = Dict(Edge(1, 2) => 500, + Edge(1, 3) => 600, + Edge(2, 3) => 700, + Edge(3, 4) => 100, + Edge(2, 4) => 1000) + + g = complete_graph(4) + match = minimum_weight_perfect_matching(g, w) + @test match.mate[1] == 2 + @test match.mate[2] == 1 + @test match.mate[3] == 4 + @test match.mate[4] == 3 + @test match.weight ≈ 600 + + w = Dict( + Edge(1, 2) => 500, + Edge(1, 3) => 400, + Edge(2, 3) => 300, + Edge(3, 4) => 1000, + Edge(2, 4) => 1000, + ) + g = complete_graph(4) + match = minimum_weight_perfect_matching(g, w) + @test match.mate[1] == 3 + @test match.mate[2] == 4 + @test match.mate[3] == 1 + @test match.mate[4] == 2 + @test match.weight ≈ 1400 + + g = complete_bipartite_graph(2, 2) + w = Dict{Edge, Float64}() + w[Edge(1, 3)] = -10 + w[Edge(1, 4)] = -0.5 + w[Edge(2, 3)] = -11 + w[Edge(2, 4)] = -1 + + match = minimum_weight_perfect_matching(g, w) + @test match.mate[1] == 4 + @test match.mate[4] == 1 + @test match.mate[2] == 3 + @test match.mate[3] == 2 + @test match.weight ≈ -11.5 + + g = complete_graph(4) + w = Dict{Edge, Float64}() + w[Edge(1, 3)] = 10 + w[Edge(1, 4)] = 0.5 + w[Edge(2, 3)] = 11 + w[Edge(2, 4)] = 2 + w[Edge(1, 2)] = 100 + + match = minimum_weight_perfect_matching(g, w, 50) + @test match.mate[1] == 4 + @test match.mate[4] == 1 + @test match.mate[2] == 3 + @test match.mate[3] == 2 + @test match.weight ≈ 11.5 + + g = complete_graph(4) + w = [ + 3 3 1 3 + 3 3 3 1 + 1 3 3 3 + 3 1 3 3 + ] + match = minimum_weight_perfect_matching(g, w) + @test match.weight ≈ 2 + @test match.mate[1] == 3 + @test match.mate[2] == 4 + @test match.mate[3] == 1 + @test match.mate[4] == 2 + end end From 141b5751381cb3a8b50d1f4323cbc2bac31b04a3 Mon Sep 17 00:00:00 2001 From: etienneINSA Date: Fri, 3 May 2024 11:08:46 +0200 Subject: [PATCH 2/3] rework tests --- Project.toml | 4 +- src/blossomv.jl | 4 +- test/runtests.jl | 553 ++++++++++++++++++++++++++++------------------- 3 files changed, 331 insertions(+), 230 deletions(-) diff --git a/Project.toml b/Project.toml index 64e7d05..a559d4b 100644 --- a/Project.toml +++ b/Project.toml @@ -11,7 +11,7 @@ JuMP = "4076af6c-e467-56ae-b986-b466b2749572" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" -StaticGraphs = "4c8beaf5-199b-59a0-a7f2-21d17de635b6" +WatchJuliaBurn = "952999c0-2bc0-44cb-b633-dc1e299b187b" [compat] BlossomV = "0.4" @@ -19,7 +19,7 @@ Graphs = "1.4, 1.7" Hungarian = "0.4, 0.6" JuMP = "1" MathOptInterface = "1" -StaticGraphs = "0.3.0" +WatchJuliaBurn = "0.2.0" julia = "1" [extras] diff --git a/src/blossomv.jl b/src/blossomv.jl index 8a7d25e..4cb6e01 100644 --- a/src/blossomv.jl +++ b/src/blossomv.jl @@ -77,7 +77,7 @@ function minimum_weight_perfect_matching(g::Graph, w::AbstractMatrix{U}, cutoff, wnew[e] = c end end - return minimum_weight_perfect_matching(g, wnew; kws...) + return minimum_weight_perfect_matching(g, wnew, kws...) end function minimum_weight_perfect_matching(g::Graph, w::AbstractMatrix{U} = default_weights(g), kws...) where {U <: Real} @@ -85,5 +85,5 @@ function minimum_weight_perfect_matching(g::Graph, w::AbstractMatrix{U} = defaul for e in edges(g) wnew[e] = w[src(e), dst(e)] end - return minimum_weight_perfect_matching(g, wnew; kws...) + return minimum_weight_perfect_matching(g, wnew, kws...) end diff --git a/test/runtests.jl b/test/runtests.jl index 0e0375e..31dc01b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -6,256 +6,357 @@ using JuMP using LinearAlgebra: I @testset "GraphsMatching" begin - @testset "maximum_weight_matching" begin - g = complete_graph(3) - w = [ - 1 2 1 - 1 1 1 - 3 1 1 - ] - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) - @test match.mate[1] == 3 - @test match.weight ≈ 3 + @testset "maximum_weight_matching" begin + g = complete_graph(3) + w = [ + 1 2 1 + 1 1 1 + 3 1 1 + ] + match = maximum_weight_matching( + g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w + ) + @test match.mate[1] == 3 + @test match.weight ≈ 3 - g = complete_graph(3) - w = zeros(3, 3) - w[1, 2] = 1 - w[3, 2] = 1 - w[1, 3] = 1 - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) - @test match.weight ≈ 1 + g = complete_graph(3) + w = zeros(3, 3) + w[1, 2] = 1 + w[3, 2] = 1 + w[1, 3] = 1 + match = maximum_weight_matching( + g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w + ) + @test match.weight ≈ 1 - g = Graph(4) - add_edge!(g, 1, 3) - add_edge!(g, 1, 4) - add_edge!(g, 2, 4) + g = Graph(4) + add_edge!(g, 1, 3) + add_edge!(g, 1, 4) + add_edge!(g, 2, 4) - w = zeros(4, 4) - w[1, 3] = 1 - w[1, 4] = 3 - w[2, 4] = 1 + w = zeros(4, 4) + w[1, 3] = 1 + w[1, 4] = 3 + w[2, 4] = 1 - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) - @test match.weight ≈ 3 - @test match.mate[1] == 4 - @test match.mate[2] == -1 - @test match.mate[3] == -1 - @test match.mate[4] == 1 + match = maximum_weight_matching( + g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w + ) + @test match.weight ≈ 3 + @test match.mate[1] == 4 + @test match.mate[2] == -1 + @test match.mate[3] == -1 + @test match.mate[4] == 1 - g = Graph(4) - add_edge!(g, 1, 2) - add_edge!(g, 2, 3) - add_edge!(g, 3, 1) - add_edge!(g, 3, 4) - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0)) - @test match.weight ≈ 2 - @test match.mate[1] == 2 - @test match.mate[2] == 1 - @test match.mate[3] == 4 - @test match.mate[4] == 3 + g = Graph(4) + add_edge!(g, 1, 2) + add_edge!(g, 2, 3) + add_edge!(g, 3, 1) + add_edge!(g, 3, 4) + match = maximum_weight_matching( + g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0) + ) + @test match.weight ≈ 2 + @test match.mate[1] == 2 + @test match.mate[2] == 1 + @test match.mate[3] == 4 + @test match.mate[4] == 3 - w = zeros(4, 4) - w[1, 2] = 1 - w[2, 3] = 1 - w[1, 3] = 1 - w[3, 4] = 1 + w = zeros(4, 4) + w[1, 2] = 1 + w[2, 3] = 1 + w[1, 3] = 1 + w[3, 4] = 1 - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) - @test match.weight ≈ 2 - @test match.mate[1] == 2 - @test match.mate[2] == 1 - @test match.mate[3] == 4 - @test match.mate[4] == 3 + match = maximum_weight_matching( + g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w + ) + @test match.weight ≈ 2 + @test match.mate[1] == 2 + @test match.mate[2] == 1 + @test match.mate[3] == 4 + @test match.mate[4] == 3 - w = zeros(4, 4) - w[1, 2] = 1 - w[2, 3] = 1 - w[1, 3] = 5 - w[3, 4] = 1 + w = zeros(4, 4) + w[1, 2] = 1 + w[2, 3] = 1 + w[1, 3] = 5 + w[3, 4] = 1 - match = maximum_weight_matching(g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w) - @test match.weight ≈ 5 - @test match.mate[1] == 3 - @test match.mate[2] == -1 - @test match.mate[3] == 1 - @test match.mate[4] == -1 - end + match = maximum_weight_matching( + g, optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), w + ) + @test match.weight ≈ 5 + @test match.mate[1] == 3 + @test match.mate[2] == -1 + @test match.mate[3] == 1 + @test match.mate[4] == -1 + end - @testset "maximum_weight_maximal_matching" begin - g = complete_bipartite_graph(2, 2) - w = zeros(4, 4) - w[1, 3] = 10.0 - w[1, 4] = 1.0 - w[2, 3] = 2.0 - w[2, 4] = 11.0 - match = maximum_weight_maximal_matching(g, w; algorithm = LPAlgorithm(), optimizer = optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0)) - @test match.weight ≈ 21 - @test match.mate[1] == 3 - @test match.mate[3] == 1 - @test match.mate[2] == 4 - @test match.mate[4] == 2 + @testset "maximum_weight_maximal_matching" begin + g = complete_bipartite_graph(2, 2) + w = zeros(4, 4) + w[1, 3] = 10.0 + w[1, 4] = 1.0 + w[2, 3] = 2.0 + w[2, 4] = 11.0 + match = maximum_weight_maximal_matching( + g, + w; + algorithm=LPAlgorithm(), + optimizer=optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), + ) + @test match.weight ≈ 21 + @test match.mate[1] == 3 + @test match.mate[3] == 1 + @test match.mate[2] == 4 + @test match.mate[4] == 2 - g = complete_bipartite_graph(2, 4) - w = zeros(6, 6) - w[1, 3] = 10 - w[1, 4] = 0.5 - w[2, 3] = 11 - w[2, 4] = 1 - match = maximum_weight_maximal_matching(g, w; algorithm = LPAlgorithm(), optimizer = optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0)) - @test match.weight ≈ 11.5 - @test match.mate[1] == 4 - @test match.mate[4] == 1 - @test match.mate[2] == 3 - @test match.mate[3] == 2 + g = complete_bipartite_graph(2, 4) + w = zeros(6, 6) + w[1, 3] = 10 + w[1, 4] = 0.5 + w[2, 3] = 11 + w[2, 4] = 1 + match = maximum_weight_maximal_matching( + g, + w; + algorithm=LPAlgorithm(), + optimizer=optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), + ) + @test match.weight ≈ 11.5 + @test match.mate[1] == 4 + @test match.mate[4] == 1 + @test match.mate[2] == 3 + @test match.mate[3] == 2 - g = complete_bipartite_graph(2, 6) - w = zeros(8, 8) - w[1, 3] = 10 - w[1, 4] = 0.5 - w[2, 3] = 11 - w[2, 4] = 1 - w[2, 5] = -1 - w[2, 6] = -1 - match = maximum_weight_maximal_matching(g, w; algorithm = LPAlgorithm(), optimizer = optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), cutoff = 0) - @test match.weight ≈ 11.5 - @test match.mate[1] == 4 - @test match.mate[4] == 1 - @test match.mate[2] == 3 - @test match.mate[3] == 2 + g = complete_bipartite_graph(2, 6) + w = zeros(8, 8) + w[1, 3] = 10 + w[1, 4] = 0.5 + w[2, 3] = 11 + w[2, 4] = 1 + w[2, 5] = -1 + w[2, 6] = -1 + match = maximum_weight_maximal_matching( + g, + w; + algorithm=LPAlgorithm(), + optimizer=optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), + cutoff=0, + ) + @test match.weight ≈ 11.5 + @test match.mate[1] == 4 + @test match.mate[4] == 1 + @test match.mate[2] == 3 + @test match.mate[3] == 2 - g = complete_bipartite_graph(4, 2) - w = zeros(6, 6) - w[3, 5] = 10 - w[3, 6] = 0.5 - w[2, 5] = 11 - w[1, 6] = 1 - w[1, 5] = -1 + g = complete_bipartite_graph(4, 2) + w = zeros(6, 6) + w[3, 5] = 10 + w[3, 6] = 0.5 + w[2, 5] = 11 + w[1, 6] = 1 + w[1, 5] = -1 - match = maximum_weight_maximal_matching(g, w; algorithm = LPAlgorithm(), optimizer = optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), cutoff = 0) - @test match.weight ≈ 12 - @test match.mate[1] == 6 - @test match.mate[2] == 5 - @test match.mate[3] == -1 - @test match.mate[4] == -1 - @test match.mate[5] == 2 - @test match.mate[6] == 1 + match = maximum_weight_maximal_matching( + g, + w; + algorithm=LPAlgorithm(), + optimizer=optimizer_with_attributes(Cbc.Optimizer, "LogLevel" => 0), + cutoff=0, + ) + @test match.weight ≈ 12 + @test match.mate[1] == 6 + @test match.mate[2] == 5 + @test match.mate[3] == -1 + @test match.mate[4] == -1 + @test match.mate[5] == 2 + @test match.mate[6] == 1 - g = complete_bipartite_graph(2, 2) - w = zeros(4, 4) - w[1, 3] = 10.0 - w[1, 4] = 1.0 - w[2, 3] = 2.0 - w[2, 4] = 11.0 - match = maximum_weight_maximal_matching(g, w; algorithm = HungarianAlgorithm()) - @test match.weight ≈ 21 - @test match.mate[1] == 3 - @test match.mate[3] == 1 - @test match.mate[2] == 4 - @test match.mate[4] == 2 + g = complete_bipartite_graph(2, 2) + w = zeros(4, 4) + w[1, 3] = 10.0 + w[1, 4] = 1.0 + w[2, 3] = 2.0 + w[2, 4] = 11.0 + match = maximum_weight_maximal_matching(g, w; algorithm=HungarianAlgorithm()) + @test match.weight ≈ 21 + @test match.mate[1] == 3 + @test match.mate[3] == 1 + @test match.mate[2] == 4 + @test match.mate[4] == 2 - g = complete_graph(3) - w = zeros(3, 3) - @test !is_bipartite(g) - @test_throws ErrorException maximum_weight_maximal_matching(g, w, algorithm = HungarianAlgorithm()) + g = complete_graph(3) + w = zeros(3, 3) + @test !is_bipartite(g) + @test_throws ErrorException maximum_weight_maximal_matching( + g, w, algorithm=HungarianAlgorithm() + ) - g = complete_bipartite_graph(2, 4) - w = zeros(6, 6) - w[1, 3] = 10 - w[1, 4] = 0.5 - w[2, 3] = 11 - w[2, 4] = 1 - match = maximum_weight_maximal_matching(g, w; algorithm = HungarianAlgorithm()) - @test match.weight ≈ 11.5 + g = complete_bipartite_graph(2, 4) + w = zeros(6, 6) + w[1, 3] = 10 + w[1, 4] = 0.5 + w[2, 3] = 11 + w[2, 4] = 1 + match = maximum_weight_maximal_matching(g, w; algorithm=HungarianAlgorithm()) + @test match.weight ≈ 11.5 - g = Graph(4) - add_edge!(g, 1, 3) - add_edge!(g, 1, 4) - add_edge!(g, 2, 4) - w = zeros(4, 4) - w[1, 3] = 1 - w[1, 4] = 3 - w[2, 4] = 1 - match = maximum_weight_maximal_matching(g, w; algorithm = HungarianAlgorithm()) - @test match.weight ≈ 2 - end + g = Graph(4) + add_edge!(g, 1, 3) + add_edge!(g, 1, 4) + add_edge!(g, 2, 4) + w = zeros(4, 4) + w[1, 3] = 1 + w[1, 4] = 3 + w[2, 4] = 1 + match = maximum_weight_maximal_matching(g, w; algorithm=HungarianAlgorithm()) + @test match.weight ≈ 2 + end - @testset "minimum_weight_perfect_matching" begin - w = Dict(Edge(1, 2) => 500) - g = Graph(2) - add_edge!(g, 1, 2) - match = minimum_weight_perfect_matching(g, w) - @test match.mate[1] == 2 + @testset "minimum_weight_perfect_matching" begin + wmat = [ + 0 500 + 500 0 + ] + wdict = Dict(Edge(1, 2) => 500) + g = Graph(2) + add_edge!(g, 1, 2) + match = minimum_weight_perfect_matching(g, wmat) + @test match.mate[1] == 2 + match = minimum_weight_perfect_matching(g, wdict) + @test match.mate[1] == 2 - w = Dict(Edge(1, 2) => 500, - Edge(1, 3) => 600, - Edge(2, 3) => 700, - Edge(3, 4) => 100, - Edge(2, 4) => 1000) + wmat = [ + 0 500 600 0 + 500 0 700 1000 + 600 700 0 100 + 0 1000 100 0 + ] + g = Graph([ + Edge(1, 2), + Edge(1, 3), + Edge(2, 3), + Edge(3, 4), + Edge(2, 4) + ]) + match = minimum_weight_perfect_matching(g, wmat) + @test match.mate[1] == 2 + @test match.mate[2] == 1 + @test match.mate[3] == 4 + @test match.mate[4] == 3 + @test match.weight ≈ 600 - g = complete_graph(4) - match = minimum_weight_perfect_matching(g, w) - @test match.mate[1] == 2 - @test match.mate[2] == 1 - @test match.mate[3] == 4 - @test match.mate[4] == 3 - @test match.weight ≈ 600 + wdict = Dict( + Edge(1, 2) => 500, + Edge(1, 3) => 600, + Edge(2, 3) => 700, + Edge(3, 4) => 100, + Edge(2, 4) => 1000, + ) + g = Graph(4) + match = minimum_weight_perfect_matching(g, wdict) + @test match.mate[1] == 2 + @test match.mate[2] == 1 + @test match.mate[3] == 4 + @test match.mate[4] == 3 + @test match.weight ≈ 600 - w = Dict( - Edge(1, 2) => 500, - Edge(1, 3) => 400, - Edge(2, 3) => 300, - Edge(3, 4) => 1000, - Edge(2, 4) => 1000, - ) - g = complete_graph(4) - match = minimum_weight_perfect_matching(g, w) - @test match.mate[1] == 3 - @test match.mate[2] == 4 - @test match.mate[3] == 1 - @test match.mate[4] == 2 - @test match.weight ≈ 1400 + wmat = [ + 0 500 400 0 + 500 0 300 1000 + 400 300 0 1000 + 0 1000 1000 0 + ] + g = Graph([ + Edge(1, 2), + Edge(1, 3), + Edge(2, 3), + Edge(3, 4), + Edge(2, 4), + ]) + match = minimum_weight_perfect_matching(g, wmat) + @test match.mate[1] == 3 + @test match.mate[2] == 4 + @test match.mate[3] == 1 + @test match.mate[4] == 2 + @test match.weight ≈ 1400 - g = complete_bipartite_graph(2, 2) - w = Dict{Edge, Float64}() - w[Edge(1, 3)] = -10 - w[Edge(1, 4)] = -0.5 - w[Edge(2, 3)] = -11 - w[Edge(2, 4)] = -1 + wdict = Dict( + Edge(1, 2) => 500, + Edge(1, 3) => 400, + Edge(2, 3) => 300, + Edge(3, 4) => 1000, + Edge(2, 4) => 1000, + ) + g = complete_graph(4) + match = minimum_weight_perfect_matching(g, wdict) + @test match.mate[1] == 3 + @test match.mate[2] == 4 + @test match.mate[3] == 1 + @test match.mate[4] == 2 + @test match.weight ≈ 1400 - match = minimum_weight_perfect_matching(g, w) - @test match.mate[1] == 4 - @test match.mate[4] == 1 - @test match.mate[2] == 3 - @test match.mate[3] == 2 - @test match.weight ≈ -11.5 + wmat = Matrix{Float64}([ + 0 0 -10 -0.5 + 0 0 -11 -1 + -10 -11 0 0 + -0.5 -1 0 0 + ]) + wdict= Dict{Edge,Float64}( + Edge(1, 3) => -10, + Edge(1, 4) => -0.5, + Edge(2, 3) => -11, + Edge(2, 4) => -1 + ) + g = complete_bipartite_graph(2, 2) + match = minimum_weight_perfect_matching(g, wmat) + @test match.mate[1] == 4 + @test match.mate[4] == 1 + @test match.mate[2] == 3 + @test match.mate[3] == 2 + @test match.weight ≈ -11.5 + match = minimum_weight_perfect_matching(g, wdict) + @test match.mate[1] == 4 + @test match.mate[4] == 1 + @test match.mate[2] == 3 + @test match.mate[3] == 2 + @test match.weight ≈ -11.5 - g = complete_graph(4) - w = Dict{Edge, Float64}() - w[Edge(1, 3)] = 10 - w[Edge(1, 4)] = 0.5 - w[Edge(2, 3)] = 11 - w[Edge(2, 4)] = 2 - w[Edge(1, 2)] = 100 + wmat = Matrix{Float64}([ + 0 100 10 0.5 + 100 0 11 2 + 10 11 0 0 + 0.5 2 0 0 + ]) + g = Graph([ + Edge(1, 3), + Edge(1, 4), + Edge(2, 3), + Edge(2, 4), + Edge(1, 2) + ]) + match = minimum_weight_perfect_matching(g, wmat, 50) + @test match.mate[1] == 4 + @test match.mate[4] == 1 + @test match.mate[2] == 3 + @test match.mate[3] == 2 + @test match.weight ≈ 11.5 - match = minimum_weight_perfect_matching(g, w, 50) - @test match.mate[1] == 4 - @test match.mate[4] == 1 - @test match.mate[2] == 3 - @test match.mate[3] == 2 - @test match.weight ≈ 11.5 - - g = complete_graph(4) - w = [ - 3 3 1 3 - 3 3 3 1 - 1 3 3 3 - 3 1 3 3 - ] - match = minimum_weight_perfect_matching(g, w) - @test match.weight ≈ 2 - @test match.mate[1] == 3 - @test match.mate[2] == 4 - @test match.mate[3] == 1 - @test match.mate[4] == 2 - end + wdict = Dict{Edge,Float64}( + Edge(1, 3) => 10, + Edge(1, 4) => 0.5, + Edge(2, 3) => 11, + Edge(2, 4) => 2, + Edge(1, 2) => 100 + ) + g = complete_graph(4) + match = minimum_weight_perfect_matching(g, wdict, 50) + @test match.mate[1] == 4 + @test match.mate[4] == 1 + @test match.mate[2] == 3 + @test match.mate[3] == 2 + @test match.weight ≈ 11.5 + end end From cf516d0c5136ad55db9376e067d311d0bd3b6ea0 Mon Sep 17 00:00:00 2001 From: etienneINSA Date: Fri, 3 May 2024 14:11:03 +0200 Subject: [PATCH 3/3] change doc function --- src/blossomv.jl | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/blossomv.jl b/src/blossomv.jl index 4cb6e01..29e2bfc 100644 --- a/src/blossomv.jl +++ b/src/blossomv.jl @@ -1,19 +1,12 @@ """ - minimum_weight_perfect_matching(g, w::Dict{Edge,Real}) - minimum_weight_perfect_matching(g, w::Dict{Edge,Real}, cutoff) + minimum_weight_perfect_matching(g, w::AbstractMatrix{U}) -Given a graph `g` and an edgemap `w` containing weights associated to edges, -returns a matching with the mimimum total weight among the ones containing -exactly `nv(g)/2` edges. - -Edges in `g` not present in `w` will not be considered for the matching. +Given a graph `g` and weights `w`, returns a matching with the mimimum total +weight among the ones containing exactly `nv(g)/2` edges. This function relies on the BlossomV.jl package, a julia wrapper around Kolmogorov's BlossomV algorithm. -Eventually a `cutoff` argument can be given, to the reduce computational time -excluding edges with weights higher than the cutoff. - The returned object is of type `MatchingResult`. In case of error try to change the optional argument `tmaxscale` (default is `tmaxscale=10`).