Skip to content

Commit 58ccca9

Browse files
authored
Merge pull request #23 from ZIB-IOL/faster-matching
non-perfect matching made faster
2 parents 19f68bc + bcaf69d commit 58ccca9

2 files changed

Lines changed: 39 additions & 26 deletions

File tree

src/matchings.jl

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,28 @@
11

22
"""
3-
MatchingLMO{G}(g::Graphs)
3+
MatchingLMO{G}(g::G)
44
5-
Return an incidence vector v of the edges of `g`, ordered as `edges(g)` for a minimum-weight matching.
5+
Return an incidence vector v of the edges of `g` which has to be a `Graphs.AbstractGraph`, ordered as `edges(g)` for a minimum-weight matching.
6+
7+
Uses a reduction of the problem to minimum-weight perfect matching:
8+
(see https://homepages.cwi.nl/~schaefer/ftp/pdf/masters-thesis.pdf section 1.5.1).
69
"""
710
struct MatchingLMO{G} <: FrankWolfe.LinearMinimizationOracle
8-
graph::G
11+
original_graph::G
12+
extended_graph::G
13+
end
14+
15+
function MatchingLMO(original_graph::G) where {G}
16+
extended_graph = copy(original_graph)
17+
nvtx = nv(original_graph)
18+
add_vertices!(extended_graph, nvtx)
19+
for edge in edges(original_graph)
20+
add_edge!(extended_graph, src(edge) + nvtx, dst(edge) + nvtx)
21+
end
22+
for i in 1:nvtx
23+
add_edge!(extended_graph, i, i + nvtx)
24+
end
25+
return MatchingLMO{G}(original_graph, extended_graph)
926
end
1027

1128
function FrankWolfe.compute_extreme_point(
@@ -16,33 +33,28 @@ function FrankWolfe.compute_extreme_point(
1633
) where {M}
1734
N = length(direction)
1835
if v === nothing
19-
v = spzeros(N)
36+
v = spzeros(Int, N)
2037
else
2138
v .= 0
2239
end
23-
iter = collect(edges(lmo.graph))
24-
g = SimpleGraphFromIterator(iter)
25-
l = nv(g)
26-
add_vertices!(g, l)
27-
w = Dict{typeof(iter[1]),typeof(direction[1])}()
28-
for i in 1:N
29-
add_edge!(g, src(iter[i]) + l, dst(iter[i]) + l)
30-
w[iter[i]] = direction[i]
31-
w[Edge(src(iter[i]) + l, dst(iter[i]) + l)] = direction[i]
40+
nvtx = nv(lmo.original_graph)
41+
w = Dict{edgetype(lmo.original_graph), eltype(direction)}()
42+
for (i, edge) in enumerate(edges(lmo.original_graph))
43+
w[edge] = direction[i]
44+
w[Edge(src(edge) + nvtx, dst(edge) + nvtx)] = direction[i]
3245
end
3346

34-
for i in 1:l
35-
add_edge!(g, i, i + l)
36-
w[Edge(i, i + l)] = 0
47+
for i in 1:nvtx
48+
w[Edge(i, i + nvtx)] = 0
3749
end
3850

39-
match = GraphsMatching.minimum_weight_perfect_matching(g, w)
51+
match = GraphsMatching.minimum_weight_perfect_matching(lmo.extended_graph, w)
4052

4153
K = length(match.mate)
42-
for i in 1:K
43-
for j in 1:N
44-
if (match.mate[i] == src(iter[j]) && dst(iter[j]) == i)
45-
v[j] = 1
54+
for (i, edge) in enumerate(edges(lmo.original_graph))
55+
for k in 1:K
56+
if match.mate[k] == src(edge) && dst(edge) == k
57+
v[i] = 1
4658
end
4759
end
4860
end
@@ -58,11 +70,10 @@ The constructor verifies that the graph admits a perfect matching.
5870
"""
5971
struct PerfectMatchingLMO{G} <: FrankWolfe.LinearMinimizationOracle
6072
graph::G
61-
end
62-
63-
function PerfectMatchingLMO(graph::G) where {G}
64-
@assert nv(graph) % 2 == 0
65-
return PerfectMatchingLMO{G}(graph)
73+
function PerfectMatchingLMO(graph::G) where {G}
74+
@assert nv(graph) % 2 == 0
75+
return new{G}(graph)
76+
end
6677
end
6778

6879
function FrankWolfe.compute_extreme_point(

test/runtests.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ end
6161
end
6262
end
6363
@test v_sol == v
64+
v2 = FrankWolfe.compute_extreme_point(lmo, ones(M))
65+
@test norm(v2) == 0
6466
end
6567

6668

0 commit comments

Comments
 (0)