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],
         |