graph_matching 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +35 -0
- data/.rubocop_todo.yml +29 -256
- data/CHANGELOG.md +8 -2
- data/Rakefile +3 -3
- data/benchmark/mcm_bipartite/complete_bigraphs/benchmark.rb +1 -1
- data/benchmark/mcm_general/complete_graphs/benchmark.rb +1 -1
- data/benchmark/mwm_bipartite/complete_bigraphs/benchmark.rb +1 -1
- data/benchmark/mwm_bipartite/misc/calc_d2/benchmark.rb +1 -5
- data/benchmark/mwm_general/complete_graphs/benchmark.rb +2 -2
- data/benchmark/mwm_general/incomplete_graphs/benchmark.rb +6 -7
- data/graph_matching.gemspec +7 -11
- data/lib/graph_matching/algorithm/mcm_bipartite.rb +9 -8
- data/lib/graph_matching/algorithm/mcm_general.rb +2 -2
- data/lib/graph_matching/algorithm/mwm_bipartite.rb +25 -25
- data/lib/graph_matching/algorithm/mwm_general.rb +121 -117
- data/lib/graph_matching/algorithm/mwmg_delta_assertions.rb +47 -50
- data/lib/graph_matching/assertion.rb +4 -4
- data/lib/graph_matching/core_ext/set.rb +1 -1
- data/lib/graph_matching/graph/bigraph.rb +1 -1
- data/lib/graph_matching/graph/graph.rb +1 -1
- data/lib/graph_matching/graph/weighted.rb +11 -8
- data/lib/graph_matching/integer_vertexes.rb +2 -2
- data/lib/graph_matching/version.rb +1 -1
- data/lib/graph_matching/visualize.rb +5 -5
- data/profile/mwm_general/profile.rb +1 -1
- data/spec/graph_matching/algorithm/mcm_bipartite_spec.rb +1 -1
- data/spec/graph_matching/algorithm/mcm_general_spec.rb +1 -1
- data/spec/graph_matching/algorithm/mwm_bipartite_spec.rb +1 -1
- data/spec/graph_matching/algorithm/mwm_general_spec.rb +44 -41
- data/spec/graph_matching/graph/graph_spec.rb +4 -4
- data/spec/graph_matching/integer_vertexes_spec.rb +2 -2
- data/spec/spec_helper.rb +2 -2
- metadata +17 -17
@@ -19,27 +19,25 @@ module GraphMatching
|
|
19
19
|
# > Check optimized delta2 against a trivial computation.
|
20
20
|
# > (Van Rantwijk, mwmatching.py, line 580)
|
21
21
|
def check_delta2
|
22
|
-
(0
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
option1 = bk.nil? && @best_edge[v].nil?
|
38
|
-
option2 = !@best_edge[v].nil? && bd == slack(@best_edge[v])
|
39
|
-
unless option1 || option2
|
40
|
-
fail "Assertion failed: Free vertex #{v}"
|
22
|
+
(0...@nvertex).each do |v|
|
23
|
+
next unless @label[@in_blossom[v]] == MWMGeneral::LBL_FREE
|
24
|
+
bd = nil
|
25
|
+
bk = nil
|
26
|
+
@neighb_end[v].each do |p|
|
27
|
+
k = p / 2 # Note: floor division
|
28
|
+
w = @endpoint[p]
|
29
|
+
next unless @label[@in_blossom[w]] == MWMGeneral::LBL_S
|
30
|
+
d = slack(k)
|
31
|
+
if bk.nil? || d < bd
|
32
|
+
bk = k
|
33
|
+
bd = d
|
41
34
|
end
|
42
35
|
end
|
36
|
+
option1 = bk.nil? && @best_edge[v].nil?
|
37
|
+
option2 = !@best_edge[v].nil? && bd == slack(@best_edge[v])
|
38
|
+
unless option1 || option2
|
39
|
+
raise "Assertion failed: Free vertex #{v}"
|
40
|
+
end
|
43
41
|
end
|
44
42
|
end
|
45
43
|
|
@@ -50,43 +48,42 @@ module GraphMatching
|
|
50
48
|
bd = nil
|
51
49
|
tbk = nil
|
52
50
|
tbd = nil
|
53
|
-
(0
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
if bk.nil? || d < bd
|
63
|
-
bk = k
|
64
|
-
bd = d
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
unless @best_edge[b].nil?
|
70
|
-
i, j = @edges[@best_edge[b]].to_a
|
71
|
-
unless @in_blossom[i] == b || @in_blossom[j] == b
|
72
|
-
fail 'Assertion failed'
|
73
|
-
end
|
74
|
-
unless @in_blossom[i] != b || @in_blossom[j] != b
|
75
|
-
fail 'Assertion failed'
|
76
|
-
end
|
77
|
-
unless @label[@in_blossom[i]] == MWMGeneral::LBL_S &&
|
78
|
-
@label[@in_blossom[j]] == MWMGeneral::LBL_S
|
79
|
-
fail 'Assertion failed'
|
51
|
+
(0...2 * @nvertex).each do |b|
|
52
|
+
next unless @blossom_parent[b].nil? && @label[b] == MWMGeneral::LBL_S
|
53
|
+
blossom_leaves(b).each do |v|
|
54
|
+
@neighb_end[v].each do |p|
|
55
|
+
k = p / 2 # Note: floor division
|
56
|
+
w = @endpoint[p]
|
57
|
+
unless @in_blossom[w] != b &&
|
58
|
+
@label[@in_blossom[w]] == MWMGeneral::LBL_S
|
59
|
+
next
|
80
60
|
end
|
81
|
-
|
82
|
-
|
83
|
-
|
61
|
+
d = slack(k)
|
62
|
+
if bk.nil? || d < bd
|
63
|
+
bk = k
|
64
|
+
bd = d
|
84
65
|
end
|
85
66
|
end
|
86
67
|
end
|
68
|
+
next if @best_edge[b].nil?
|
69
|
+
i, j = @edges[@best_edge[b]].to_a
|
70
|
+
unless @in_blossom[i] == b || @in_blossom[j] == b
|
71
|
+
raise 'Assertion failed'
|
72
|
+
end
|
73
|
+
unless @in_blossom[i] != b || @in_blossom[j] != b
|
74
|
+
raise 'Assertion failed'
|
75
|
+
end
|
76
|
+
unless @label[@in_blossom[i]] == MWMGeneral::LBL_S &&
|
77
|
+
@label[@in_blossom[j]] == MWMGeneral::LBL_S
|
78
|
+
raise 'Assertion failed'
|
79
|
+
end
|
80
|
+
if tbk.nil? || slack(@best_edge[b]) < tbd
|
81
|
+
tbk = @best_edge[b]
|
82
|
+
tbd = slack(@best_edge[b])
|
83
|
+
end
|
87
84
|
end
|
88
85
|
unless bd == tbd
|
89
|
-
|
86
|
+
raise 'Assertion failed'
|
90
87
|
end
|
91
88
|
end
|
92
89
|
end
|
@@ -14,27 +14,27 @@ module GraphMatching
|
|
14
14
|
|
15
15
|
def eq(other)
|
16
16
|
unless obj == other
|
17
|
-
|
17
|
+
raise "Expected #{other}, got #{obj}"
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
def gte(other)
|
22
22
|
unless obj >= other
|
23
|
-
|
23
|
+
raise "Expected #{obj} to be >= #{other}"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
# rubocop:disable Style/PredicateName
|
28
28
|
def is_a(klass)
|
29
29
|
unless obj.is_a?(klass)
|
30
|
-
|
30
|
+
raise TypeError, "Expected #{klass}, got #{obj.class}"
|
31
31
|
end
|
32
32
|
end
|
33
33
|
# rubocop:enable Style/PredicateName
|
34
34
|
|
35
35
|
def not_nil
|
36
36
|
if obj.nil?
|
37
|
-
|
37
|
+
raise 'Unexpected nil'
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -16,7 +16,7 @@ unless Set.instance_methods.include?(:intersect?)
|
|
16
16
|
# http://www.ruby-doc.org/stdlib-2.2.0/libdoc/set/rdoc/Set.html#method-i-intersect-3F
|
17
17
|
def intersect?(set)
|
18
18
|
unless set.is_a?(Set)
|
19
|
-
|
19
|
+
raise ArgumentError, 'value must be a set'
|
20
20
|
end
|
21
21
|
if size < set.size
|
22
22
|
any? { |o| set.include?(o) }
|
@@ -44,7 +44,9 @@ module GraphMatching
|
|
44
44
|
g = super(*weightless_edges.flatten)
|
45
45
|
g.init_weights
|
46
46
|
args.each do |edge|
|
47
|
-
i
|
47
|
+
i = edge[0] - 1
|
48
|
+
j = edge[1] - 1
|
49
|
+
weight = edge[2]
|
48
50
|
g.weight[i][j] = weight
|
49
51
|
g.weight[j][i] = weight
|
50
52
|
end
|
@@ -56,7 +58,7 @@ module GraphMatching
|
|
56
58
|
# (The first two represent the edge, the third, the weight)
|
57
59
|
def assert_weighted_edges(ary)
|
58
60
|
return if ary.is_a?(Array) && ary.all?(&method(:weighted_edge?))
|
59
|
-
|
61
|
+
raise 'Invalid array of weighted edges'
|
60
62
|
end
|
61
63
|
|
62
64
|
# `weighted_edge?` returns true if `e` is an array whose
|
@@ -83,8 +85,8 @@ module GraphMatching
|
|
83
85
|
# clarity outweighs performance.
|
84
86
|
def w(edge)
|
85
87
|
i, j = edge
|
86
|
-
|
87
|
-
|
88
|
+
raise ArgumentError, "Invalid edge: #{edge}" if i.nil? || j.nil?
|
89
|
+
raise "Edge not found: #{edge}" unless has_edge?(*edge)
|
88
90
|
init_weights if @weight.nil?
|
89
91
|
@weight[i - 1][j - 1]
|
90
92
|
end
|
@@ -94,14 +96,15 @@ module GraphMatching
|
|
94
96
|
# graph with `.[]` is not convenient.
|
95
97
|
def set_w(edge, weight)
|
96
98
|
if edge[0].nil? || edge[1].nil?
|
97
|
-
|
99
|
+
raise ArgumentError, "Invalid edge: #{edge}"
|
98
100
|
end
|
99
101
|
unless weight.is_a?(Integer)
|
100
|
-
|
102
|
+
raise TypeError, 'Edge weight must be integer'
|
101
103
|
end
|
102
104
|
init_weights if @weight.nil?
|
103
|
-
i
|
104
|
-
|
105
|
+
i = edge[0] - 1
|
106
|
+
j = edge[1] - 1
|
107
|
+
raise "Edge not found: #{edge}" unless has_edge?(*edge)
|
105
108
|
@weight[i] ||= []
|
106
109
|
@weight[j] ||= []
|
107
110
|
@weight[i][j] = weight
|
@@ -10,7 +10,7 @@ module GraphMatching
|
|
10
10
|
# original vertexes.
|
11
11
|
#
|
12
12
|
def self.to_integers(graph)
|
13
|
-
|
13
|
+
raise ArgumentError unless graph.is_a?(RGL::MutableGraph)
|
14
14
|
legend = {}
|
15
15
|
reverse_legend = {}
|
16
16
|
new_graph = graph.class.new
|
@@ -23,7 +23,7 @@ module GraphMatching
|
|
23
23
|
target = reverse_legend[edge.target]
|
24
24
|
new_graph.add_edge(source, target)
|
25
25
|
end
|
26
|
-
|
26
|
+
[new_graph, legend]
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -6,8 +6,8 @@ require 'rgl/rdot'
|
|
6
6
|
module GraphMatching
|
7
7
|
# Renders `GraphMatching::Graph` objects using `graphviz`.
|
8
8
|
class Visualize
|
9
|
-
TMP_DIR = '/tmp/graph_matching'
|
10
|
-
USR_BIN_ENV = '/usr/bin/env'
|
9
|
+
TMP_DIR = '/tmp/graph_matching'.freeze
|
10
|
+
USR_BIN_ENV = '/usr/bin/env'.freeze
|
11
11
|
|
12
12
|
attr_reader :graph
|
13
13
|
|
@@ -34,8 +34,8 @@ module GraphMatching
|
|
34
34
|
|
35
35
|
def check_that_dot_is_installed
|
36
36
|
return if dot_installed?
|
37
|
-
$stderr.puts
|
38
|
-
$stderr.puts
|
37
|
+
$stderr.puts 'Executable not found: dot'
|
38
|
+
$stderr.puts 'Please install graphviz'
|
39
39
|
exit(1)
|
40
40
|
end
|
41
41
|
|
@@ -85,7 +85,7 @@ module GraphMatching
|
|
85
85
|
def write_png(abs_path)
|
86
86
|
_so, se, st = Open3.capture3("dot -T png > #{abs_path}", stdin_data: dot)
|
87
87
|
return if st.success?
|
88
|
-
$stderr.puts
|
88
|
+
$stderr.puts 'Failed to generate .png'
|
89
89
|
$stderr.puts se
|
90
90
|
exit(1)
|
91
91
|
end
|
@@ -7,7 +7,7 @@ RSpec.describe GraphMatching::Algorithm::MCMBipartite do
|
|
7
7
|
|
8
8
|
describe '.new' do
|
9
9
|
it 'requires a Bigraph' do
|
10
|
-
expect { described_class.new(
|
10
|
+
expect { described_class.new('banana') }.to raise_error(TypeError)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -7,7 +7,7 @@ RSpec.describe GraphMatching::Algorithm::MWMBipartite do
|
|
7
7
|
|
8
8
|
describe '.new' do
|
9
9
|
it 'requires a WeightedBigraph' do
|
10
|
-
expect { described_class.new(
|
10
|
+
expect { described_class.new('banana') }.to raise_error(TypeError)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -7,7 +7,7 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
7
7
|
|
8
8
|
describe '.new' do
|
9
9
|
it 'requires a WeightedGraph' do
|
10
|
-
expect { described_class.new(
|
10
|
+
expect { described_class.new('banana') }.to raise_error(TypeError)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -22,14 +22,17 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
22
22
|
[3, 4, 0]
|
23
23
|
]
|
24
24
|
a = described_class.new(g)
|
25
|
-
a.instance_variable_set(
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
a.instance_variable_set(
|
26
|
+
:@blossom_children,
|
27
|
+
[
|
28
|
+
nil,
|
29
|
+
nil,
|
30
|
+
nil,
|
31
|
+
nil,
|
32
|
+
nil,
|
33
|
+
[2, 3, 4]
|
34
|
+
]
|
35
|
+
)
|
33
36
|
expect(a.send(:blossom_leaves, 0)).to eq([0])
|
34
37
|
expect(a.send(:blossom_leaves, 4)).to eq([4])
|
35
38
|
expect(a.send(:blossom_leaves, 5)).to eq([2, 3, 4])
|
@@ -104,14 +107,14 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
104
107
|
end
|
105
108
|
end
|
106
109
|
|
107
|
-
it
|
110
|
+
it 'passes Van Rantwijk test 12' do
|
108
111
|
g = graph_class[[1, 2, 10], [2, 3, 11]]
|
109
112
|
m = described_class.new(g).match(false)
|
110
113
|
expect(m).to match_edges [[2, 3]]
|
111
114
|
expect(m.weight(g)).to eq(11)
|
112
115
|
end
|
113
116
|
|
114
|
-
it
|
117
|
+
it 'passes Van Rantwijk test 13' do
|
115
118
|
g = graph_class[
|
116
119
|
[1, 2, 5],
|
117
120
|
[2, 3, 11],
|
@@ -122,7 +125,7 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
122
125
|
expect(m.weight(g)).to eq(11)
|
123
126
|
end
|
124
127
|
|
125
|
-
it
|
128
|
+
it 'passes Van Rantwijk test 14: max. cardinality' do
|
126
129
|
g = graph_class[
|
127
130
|
[1, 2, 5],
|
128
131
|
[2, 3, 11],
|
@@ -133,7 +136,7 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
133
136
|
expect(m.weight(g)).to eq(10)
|
134
137
|
end
|
135
138
|
|
136
|
-
it
|
139
|
+
it 'passes Van Rantwijk test 15: floating-point weights' do
|
137
140
|
g = graph_class[
|
138
141
|
[1, 2, Math::PI],
|
139
142
|
[2, 3, Math.exp(1)],
|
@@ -145,7 +148,7 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
145
148
|
expect(m.weight(g)).to be_within(0.00001).of(Math.sqrt(2.0) + Math.exp(1))
|
146
149
|
end
|
147
150
|
|
148
|
-
it
|
151
|
+
it 'passes Van Rantwijk test 16: negative weights' do
|
149
152
|
g = graph_class[
|
150
153
|
[1, 2, 2],
|
151
154
|
[1, 3, -2],
|
@@ -161,8 +164,8 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
161
164
|
expect(m.weight(g)).to eq(-3)
|
162
165
|
end
|
163
166
|
|
164
|
-
context
|
165
|
-
it
|
167
|
+
context 'Van Rantwijk test 20: Uses S-blossom for augmentation' do
|
168
|
+
it 'passes test 20-A' do
|
166
169
|
g = graph_class[
|
167
170
|
[1, 2, 8],
|
168
171
|
[1, 3, 9],
|
@@ -174,7 +177,7 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
174
177
|
expect(m.weight(g)).to eq(15)
|
175
178
|
end
|
176
179
|
|
177
|
-
it
|
180
|
+
it 'passes test 20-B' do
|
178
181
|
g = graph_class[
|
179
182
|
[1, 2, 8],
|
180
183
|
[1, 3, 9],
|
@@ -190,8 +193,8 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
190
193
|
end
|
191
194
|
|
192
195
|
# Van Rantwijk test 21
|
193
|
-
context
|
194
|
-
it
|
196
|
+
context 'create S-blossom, relabel as T-blossom, use for augmentation' do
|
197
|
+
it 'passes test 21-A' do
|
195
198
|
g = graph_class[
|
196
199
|
[1, 2, 9],
|
197
200
|
[1, 3, 8],
|
@@ -204,7 +207,7 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
204
207
|
expect(m).to match_edges [[1, 6], [2, 3], [4, 5]]
|
205
208
|
end
|
206
209
|
|
207
|
-
it
|
210
|
+
it 'passes test 21-B' do
|
208
211
|
g = graph_class[
|
209
212
|
[1, 2, 9],
|
210
213
|
[1, 3, 8],
|
@@ -217,7 +220,7 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
217
220
|
expect(m).to match_edges [[1, 6], [2, 3], [4, 5]]
|
218
221
|
end
|
219
222
|
|
220
|
-
it
|
223
|
+
it 'passes test 21-C' do
|
221
224
|
g = graph_class[
|
222
225
|
[1, 2, 9],
|
223
226
|
[1, 3, 8],
|
@@ -231,8 +234,8 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
231
234
|
end
|
232
235
|
end
|
233
236
|
|
234
|
-
context
|
235
|
-
it
|
237
|
+
context 'Van Rantwijk test 22' do
|
238
|
+
it 'creates nested S-blossom, uses for augmentation' do
|
236
239
|
g = graph_class[
|
237
240
|
[1, 2, 9],
|
238
241
|
[1, 3, 9],
|
@@ -247,8 +250,8 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
247
250
|
end
|
248
251
|
end
|
249
252
|
|
250
|
-
context
|
251
|
-
it
|
253
|
+
context 'Van Rantwijk test 23' do
|
254
|
+
it 'create S-blossom, relabel as S, include in nested S-blossom' do
|
252
255
|
g = graph_class[
|
253
256
|
[1, 2, 10],
|
254
257
|
[1, 7, 10],
|
@@ -265,8 +268,8 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
265
268
|
end
|
266
269
|
end
|
267
270
|
|
268
|
-
context
|
269
|
-
it
|
271
|
+
context 'Van Rantwijk test 24' do
|
272
|
+
it 'create nested S-blossom, augment, expand recursively' do
|
270
273
|
g = graph_class[
|
271
274
|
[1, 2, 8],
|
272
275
|
[1, 3, 8],
|
@@ -284,8 +287,8 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
284
287
|
end
|
285
288
|
end
|
286
289
|
|
287
|
-
context
|
288
|
-
it
|
290
|
+
context 'Van Rantwijk test 25' do
|
291
|
+
it 'create S-blossom, relabel as T, expand' do
|
289
292
|
g = graph_class[
|
290
293
|
[1, 2, 23],
|
291
294
|
[1, 5, 22],
|
@@ -301,8 +304,8 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
301
304
|
end
|
302
305
|
end
|
303
306
|
|
304
|
-
context
|
305
|
-
it
|
307
|
+
context 'Van Rantwijk test 26' do
|
308
|
+
it 'create nested S-blossom, relabel as T, expand' do
|
306
309
|
g = graph_class[
|
307
310
|
[1, 2, 19],
|
308
311
|
[1, 3, 20],
|
@@ -319,8 +322,8 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
319
322
|
end
|
320
323
|
end
|
321
324
|
|
322
|
-
context
|
323
|
-
it
|
325
|
+
context 'Van Rantwijk test 30' do
|
326
|
+
it 'create blossom, relabel as T in more than one way, expand, augment' do
|
324
327
|
g = graph_class[
|
325
328
|
[1, 2, 45],
|
326
329
|
[1, 5, 45],
|
@@ -338,8 +341,8 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
338
341
|
end
|
339
342
|
end
|
340
343
|
|
341
|
-
context
|
342
|
-
it
|
344
|
+
context 'Van Rantwijk test 31' do
|
345
|
+
it 'similar to test 30, but slightly different' do
|
343
346
|
g = graph_class[
|
344
347
|
[1, 2, 45],
|
345
348
|
[1, 5, 45],
|
@@ -357,10 +360,10 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
357
360
|
end
|
358
361
|
end
|
359
362
|
|
360
|
-
context
|
363
|
+
context 'Van Rantwijk test 32' do
|
361
364
|
# create blossom, relabel as T, expand such that a new
|
362
365
|
# least-slack S-to-free edge is produced, augment
|
363
|
-
it
|
366
|
+
it 'see comment' do
|
364
367
|
g = graph_class[
|
365
368
|
[1, 2, 45],
|
366
369
|
[1, 5, 45],
|
@@ -378,11 +381,11 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
378
381
|
end
|
379
382
|
end
|
380
383
|
|
381
|
-
context
|
384
|
+
context 'Van Rantwijk test 33' do
|
382
385
|
# create nested blossom, relabel as T in more than one way,
|
383
386
|
# expand outer blossom such that inner blossom ends up on
|
384
387
|
# an augmenting path
|
385
|
-
it
|
388
|
+
it 'see comment' do
|
386
389
|
g = graph_class[
|
387
390
|
[1, 2, 45],
|
388
391
|
[1, 7, 45],
|
@@ -410,8 +413,8 @@ RSpec.describe GraphMatching::Algorithm::MWMGeneral do
|
|
410
413
|
end
|
411
414
|
end
|
412
415
|
|
413
|
-
context
|
414
|
-
it
|
416
|
+
context 'Van Rantwijk test 34: nest, relabel, expand' do
|
417
|
+
it 'create nested S-blossom, relabel as S, expand recursively' do
|
415
418
|
g = graph_class[
|
416
419
|
[1, 2, 40],
|
417
420
|
[1, 3, 40],
|