@@ -21,34 +21,40 @@ Returns MatchingResult containing:
2121"""
2222function maximum_weight_matching end
2323
24- function maximum_weight_matching (g:: Graph ,
25- optimizer,
26- w:: AbstractMatrix{U} = default_weights (g)) where {U <: Real }
24+ function maximum_weight_matching (
25+ g:: Graph ,
26+ optimizer,
27+ w:: AbstractMatrix{U} = default_weights (g),
28+ ) where {U<: Real }
2729
2830 model = Model (optimizer)
2931 n = nv (g)
3032 edge_list = collect (edges (g))
3133
3234 # put the edge weights in w in the right order to be compatible with edge_list
33- for j in 1 : n
34- for i in 1 : n
35- if i > j && w[i,j] > zero (U) && w[j,i] < w[i,j]
36- w[j,i] = w[i,j]
35+ for j = 1 : n
36+ for i = 1 : n
37+ if i > j && w[i, j] > zero (U) && w[j, i] < w[i, j]
38+ w[j, i] = w[i, j]
39+ end
40+ if Edge (i, j) ∉ edge_list
41+ w[i, j] = zero (U)
42+ end
3743 end
38- if Edge (i,j) ∉ edge_list
39- w[i,j] = zero (U)
40- end
41- end
4244 end
4345
4446 if is_bipartite (g)
45- @variable (model, x[edge_list] >= 0 ) # no need to enforce integrality
47+ @variable (model, x[edge_list] >= 0 ) # no need to enforce integrality
4648 else
47- @variable (model, x[edge_list] >= 0 , Int) # requires MIP solver
49+ @variable (model, x[edge_list] >= 0 , Int) # requires MIP solver
4850 end
49- @objective (model, Max, sum (x[e]* w[src (e),dst (e)] for e in edge_list))
51+ @objective (model, Max, sum (x[e] * w[src (e), dst (e)] for e in edge_list))
5052
51- @constraint (model, c1[i= 1 : n], sum (x[Edge (minmax (i,j))] for j in neighbors (g,i)) <= 1 )
53+ @constraint (
54+ model,
55+ c1[i = 1 : n],
56+ sum (x[Edge (minmax (i, j))] for j in neighbors (g, i)) <= 1
57+ )
5258 optimize! (model)
5359 status = JuMP. termination_status (model)
5460 status != MOI. OPTIMAL && error (" JuMP solver failed to find optimal solution." )
@@ -58,24 +64,28 @@ function maximum_weight_matching(g::Graph,
5864end
5965
6066""" Returns an array of mates from a dictionary that maps edges to {0,1} """
61- function dict_to_arr (n:: Int64 , solution:: JuMP.Containers.DenseAxisArray{U,1,Tuple{Array{E,1}}} , edge_list:: AbstractVector{E} ) where {U<: Real , E<: Edge }
62- mate = fill (- 1 ,n)
63- for e in edge_list
64- if solution[e] >= 1 - 1e-5 # Some tolerance to numerical approximations by the solver.
65- mate[src (e)] = dst (e)
66- mate[dst (e)] = src (e)
67+ function dict_to_arr (
68+ n:: Int64 ,
69+ solution:: JuMP.Containers.DenseAxisArray{U,1,Tuple{Array{E,1}}} ,
70+ edge_list:: AbstractVector{E} ,
71+ ) where {U<: Real ,E<: Edge }
72+ mate = fill (- 1 , n)
73+ for e in edge_list
74+ if solution[e] >= 1 - 1e-5 # Some tolerance to numerical approximations by the solver.
75+ mate[src (e)] = dst (e)
76+ mate[dst (e)] = src (e)
77+ end
6778 end
68- end
69- return mate
79+ return mate
7080end
7181
7282
7383function default_weights (g:: G ) where {G<: AbstractGraph }
74- m = spzeros (nv (g),nv (g))
75- for e in edges (g)
76- m[src (e),dst (e)] = 1
77- end
78- return m
84+ m = spzeros (nv (g), nv (g))
85+ for e in edges (g)
86+ m[src (e), dst (e)] = 1
87+ end
88+ return m
7989end
8090
8191"""
@@ -91,35 +101,37 @@ to find the maximum weight matching (see https://homepages.cwi.nl/~schaefer/ftp/
91101
92102Return an array of edges contained in the matching.
93103"""
94- function maximum_weight_matching_reduction (g:: Graph ,
95- w:: AbstractMatrix{U} = default_weights (g)) where {U <: Real }
96-
97- h = deepcopy (g)
98- iter = collect (edges (h))
99- l = nv (h)
100- add_vertices! (h,l)
101- weights = Dict {typeof(iter[1]),typeof(w[1][1])} ()
102- for edge in iter
103- add_edge! (h,src (edge) + l,dst (edge) + l)
104- weights[edge] = - w[src (edge),dst (edge)]
105- weights[Edge (dst (edge),src (edge))] = - w[src (edge),dst (edge)]
106- weights[Edge (src (edge) + l,dst (edge) + l)] = - w[src (edge),dst (edge)]
107- weights[Edge (dst (edge) + l,src (edge) + l)] = - w[src (edge),dst (edge)]
108- end
109- for i in 1 : l
110- add_edge! (g,i,i+ l)
111- weights[Edge (i,i+ l)] = 0
112- end
113-
114- match = minimum_weight_perfect_matching (h,weights)
115-
116- result = Edge[]
117-
118- for i in 1 : l
119- if (match. mate[i] <= l && match. mate[i] > 0 )
120- push! (result,Edge (i,match. mate[i]))
104+ function maximum_weight_matching_reduction (
105+ g:: Graph ,
106+ w:: AbstractMatrix{U} = default_weights (g),
107+ ) where {U<: Real }
108+
109+ h = deepcopy (g)
110+ iter = collect (edges (h))
111+ l = nv (h)
112+ add_vertices! (h, l)
113+ weights = Dict {typeof(iter[1]),typeof(w[1][1])} ()
114+ for edge in iter
115+ add_edge! (h, src (edge) + l, dst (edge) + l)
116+ weights[edge] = - w[src (edge), dst (edge)]
117+ weights[Edge (dst (edge), src (edge))] = - w[src (edge), dst (edge)]
118+ weights[Edge (src (edge) + l, dst (edge) + l)] = - w[src (edge), dst (edge)]
119+ weights[Edge (dst (edge) + l, src (edge) + l)] = - w[src (edge), dst (edge)]
120+ end
121+ for i = 1 : l
122+ add_edge! (g, i, i + l)
123+ weights[Edge (i, i + l)] = 0
124+ end
125+
126+ match = minimum_weight_perfect_matching (h, weights)
127+
128+ result = Edge[]
129+
130+ for i = 1 : l
131+ if (match. mate[i] <= l && match. mate[i] > 0 )
132+ push! (result, Edge (i, match. mate[i]))
133+ end
121134 end
122- end
123-
124- return result
135+
136+ return result
125137end
0 commit comments