art-decomp 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/ad-validate +5 -1
- data/lib/art-decomp/blanket.rb +3 -9
- data/lib/art-decomp/graph.rb +35 -25
- data/lib/core/enumerable.rb +0 -17
- data/spec/core/enumerable_spec.rb +0 -6
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/bin/ad-validate
CHANGED
@@ -6,4 +6,8 @@ require 'backports/1.9' if RUBY_VERSION < '1.9'
|
|
6
6
|
require_relative '../lib/art-decomp'
|
7
7
|
|
8
8
|
$stdout.sync = true
|
9
|
-
|
9
|
+
|
10
|
+
ARGV.each do |file|
|
11
|
+
print file
|
12
|
+
puts Marshal.load(File.open file).all? { |d| print '.'; d.valid? }
|
13
|
+
end
|
data/lib/art-decomp/blanket.rb
CHANGED
@@ -64,15 +64,9 @@ module ArtDecomp class Blanket
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def seps
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
@ints.pairs.each { |int1, int2| singles |= int1 ^ int2 }
|
71
|
-
singles.bits.pairs.each do |elem1, elem2|
|
72
|
-
sep = Sep[elem1, elem2]
|
73
|
-
seps << sep unless @ints.any? { |int| int & sep == sep }
|
74
|
-
end
|
75
|
-
seps
|
67
|
+
potential = @ints.inject(0, :|).bits.pairs.map { |a, b| Sep[a,b] }
|
68
|
+
not_separate = @ints.map{ |i| i.bits.pairs.map { |a, b| Sep[a,b] } }.flatten
|
69
|
+
(potential - not_separate).to_set
|
76
70
|
end
|
77
71
|
|
78
72
|
def size
|
data/lib/art-decomp/graph.rb
CHANGED
@@ -1,24 +1,25 @@
|
|
1
1
|
module ArtDecomp class Graph
|
2
2
|
|
3
|
-
attr_reader :edges, :vertices
|
4
|
-
|
5
3
|
def initialize blanket, seps
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
vertices = blanket.ints.dup
|
5
|
+
vertices.delete_if { |this| vertices.any? { |other| other != this and other & this == this } }
|
6
|
+
@edges = Hash[vertices.map { |vertex| [vertex, Set[]] }]
|
7
|
+
relevant = Hash[vertices.map { |v| [v, seps.select { |s| v&s != 0 and v&s != s }.to_set] }]
|
8
|
+
vertices.pairs.each do |a, b|
|
9
|
+
if (relevant[a] & relevant[b]).any? { |s| a&s != b&s }
|
10
|
+
@edges[a] << b
|
11
|
+
@edges[b] << a
|
12
|
+
end
|
13
|
+
end
|
12
14
|
end
|
13
15
|
|
14
16
|
def adjacent *vertices
|
15
|
-
|
16
|
-
@edges.reject { |edge| (edge & vertices).empty? }.inject(:|) - vertices
|
17
|
+
vertices.map { |vertex| @edges[vertex] }.inject(:|) - vertices
|
17
18
|
end
|
18
19
|
|
19
20
|
def blanket_from_colouring
|
20
21
|
colours = {}
|
21
|
-
@
|
22
|
+
@edges.keys.sort_by { |vert| [-degree(vert), vert] }.each do |vertex|
|
22
23
|
forbidden = adjacent(vertex).map { |vert| colours[vert] }.to_set
|
23
24
|
# FIXME: consider selecting colours on the least-popular-first basis
|
24
25
|
colour = :a
|
@@ -31,28 +32,32 @@ module ArtDecomp class Graph
|
|
31
32
|
end
|
32
33
|
|
33
34
|
def complete?
|
34
|
-
|
35
|
+
@edges.values.map(&:size).inject(:+) == @edges.size * (@edges.size - 1)
|
35
36
|
end
|
36
37
|
|
37
38
|
def degree vertex
|
38
|
-
@edges.
|
39
|
+
@edges[vertex].size
|
40
|
+
end
|
41
|
+
|
42
|
+
def edges
|
43
|
+
@edges.map { |v, adjacents| adjacents.map { |adj| Set[v, adj] } }.flatten.to_set
|
39
44
|
end
|
40
45
|
|
41
46
|
def merge_by_edge_labels!
|
42
|
-
return self if @
|
43
|
-
pins = @
|
44
|
-
until @
|
47
|
+
return self if @edges.size == 1
|
48
|
+
pins = @edges.size.log2_ceil
|
49
|
+
until @edges.size.log2_ceil < pins
|
45
50
|
# FIXME: edge labels can/should be cached from previous computations
|
46
|
-
a, b =
|
51
|
+
a, b = *edges.sort_by { |edge| yield *edge }.first
|
47
52
|
merge! a, b
|
48
53
|
end
|
49
54
|
self
|
50
55
|
end
|
51
56
|
|
52
57
|
def merge_by_vertex_degrees!
|
53
|
-
pins = @
|
54
|
-
until @
|
55
|
-
a, b = *@
|
58
|
+
pins = @edges.size.log2_ceil
|
59
|
+
until @edges.size.log2_ceil < pins or complete?
|
60
|
+
a, b = *@edges.keys.sort_by { |v| -degree(v) }.pairs.find { |v1, v2| not @edges[v1].include? v2 }
|
56
61
|
merge! a, b
|
57
62
|
end
|
58
63
|
self
|
@@ -63,14 +68,19 @@ module ArtDecomp class Graph
|
|
63
68
|
self
|
64
69
|
end
|
65
70
|
|
71
|
+
def vertices
|
72
|
+
@edges.keys.to_set
|
73
|
+
end
|
74
|
+
|
66
75
|
private
|
67
76
|
|
68
77
|
def merge! a, b
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
@edges
|
73
|
-
@edges.
|
78
|
+
new = a | b
|
79
|
+
adjs = adjacent(a) | adjacent(b)
|
80
|
+
adjs.each { |adj| @edges[adj] << new }
|
81
|
+
@edges[new] = adjs
|
82
|
+
@edges.delete(a).each { |adj| @edges[adj].delete a } unless a == new
|
83
|
+
@edges.delete(b).each { |adj| @edges[adj].delete b } unless b == new
|
74
84
|
end
|
75
85
|
|
76
86
|
end end
|
data/lib/core/enumerable.rb
CHANGED
@@ -1,22 +1,5 @@
|
|
1
1
|
module Enumerable
|
2
2
|
|
3
|
-
def self.all_combinations source
|
4
|
-
result_count = source.map(&:size).inject :*
|
5
|
-
group_count = 1
|
6
|
-
result = []
|
7
|
-
source.each do |elems|
|
8
|
-
row = []
|
9
|
-
group_count.times do
|
10
|
-
elems.each do |elem|
|
11
|
-
(result_count / group_count / elems.size).times { row << elem }
|
12
|
-
end
|
13
|
-
end
|
14
|
-
group_count *= elems.size
|
15
|
-
result << row
|
16
|
-
end
|
17
|
-
result.transpose
|
18
|
-
end
|
19
|
-
|
20
3
|
def pairs
|
21
4
|
respond_to?(:combination) ? combination(2) : to_a.combination(2)
|
22
5
|
end
|
@@ -11,10 +11,4 @@ describe Enumerable do
|
|
11
11
|
array.pairs
|
12
12
|
end
|
13
13
|
|
14
|
-
it 'should have a method to get all possible combinations of the passed elements' do
|
15
|
-
source = [[:a,:b], [:c], [:d,:e,:f]]
|
16
|
-
Enumerable.all_combinations(source).should == [[:a,:c,:d], [:a,:c,:e], [:a,:c,:f],
|
17
|
-
[:b,:c,:d], [:b,:c,:e], [:b,:c,:f]]
|
18
|
-
end
|
19
|
-
|
20
14
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: art-decomp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Szotkowski
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-10 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|