@@ -21,34 +21,40 @@ Returns MatchingResult containing:
21
21
"""
22
22
function maximum_weight_matching end
23
23
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 }
27
29
28
30
model = Model (optimizer)
29
31
n = nv (g)
30
32
edge_list = collect (edges (g))
31
33
32
34
# 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
37
43
end
38
- if Edge (i,j) ∉ edge_list
39
- w[i,j] = zero (U)
40
- end
41
- end
42
44
end
43
45
44
46
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
46
48
else
47
- @variable (model, x[edge_list] >= 0 , Int) # requires MIP solver
49
+ @variable (model, x[edge_list] >= 0 , Int) # requires MIP solver
48
50
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))
50
52
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
+ )
52
58
optimize! (model)
53
59
status = JuMP. termination_status (model)
54
60
status != MOI. OPTIMAL && error (" JuMP solver failed to find optimal solution." )
@@ -58,24 +64,28 @@ function maximum_weight_matching(g::Graph,
58
64
end
59
65
60
66
""" 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
67
78
end
68
- end
69
- return mate
79
+ return mate
70
80
end
71
81
72
82
73
83
function 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
79
89
end
80
90
81
91
"""
@@ -91,35 +101,37 @@ to find the maximum weight matching (see https://homepages.cwi.nl/~schaefer/ftp/
91
101
92
102
Return an array of edges contained in the matching.
93
103
"""
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
121
134
end
122
- end
123
-
124
- return result
135
+
136
+ return result
125
137
end
0 commit comments