graph_matching 0.1.0 → 0.1.1
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/CHANGELOG.md +6 -0
- data/graph_matching.gemspec +13 -11
- data/lib/graph_matching/version.rb +1 -1
- metadata +2 -77
- data/benchmark/mcm_bipartite/complete_bigraphs/benchmark.rb +0 -33
- data/benchmark/mcm_bipartite/complete_bigraphs/compare.gnuplot +0 -19
- data/benchmark/mcm_bipartite/complete_bigraphs/edges_times_vertexes.data +0 -500
- data/benchmark/mcm_bipartite/complete_bigraphs/plot.gnuplot +0 -21
- data/benchmark/mcm_bipartite/complete_bigraphs/plot.png +0 -0
- data/benchmark/mcm_bipartite/complete_bigraphs/time.data +0 -499
- data/benchmark/mcm_general/complete_graphs/benchmark.rb +0 -30
- data/benchmark/mcm_general/complete_graphs/plot.gnuplot +0 -19
- data/benchmark/mcm_general/complete_graphs/plot.png +0 -0
- data/benchmark/mcm_general/complete_graphs/time.data +0 -499
- data/benchmark/mcm_general/complete_graphs/v_cubed.data +0 -500
- data/benchmark/mwm_bipartite/complete_bigraphs/benchmark.rb +0 -43
- data/benchmark/mwm_bipartite/complete_bigraphs/nmN.data +0 -499
- data/benchmark/mwm_bipartite/complete_bigraphs/nmN.xlsx +0 -0
- data/benchmark/mwm_bipartite/complete_bigraphs/plot.gnuplot +0 -22
- data/benchmark/mwm_bipartite/complete_bigraphs/plot.png +0 -0
- data/benchmark/mwm_bipartite/complete_bigraphs/time.data +0 -299
- data/benchmark/mwm_bipartite/misc/calc_d2/benchmark.rb +0 -25
- data/benchmark/mwm_general/complete_graphs/benchmark.rb +0 -32
- data/benchmark/mwm_general/complete_graphs/compare.gnuplot +0 -19
- data/benchmark/mwm_general/complete_graphs/mn_log_n.data +0 -299
- data/benchmark/mwm_general/complete_graphs/mn_log_n.xlsx +0 -0
- data/benchmark/mwm_general/complete_graphs/plot.gnuplot +0 -22
- data/benchmark/mwm_general/complete_graphs/plot.png +0 -0
- data/benchmark/mwm_general/complete_graphs/time.data +0 -299
- data/benchmark/mwm_general/incomplete_graphs/benchmark.rb +0 -38
- data/benchmark/mwm_general/incomplete_graphs/plot.gnuplot +0 -22
- data/benchmark/mwm_general/incomplete_graphs/plot.png +0 -0
- data/benchmark/mwm_general/incomplete_graphs/time_10_pct.data +0 -299
- data/benchmark/mwm_general/incomplete_graphs/time_20_pct.data +0 -299
- data/benchmark/mwm_general/incomplete_graphs/time_30_pct.data +0 -299
- data/profile/mcm_bipartite/compare.sh +0 -15
- data/profile/mcm_bipartite/publish.sh +0 -12
- data/profile/mwm_general/compare.sh +0 -15
- data/profile/mwm_general/profile.rb +0 -28
- data/profile/mwm_general/publish.sh +0 -12
- data/research/1965_edmonds.pdf +0 -0
- data/research/1975_even_kariv.pdf +0 -0
- data/research/1976_gabow.pdf +0 -0
- data/research/1980_micali_vazirani.pdf +0 -0
- data/research/1985_gabow.pdf +0 -0
- data/research/2002_tarjan.pdf +0 -0
- data/research/2013_zwick.pdf +0 -0
- data/research/examples/unweighted_general/1.txt +0 -86
- data/research/goodwin.pdf +0 -0
- data/research/kavathekar-scribe.pdf +0 -0
- data/research/kusner.pdf +0 -0
- data/research/van_rantwijk/mwm_example.py +0 -19
- data/research/van_rantwijk/mwmatching.py +0 -945
- data/spec/graph_matching/algorithm/matching_algorithm_spec.rb +0 -14
- data/spec/graph_matching/algorithm/mcm_bipartite_spec.rb +0 -98
- data/spec/graph_matching/algorithm/mcm_general_spec.rb +0 -159
- data/spec/graph_matching/algorithm/mwm_bipartite_spec.rb +0 -82
- data/spec/graph_matching/algorithm/mwm_general_spec.rb +0 -442
- data/spec/graph_matching/graph/bigraph_spec.rb +0 -73
- data/spec/graph_matching/graph/graph_spec.rb +0 -53
- data/spec/graph_matching/graph/weighted_spec.rb +0 -29
- data/spec/graph_matching/integer_vertexes_spec.rb +0 -21
- data/spec/graph_matching/matching_spec.rb +0 -89
- data/spec/graph_matching/visualize_spec.rb +0 -38
- data/spec/graph_matching_spec.rb +0 -9
- data/spec/spec_helper.rb +0 -26
@@ -1,73 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe GraphMatching::Graph::Bigraph do
|
6
|
-
let(:g) { described_class.new }
|
7
|
-
|
8
|
-
it 'is a Graph' do
|
9
|
-
expect(g).to be_a(GraphMatching::Graph::Graph)
|
10
|
-
end
|
11
|
-
|
12
|
-
describe '#partition' do
|
13
|
-
context 'empty graph' do
|
14
|
-
it 'returns two empty sets' do
|
15
|
-
p = g.partition
|
16
|
-
expect(p.length).to eq(2)
|
17
|
-
p.each do |set|
|
18
|
-
expect(set).to be_a(Set)
|
19
|
-
expect(set).to be_empty
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'graph with single vertex v' do
|
25
|
-
it 'returns two sets, one with v' do
|
26
|
-
v = 0
|
27
|
-
g.add_vertex(v)
|
28
|
-
p = g.partition
|
29
|
-
expect(p[0]).to eq(Set[v])
|
30
|
-
expect(p[1]).to eq(Set[])
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context 'graph with single edge' do
|
35
|
-
it 'returns two disjoint sets, each with one vertex' do
|
36
|
-
e = [0, 1]
|
37
|
-
g.add_edge(*e)
|
38
|
-
p = g.partition
|
39
|
-
expect(p.map(&:first)).to match_array(e)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
context 'complete graph with three vertexes' do
|
44
|
-
it 'raises a NotBipartite error' do
|
45
|
-
g.add_edge('alice', 'bob')
|
46
|
-
g.add_edge('bob', 'carol')
|
47
|
-
g.add_edge('alice', 'carol')
|
48
|
-
expect { g.partition }.to \
|
49
|
-
raise_error(GraphMatching::NotBipartite)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'non-trivial bipartite graph' do
|
54
|
-
it 'returns the expected disjoint sets' do
|
55
|
-
g.add_edge(1, 3)
|
56
|
-
g.add_edge(1, 4)
|
57
|
-
g.add_edge(2, 3)
|
58
|
-
g.add_edge(2, 4)
|
59
|
-
p = g.partition.map(&:sort).sort_by(&:first)
|
60
|
-
expect(p).to match_array([[1, 2], [3, 4]])
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
context 'disconnected, yet bipartite graph' do
|
65
|
-
it 'returns one of the the expected disjoint sets' do
|
66
|
-
g = described_class[1, 3, 2, 4]
|
67
|
-
p = g.partition.map(&:sort).sort_by(&:first)
|
68
|
-
permutations = [[[1, 2], [3, 4]], [[1, 4], [2, 3]]]
|
69
|
-
expect(permutations).to include(p)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe GraphMatching::Graph::Graph do
|
6
|
-
ERR_MSG_INT_VERTEXES = 'All vertexes must be integers'.freeze
|
7
|
-
|
8
|
-
let(:g) { described_class.new }
|
9
|
-
|
10
|
-
it 'is an RGL::MutableGraph' do
|
11
|
-
expect(g).to be_a(RGL::MutableGraph)
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '.[]' do
|
15
|
-
it 'checks that all vertexes are integers' do
|
16
|
-
expect { described_class['a', 'b'] }.to \
|
17
|
-
raise_error(ArgumentError, ERR_MSG_INT_VERTEXES)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe '.new' do
|
22
|
-
it 'checks that all vertexes are integers' do
|
23
|
-
g1 = RGL::AdjacencyGraph[1, 'b']
|
24
|
-
g2 = RGL::AdjacencyGraph['a', 2]
|
25
|
-
expect { described_class.new(Set, g1, g2) }.to \
|
26
|
-
raise_error(ArgumentError, ERR_MSG_INT_VERTEXES)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe '#connected?' do
|
31
|
-
it 'returns true for a connected graph' do
|
32
|
-
g.add_edge('alice', 'bob')
|
33
|
-
expect(g).to be_connected
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'returns false for a disconnected graph' do
|
37
|
-
g.add_edge('alice', 'bob')
|
38
|
-
g.add_edge('yvette', 'zach')
|
39
|
-
expect(g).to_not be_connected
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe '#max_v' do
|
44
|
-
it 'returns the largest vertex number' do
|
45
|
-
g = described_class[1, 3, 3, 7]
|
46
|
-
expect(g.max_v).to eq(7)
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'returns nil when graph is empty' do
|
50
|
-
expect(g.max_v).to eq(nil)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe GraphMatching::Graph::Weighted do
|
6
|
-
# no-doc
|
7
|
-
class MyGraph < RGL::AdjacencyGraph
|
8
|
-
include GraphMatching::Graph::Weighted
|
9
|
-
end
|
10
|
-
|
11
|
-
describe '.[]' do
|
12
|
-
it 'sets weights' do
|
13
|
-
g = MyGraph[[1, 2, 100], [1, 3, 101]]
|
14
|
-
expect(g.w([1, 2])).to eq(100)
|
15
|
-
expect(g.w([1, 3])).to eq(101)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe '#set_w' do
|
20
|
-
let(:g) { MyGraph[[1, 2, 100]] }
|
21
|
-
let(:edge) { [1, 2] }
|
22
|
-
|
23
|
-
it 'records the assigned weight' do
|
24
|
-
weight = 7
|
25
|
-
g.set_w(edge, weight)
|
26
|
-
expect(g.w(edge)).to eq(weight)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'rgl/adjacency'
|
4
|
-
require 'spec_helper'
|
5
|
-
require 'graph_matching/integer_vertexes'
|
6
|
-
|
7
|
-
RSpec.describe GraphMatching::IntegerVertexes do
|
8
|
-
describe '.to_integers' do
|
9
|
-
it 'returns new graph with vertexes converted to integers, and a legend' do
|
10
|
-
e = %w(a b)
|
11
|
-
g1 = RGL::AdjacencyGraph[*e]
|
12
|
-
g2, legend = described_class.to_integers(g1)
|
13
|
-
expect(g2.size).to eq(g1.size)
|
14
|
-
expect(g2.vertices).to eq(1.upto(g1.size).to_a)
|
15
|
-
expect(g2.num_edges).to eq(g1.num_edges)
|
16
|
-
legend.keys.map(&:class).uniq.each do |klass|
|
17
|
-
expect(klass).to(be <= ::Integer)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe GraphMatching::Matching do
|
6
|
-
describe '.gabow' do
|
7
|
-
context 'when nil is used as a placeholder' do
|
8
|
-
it 'returns a Matching' do
|
9
|
-
a = [nil, 2, 1, nil, 5, 4]
|
10
|
-
m = described_class.gabow(a)
|
11
|
-
expect(m.edge?([1, 2])).to eq(true)
|
12
|
-
expect(m.edge?([4, 5])).to eq(true)
|
13
|
-
expect(m.vertex?(3)).to eq(false)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
context 'when 0 is used as a placeholder' do
|
18
|
-
it 'returns a Matching' do
|
19
|
-
a = [0, 2, 1]
|
20
|
-
m = described_class.gabow(a)
|
21
|
-
expect(m.edge?([1, 2])).to eq(true)
|
22
|
-
expect(m.vertex?(3)).to eq(false)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe '#delete' do
|
28
|
-
it 'removes edge' do
|
29
|
-
e = [2, 3]
|
30
|
-
m = described_class[e]
|
31
|
-
expect(m.edge?(e)).to eq(true)
|
32
|
-
m.delete(e)
|
33
|
-
expect(m.edge?(e)).to eq(false)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe '#empty?' do
|
38
|
-
context 'when initialized' do
|
39
|
-
it 'returns true' do
|
40
|
-
expect(described_class.new.empty?).to eq(true)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context 'with one or more edges' do
|
45
|
-
it 'returns false' do
|
46
|
-
expect(described_class[[1, 2]].empty?).to eq(false)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe '#edge?' do
|
52
|
-
it 'returns true if edge found' do
|
53
|
-
m = described_class.new
|
54
|
-
expect(m.edge?([1, 2])).to eq(false)
|
55
|
-
m.add([1, 2])
|
56
|
-
expect(m.edge?([1, 2])).to eq(true)
|
57
|
-
m.add([4, 3])
|
58
|
-
expect(m.edge?([3, 4])).to eq(true)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe '#vertex?' do
|
63
|
-
it 'returns true if vertex found' do
|
64
|
-
m = described_class.new
|
65
|
-
expect(m.vertex?(1)).to eq(false)
|
66
|
-
expect(m.vertex?(2)).to eq(false)
|
67
|
-
m.add([1, 2])
|
68
|
-
expect(m.vertex?(1)).to eq(true)
|
69
|
-
expect(m.vertex?(2)).to eq(true)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe '#to_a' do
|
74
|
-
it 'returns edges' do
|
75
|
-
edges = [[1, 2], [3, 4]]
|
76
|
-
m = described_class[*edges]
|
77
|
-
expect(m.to_a).to eq(edges)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
describe '#vertexes' do
|
82
|
-
it 'returns array of matched vertexes' do
|
83
|
-
expect(described_class.new.vertexes).to be_empty
|
84
|
-
expect(described_class[[3, 4]].vertexes).to match_array([3, 4])
|
85
|
-
expect(described_class[[1, 2], [3, 4]].vertexes).to \
|
86
|
-
match_array([1, 2, 3, 4])
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require_relative '../spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe GraphMatching::Visualize do
|
6
|
-
describe '.new' do
|
7
|
-
it 'initializes with a graph' do
|
8
|
-
g = double
|
9
|
-
v = described_class.new(g)
|
10
|
-
expect(v.graph).to eq(g)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '#dot' do
|
15
|
-
let(:g) { GraphMatching::Graph::Graph.new }
|
16
|
-
|
17
|
-
def normalize_ws(str)
|
18
|
-
str.gsub(/\s+/, ' ').strip
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'given a graph with a single edge' do
|
22
|
-
it 'returns a string in .dot format' do
|
23
|
-
g.add_edge('alice', 'bob')
|
24
|
-
str = described_class.new(g).dot
|
25
|
-
expect(normalize_ws(str)).to eq('graph { alice -- bob }')
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
context 'given a graph with two edges' do
|
30
|
-
it 'returns a string in .dot format' do
|
31
|
-
g.add_edge('alice', 'bob')
|
32
|
-
g.add_edge('tom', 'jerry')
|
33
|
-
str = described_class.new(g).dot
|
34
|
-
expect(normalize_ws(str)).to eq('graph { alice -- bob tom -- jerry }')
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/spec/graph_matching_spec.rb
DELETED
data/spec/spec_helper.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
4
|
-
require 'graph_matching'
|
5
|
-
require 'pry'
|
6
|
-
|
7
|
-
RSpec.configure do |config|
|
8
|
-
config.disable_monkey_patching!
|
9
|
-
config.filter_run_including(focus: true)
|
10
|
-
config.run_all_when_everything_filtered = true
|
11
|
-
end
|
12
|
-
|
13
|
-
RSpec::Matchers.define(:match_edges) do |expected|
|
14
|
-
match do |matching|
|
15
|
-
raise TypeError unless matching.is_a?(GraphMatching::Matching)
|
16
|
-
raise TypeError unless expected.is_a?(Array)
|
17
|
-
se = Set.new(expected.map { |e| RGL::Edge::UnDirectedEdge.new(*e) })
|
18
|
-
sa = Set.new(matching.undirected_edges)
|
19
|
-
se == sa
|
20
|
-
end
|
21
|
-
|
22
|
-
failure_message do |matching|
|
23
|
-
edges_desc = to_sentence(expected)
|
24
|
-
"expected #{matching.edges} to equal" + edges_desc
|
25
|
-
end
|
26
|
-
end
|