art-decomp 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/.gitignore +2 -0
  2. data/LICENCE +661 -0
  3. data/README +9 -0
  4. data/Rakefile +46 -0
  5. data/VERSION +1 -0
  6. data/bin/ad-compare +22 -0
  7. data/bin/ad-console +11 -0
  8. data/bin/ad-inputs +24 -0
  9. data/bin/ad-validate +9 -0
  10. data/bin/art-decomp +8 -0
  11. data/lib/art-decomp/arch.rb +32 -0
  12. data/lib/art-decomp/b.rb +7 -0
  13. data/lib/art-decomp/bipainter.rb +142 -0
  14. data/lib/art-decomp/blanket.rb +82 -0
  15. data/lib/art-decomp/decomposer.rb +75 -0
  16. data/lib/art-decomp/decomposition.rb +91 -0
  17. data/lib/art-decomp/exceptions.rb +9 -0
  18. data/lib/art-decomp/executable.rb +94 -0
  19. data/lib/art-decomp/fsm.rb +128 -0
  20. data/lib/art-decomp/graph.rb +78 -0
  21. data/lib/art-decomp/kiss.rb +47 -0
  22. data/lib/art-decomp/logging.rb +52 -0
  23. data/lib/art-decomp/qu_generator/block_table.rb +42 -0
  24. data/lib/art-decomp/qu_generator/edge_labels.rb +24 -0
  25. data/lib/art-decomp/qv_generator/bipainting.rb +12 -0
  26. data/lib/art-decomp/qv_generator/graph_colouring.rb +16 -0
  27. data/lib/art-decomp/qv_generator/graph_merging.rb +19 -0
  28. data/lib/art-decomp/sep.rb +7 -0
  29. data/lib/art-decomp/uv_generator/braindead.rb +22 -0
  30. data/lib/art-decomp/uv_generator/relevance.rb +23 -0
  31. data/lib/art-decomp.rb +65 -0
  32. data/lib/core/enumerable.rb +24 -0
  33. data/lib/core/file.rb +11 -0
  34. data/lib/core/integer.rb +13 -0
  35. data/lib/core/set.rb +16 -0
  36. data/lib/core/string.rb +13 -0
  37. data/spec/art-decomp/arch_spec.rb +23 -0
  38. data/spec/art-decomp/b_spec.rb +27 -0
  39. data/spec/art-decomp/bipainter_spec.rb +22 -0
  40. data/spec/art-decomp/blanket_spec.rb +77 -0
  41. data/spec/art-decomp/decomposer_spec.rb +106 -0
  42. data/spec/art-decomp/decomposition_spec.rb +119 -0
  43. data/spec/art-decomp/executable_spec.rb +161 -0
  44. data/spec/art-decomp/fsm_spec.rb +146 -0
  45. data/spec/art-decomp/graph_spec.rb +69 -0
  46. data/spec/art-decomp/kiss_spec.rb +30 -0
  47. data/spec/art-decomp/logging_spec.rb +62 -0
  48. data/spec/art-decomp/qu_generator/block_table_spec.rb +37 -0
  49. data/spec/art-decomp/qu_generator/edge_labels_spec.rb +35 -0
  50. data/spec/art-decomp/qv_generator/bipainting_spec.rb +28 -0
  51. data/spec/art-decomp/qv_generator/graph_colouring_spec.rb +31 -0
  52. data/spec/art-decomp/qv_generator/graph_merging_spec.rb +30 -0
  53. data/spec/art-decomp/sep_spec.rb +13 -0
  54. data/spec/art-decomp/uv_generator/braindead_spec.rb +33 -0
  55. data/spec/art-decomp/uv_generator/relevance_spec.rb +61 -0
  56. data/spec/core/enumerable_spec.rb +20 -0
  57. data/spec/core/file_spec.rb +15 -0
  58. data/spec/core/integer_spec.rb +16 -0
  59. data/spec/core/set_spec.rb +26 -0
  60. data/spec/core/string_spec.rb +17 -0
  61. data/spec/fixtures/ex5 +36 -0
  62. data/spec/fixtures/fsm +24 -0
  63. data/spec/fixtures/fsm.exp +40 -0
  64. data/spec/fixtures/fsm.f +20 -0
  65. data/spec/fixtures/fsm.g +4 -0
  66. data/spec/fixtures/fsm.h +19 -0
  67. data/spec/fixtures/fsm.partially-exp +31 -0
  68. data/spec/fixtures/fsm.q +10 -0
  69. data/spec/fixtures/lion +15 -0
  70. data/spec/fixtures/lion.exp +15 -0
  71. data/spec/fixtures/lion.h +10 -0
  72. data/spec/fixtures/lion.to_kiss +11 -0
  73. data/spec/fixtures/mark1 +26 -0
  74. data/spec/fixtures/mc +14 -0
  75. data/spec/fixtures/mc.to_kiss +10 -0
  76. data/spec/fixtures/opus +26 -0
  77. data/spec/fixtures/opus.amb.h +22 -0
  78. data/spec/fixtures/opus.h +21 -0
  79. data/spec/fixtures/opus.to_kiss +22 -0
  80. data/spec/fixtures/s420 +142 -0
  81. data/spec/fixtures/s8 +24 -0
  82. data/spec/spec.opts +3 -0
  83. data/spec/spec_helper.rb +8 -0
  84. metadata +224 -0
@@ -0,0 +1,69 @@
1
+ # encoding: UTF-8
2
+
3
+ module ArtDecomp describe Graph do
4
+
5
+ before do
6
+ blanket = Blanket[B[1,2], B[3,4], B[5,6], B[7], B[8,9]]
7
+ seps = Set[Sep[4,6], Sep[5,9], Sep[5,7], Sep[7,9]]
8
+ @graph = Graph.new blanket, seps
9
+ end
10
+
11
+ it 'should initialise properly from a Blanket and a Set of Seps' do
12
+ @graph.vertices.should == Set[B[1,2], B[3,4], B[5,6], B[7], B[8,9]]
13
+ @graph.edges.should == Set[Set[B[3,4], B[5,6]], Set[B[5,6], B[7]], Set[B[8,9], B[7]], Set[B[5,6], B[8,9]]]
14
+ end
15
+
16
+ it 'should drop vertices covered by other vertices upon initialisation' do
17
+ Graph.new(Blanket[B[1,2], B[2]], Set[]).vertices.should == Set[B[1,2]]
18
+ end
19
+
20
+ it 'should properly compute vertex degrees' do
21
+ degrees = {B[1,2] => 0, B[3,4] => 1, B[5,6] => 3, B[7] => 2, B[8,9] => 2}
22
+ degrees.each { |vert, deg| @graph.degree(vert).should == deg }
23
+ end
24
+
25
+ it 'should return the proper Blanket obtained by colouring the vertices' do
26
+ blanket = @graph.blanket_from_colouring
27
+ blanket.size.should == 3
28
+ blanket.ints.should include(B[1,2,5,6])
29
+ end
30
+
31
+ it 'should report whether it’s complete' do
32
+ complete = Graph.new Blanket[B[1], B[2], B[3]], Set[Sep[1,2], Sep[1,3], Sep[2,3]]
33
+ complete.should be_complete
34
+ @graph.should_not be_complete
35
+ end
36
+
37
+ it 'should properly merge until it’s complete and return self' do
38
+ @graph.merge_until_complete!.should be_a(Graph)
39
+ @graph.vertices.size.should == 3
40
+ @graph.vertices.should include(B[1,2,5,6])
41
+ @graph.should be_complete
42
+ end
43
+
44
+ it 'should properly merge based on edge weights and return self' do
45
+ b1234 = Blanket[B[1], B[2], B[3], B[4]]
46
+ graph = Graph.new b1234, b1234.seps
47
+ graph.merge_by_edge_labels! { |a, b| a | b }.should be_a(Graph)
48
+ graph.vertices.should == Set[B[1,2,3], B[4]]
49
+ graph.merge_by_edge_labels! { |a, b| a | b }.should be_a(Graph)
50
+ graph.vertices.should == Set[B[1,2,3,4]]
51
+ graph.merge_by_edge_labels! { |a, b| a | b }.should be_a(Graph)
52
+ graph.vertices.should == Set[B[1,2,3,4]]
53
+ end
54
+
55
+ it 'should properly merge based on vertex degrees and return self' do
56
+ graph = Graph.new Blanket[B[1], B[2], B[3], B[4], B[5], B[6]], Set[Sep[3,4], Sep[4,5], Sep[4,6], Sep[5,6]]
57
+ graph.merge_by_vertex_degrees!.should be_a(Graph)
58
+ graph.vertices.should == Set[B[1,2,4], B[3], B[5], B[6]]
59
+ graph.merge_by_vertex_degrees!.should be_a(Graph)
60
+ graph.vertices.size.should == 3
61
+ end
62
+
63
+ it 'should report a given vertex’s adjacent vertices' do
64
+ @graph.adjacent(B[3,4]).should == Set[B[5,6]]
65
+ @graph.adjacent(B[1,2]).should == Set[]
66
+ @graph.adjacent(B[5,6], B[7]).should == Set[B[3,4], B[8,9]]
67
+ end
68
+
69
+ end end
@@ -0,0 +1,30 @@
1
+ module ArtDecomp describe KISS do
2
+
3
+ it 'should sort entries' do
4
+ kiss = KISS.new ['1 1', '0 0']
5
+ kiss.formatted.should == "0 0\n1 1\n"
6
+ end
7
+
8
+ it 'should drop non-unique entries' do
9
+ kiss = KISS.new ['0 0', '0 0']
10
+ kiss.formatted.should == "0 0\n"
11
+ end
12
+
13
+ it 'should drop overlapping entries' do
14
+ kiss = KISS.new ['0-0 0', '010 0', '1-1 1', '--1 1']
15
+ kiss.formatted.should == "--1 1\n0-0 0\n"
16
+ end
17
+
18
+ it 'should preserve overlapping entries which differ on subsequent column groups' do
19
+ kiss = KISS.new ['-- 1 0 1', '10 0 0 1']
20
+ kiss.formatted.should == "-- 1 0 1\n10 0 0 1\n"
21
+ end
22
+
23
+ it 'should combine matching entries' do
24
+ kiss = KISS.new ['00 0 1 1', '01 0 1 1', '10 1 0 0', '11 1 0 0']
25
+ kiss.formatted.should == "0- 0 1 1\n1- 1 0 0\n"
26
+ kiss = KISS.new ['00 0', '11 0', '10 0', '01 0']
27
+ kiss.formatted.should == "-- 0\n"
28
+ end
29
+
30
+ end end
@@ -0,0 +1,62 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative '../../lib/art-decomp/logging'
4
+
5
+ module ArtDecomp describe Logging do
6
+
7
+ before do
8
+ @dir = "#{Dir.tmpdir}/#{rand.to_s}"
9
+ @log = StringIO.new
10
+ Logging.log = @log
11
+ end
12
+
13
+ after do
14
+ Logging.off
15
+ FileUtils.rmtree @dir if Dir.exists? @dir
16
+ end
17
+
18
+ def log
19
+ @log.rewind
20
+ @log.read
21
+ end
22
+
23
+ it 'should log Executable’s decompositions calls on simple cases' do
24
+ args = ['-a', '5/1', '4/2', '-o', @dir, 'spec/fixtures/lion']
25
+ Executable.new(args).run
26
+ log.should =~ rex('final best decomposition: 2')
27
+ end
28
+
29
+ it 'should log Executable’s decompositions calls on typical cases' do
30
+ Decomposer.should_receive(:new).and_return mock(Decomposer, :decompositions => [].each)
31
+ args = ['-a', '5/1', '4/2', '-o', @dir, 'spec/fixtures/fsm']
32
+ Executable.new(args).run
33
+ log.should =~ rex('FSM 4/2+10s → 5/1+4/2 () with Relevance, EdgeLabels, GraphColouring – best so far: ')
34
+ log.should =~ rex('final best decomposition: ')
35
+ end
36
+
37
+ it 'should log UVGenerators’ uv_pairs calls' do
38
+ uv = UVGenerator::Braindead.new mock(FSM, :input_count => 2), Set[Arch[5,1]]
39
+ uv.uv_pairs
40
+ log.should =~ rex('UV with Braindead')
41
+ end
42
+
43
+ it 'should log QuGenerators’ blankets calls' do
44
+ qu = QuGenerator::BlockTable.new
45
+ [[Set[0], Set[1]], [Set[1], Set[0]]].each do |u, v|
46
+ qu.blankets mock(FSM), u, v
47
+ end
48
+ log.should =~ rex('U = [0], V = [1], Qu with BlockTable')
49
+ log.should =~ rex('U = [1], V = [0], Qu with BlockTable')
50
+ end
51
+
52
+ it 'should log QvGenerators’ blankets calls (on the DEBUG level)' do
53
+ Logging.level = Logger::DEBUG
54
+ qv = QvGenerator::GraphColouring.new
55
+ [mock(Blanket, :size => 8), mock(Blanket, :size => 4)].each do |qu|
56
+ qv.blankets mock(FSM), Set[0], Set[1], qu
57
+ end
58
+ log.should =~ rex('|Qu| = 8, Qv+G with GraphColouring')
59
+ log.should =~ rex('|Qu| = 4, Qv+G with GraphColouring')
60
+ end
61
+
62
+ end end
@@ -0,0 +1,37 @@
1
+ # encoding: UTF-8
2
+
3
+ module ArtDecomp describe QuGenerator::BlockTable do
4
+
5
+ context 'when generating Qu blankets' do
6
+
7
+ def qus
8
+ fsm = mock FSM, :beta_f => @beta_f, :beta_q => @beta_q, :beta_x => @beta_x
9
+ archs = Set[Arch[3,1]]
10
+ bt = QuGenerator::BlockTable.new
11
+ bt.blankets(fsm, Set[0], Set[1]).to_a
12
+ end
13
+
14
+ it 'should fold Q blocks that match in the first go' do
15
+ @beta_f = Blanket[]
16
+ @beta_q = Blanket[B[1,2], B[2], B[3]]
17
+ @beta_x = Blanket[B[1], B[2], B[3]]
18
+ qus.first.should == Blanket[B[1,2,3], B[2]]
19
+ end
20
+
21
+ it 'shouldn’t fold Q blocks if they don’t match' do
22
+ @beta_f = Blanket[]
23
+ @beta_q = Blanket[B[1,2], B[2,3]]
24
+ @beta_x = Blanket[B[1], B[2], B[3]]
25
+ qus.first.should == Blanket[B[1,2], B[2,3]]
26
+ end
27
+
28
+ it 'should first try to fold matching blocks and then fold by r-admissibility' do
29
+ @beta_f = mock Blanket, :seps => Set[Sep[1,2], Sep[2,3]]
30
+ @beta_q = Blanket[B[1], B[2], B[3]]
31
+ @beta_x = Blanket[B[1,2,3], B[1,3]]
32
+ qus.should == [Blanket[B[1], B[2], B[3]], Blanket[B[1,3], B[2]], Blanket[B[1,2,3]]]
33
+ end
34
+
35
+ end
36
+
37
+ end end
@@ -0,0 +1,35 @@
1
+ module ArtDecomp describe QuGenerator::EdgeLabels do
2
+
3
+ context 'when generating Qu blankets' do
4
+
5
+ def qus
6
+ fsm = mock FSM, :beta_f => @beta_f, :beta_q => @beta_q, :beta_x => @beta_x
7
+ archs = Set[Arch[3,1]]
8
+ el = QuGenerator::EdgeLabels.new
9
+ el.blankets(fsm, Set[0], Set[1]).to_a
10
+ end
11
+
12
+ it 'should fist merge until its graph is complete' do
13
+ @beta_f = mock Blanket, :seps => Set[Sep[1,2], Sep[2,3]]
14
+ @beta_q = Blanket[B[1], B[2], B[3]]
15
+ @beta_x = Blanket[]
16
+ qus.first.should == Blanket[B[1,3], B[2]]
17
+ end
18
+
19
+ it 'should then merge blocks based on r-admissibility of the merged block, all the way down' do
20
+ @beta_f = Blanket[B[1], B[2,3], B[4], B[5], B[6]]
21
+ @beta_q = Blanket[B[1], B[2,3], B[4,5,6]]
22
+ @beta_x = Blanket[]
23
+ qus.should == [Blanket[B[1], B[2,3], B[4,5,6]], Blanket[B[1,2,3], B[4,5,6]], Blanket[B[1,2,3,4,5,6]]]
24
+ end
25
+
26
+ it 'should merge blocks based on the number of separations lost (if the r-admissibility is the same)' do
27
+ @beta_f = Blanket[B[1,2], B[3,4,5], B[6]]
28
+ @beta_q = Blanket[B[1,2], B[3,4,5], B[6]]
29
+ @beta_x = Blanket[]
30
+ qus.should == [Blanket[B[1,2], B[3,4,5], B[6]], Blanket[B[1,2,6], B[3,4,5]], Blanket[B[1,2,3,4,5,6]]]
31
+ end
32
+
33
+ end
34
+
35
+ end end
@@ -0,0 +1,28 @@
1
+ module ArtDecomp describe QvGenerator::Bipainting do
2
+
3
+ context 'when generating G and Qv blankets' do
4
+
5
+ it 'should use graph bicolouring' do
6
+ beta_f = mock Blanket, :seps => Set[Sep[1,2], Sep[1,3], Sep[1,6], Sep[2,6], Sep[3,4], Sep[3,6], Sep[4,5], Sep[5,6]]
7
+ beta_q = Blanket[B[1,2], B[3,4], B[5,6]]
8
+ beta_u = Blanket[]
9
+ beta_v = Blanket[B[1,3,5], B[2,4,6]]
10
+ beta_qu = Blanket[]
11
+
12
+ fsm = mock FSM, :beta_f => beta_f, :beta_q => beta_q
13
+ fsm.should_receive(:beta_x).with(Set[0]).and_return beta_u
14
+ fsm.should_receive(:beta_x).with(Set[1]).and_return beta_v
15
+ archs = Set[Arch[3,1]]
16
+ bi = QvGenerator::Bipainting.new
17
+
18
+ beta_qv, beta_g = bi.blankets(fsm, Set[0], Set[1], beta_qu).to_a.first
19
+ beta_qv.should == Blanket[B[1,2], B[3,4,5,6]]
20
+ beta_g.should == Blanket[B[1], B[2,3,5], B[4,6]]
21
+
22
+ beta_f.seps.should be_subset(beta_u.seps + beta_qu.seps + beta_g.seps)
23
+ beta_g.seps.should be_subset(beta_v.seps + beta_qv.seps)
24
+ end
25
+
26
+ end
27
+
28
+ end end
@@ -0,0 +1,31 @@
1
+ module ArtDecomp describe QvGenerator::GraphColouring do
2
+
3
+ context 'when generating G and Qv blankets' do
4
+
5
+ it 'should use graph colouring of the proper incompatibility graphs' do
6
+ beta_f = mock Blanket, :seps => Set[Sep[1,2], Sep[1,3], Sep[1,6], Sep[2,6], Sep[3,4], Sep[3,6], Sep[4,5], Sep[5,6]]
7
+ beta_q = Blanket[B[1,2], B[3,4], B[5,6]]
8
+ beta_u = Blanket[]
9
+ beta_v = Blanket[B[1,3,5], B[2,4,6]]
10
+ beta_qu = Blanket[]
11
+
12
+ fsm = mock FSM, :beta_f => beta_f, :beta_q => beta_q
13
+ fsm.should_receive(:beta_x).with(Set[0]).and_return beta_u
14
+ fsm.should_receive(:beta_x).with(Set[1]).and_return beta_v
15
+ archs = Set[Arch[3,1]]
16
+ gc = QvGenerator::GraphColouring.new
17
+
18
+ pairs = gc.blankets(fsm, Set[0], Set[1], beta_qu).to_a
19
+ pairs.size.should == 2
20
+ pairs.first.should == [Blanket[B[1,2], B[3,4], B[5,6]], Blanket[B[1,5], B[2,3], B[4,6]]]
21
+ pairs.last.should == [Blanket[B[1,2], B[3,4,5,6]], Blanket[B[1], B[2,3,5], B[4,6]]]
22
+
23
+ pairs.each do |beta_qv, beta_g|
24
+ beta_f.seps.should be_subset(beta_u.seps + beta_qu.seps + beta_g.seps)
25
+ beta_g.seps.should be_subset(beta_v.seps + beta_qv.seps)
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ end end
@@ -0,0 +1,30 @@
1
+ module ArtDecomp describe QvGenerator::GraphMerging do
2
+
3
+ context 'when generating G and Qv blankets' do
4
+
5
+ it 'should merge vertices of the proper incompatibility graphs' do
6
+ beta_f = mock Blanket, :seps => Set[Sep[1,2], Sep[1,3], Sep[1,6], Sep[2,6], Sep[3,4], Sep[3,6], Sep[4,5], Sep[5,6]]
7
+ beta_q = Blanket[B[1,2], B[3,4], B[5,6]]
8
+ beta_u = Blanket[]
9
+ beta_v = Blanket[B[1,3,5], B[2,4,6]]
10
+ beta_qu = Blanket[]
11
+
12
+ fsm = mock FSM, :beta_f => beta_f, :beta_q => beta_q
13
+ fsm.should_receive(:beta_x).with(Set[0]).and_return beta_u
14
+ fsm.should_receive(:beta_x).with(Set[1]).and_return beta_v
15
+ archs = Set[Arch[3,1]]
16
+ gm = QvGenerator::GraphMerging.new
17
+
18
+ pairs = gm.blankets(fsm, Set[0], Set[1], beta_qu).to_a
19
+ pairs.first.should == [Blanket[B[1,2], B[3,4], B[5,6]], Blanket[B[1,5], B[2,3], B[4,6]]]
20
+ pairs.last.should == [Blanket[B[1,2], B[3,4,5,6]], Blanket[B[1], B[2,3,5], B[4,6]]]
21
+
22
+ pairs.each do |beta_qv, beta_g|
23
+ beta_f.seps.should be_subset(beta_u.seps + beta_qu.seps + beta_g.seps)
24
+ beta_g.seps.should be_subset(beta_v.seps + beta_qv.seps)
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end end
@@ -0,0 +1,13 @@
1
+ module ArtDecomp describe Sep do
2
+
3
+ it 'should be an Integer with bits representing the separated values' do
4
+ Sep[1,2].should == 0b110
5
+ Sep[0,69].should == 2**69 + 0b1
6
+ end
7
+
8
+ it 'should be usable as a Set element' do
9
+ Sep[1,2].hash.should == 0b110.hash
10
+ Sep[0,69].hash.should == (2**69 + 0b1).hash
11
+ end
12
+
13
+ end end
@@ -0,0 +1,33 @@
1
+ module ArtDecomp describe UVGenerator::Braindead do
2
+
3
+ context 'given a certain FSM and a Set of Archs' do
4
+
5
+ it 'should yield all non-insane U and V combinations' do
6
+ fsm = mock FSM, :input_count => 4
7
+ fsm.stub!(:expand_x).and_return fsm
8
+ archs = Set[Arch[3,1]]
9
+ uv_gen = UVGenerator::Braindead.new fsm, archs
10
+ uvs = uv_gen.uv_pairs.to_a
11
+ uvs.size.should == 15
12
+ uvs.first.should == [fsm, Set[0,1,2,3], Set[]]
13
+ uvs[7].should == [fsm, Set[3], Set[0,1,2]]
14
+ uvs.last.should == [fsm, Set[0], Set[1,2,3]]
15
+ end
16
+
17
+ it 'should yield V-expanded FSMs' do
18
+ fsm = mock FSM, :input_count => 2
19
+ fsm0, fsm1, fsm2, fsm3 = mock(FSM), mock(FSM), mock(FSM), mock(FSM)
20
+ fsm.should_receive(:expand_x).exactly(4).times.and_return(fsm0, fsm1, fsm2, fsm3)
21
+ archs = Set[Arch[3,1]]
22
+ uv_gen = UVGenerator::Braindead.new fsm, archs
23
+ uv_gen.uv_pairs.to_a.should == [
24
+ [fsm0, Set[0,1], Set[]],
25
+ [fsm1, Set[1], Set[0]],
26
+ [fsm2, Set[0], Set[1]],
27
+ [fsm3, Set[], Set[0,1]],
28
+ ]
29
+ end
30
+
31
+ end
32
+
33
+ end end
@@ -0,0 +1,61 @@
1
+ module ArtDecomp describe UVGenerator::Relevance do
2
+
3
+ context 'given a certain FSM and a Set of Archs' do
4
+
5
+ it 'should yield U and V combinations in a relevance-based order' do
6
+ fsm = mock FSM, :input_count => 6, :input_relevance => [0, 1, 2, nil, nil, nil, 3, 4, 5]
7
+ fsm.stub!(:expand_x).and_return fsm
8
+ archs = Set[Arch[3,1]]
9
+ uv_gen = UVGenerator::Relevance.new fsm, archs
10
+ uvs = uv_gen.uv_pairs.to_a
11
+ uvs.size.should == 42
12
+ uvs[0].should == [fsm, Set[0,1,2], Set[3,4,5]]
13
+ uvs[1].should == [fsm, Set[0,1,2,3], Set[4,5]]
14
+ uvs[2].should == [fsm, Set[0,1,2,4], Set[3,5]]
15
+ uvs[3].should == [fsm, Set[0,1,2,5], Set[3,4]]
16
+ uvs[4].should == [fsm, Set[0,1,2,3,4], Set[5]]
17
+ uvs[5].should == [fsm, Set[0,1,2,3,5], Set[4]]
18
+ uvs[6].should == [fsm, Set[0,1,2,4,5], Set[3]]
19
+ uvs[7].should == [fsm, Set[0,1,2,3,4,5], Set[]]
20
+ uvs[8].should == [fsm, Set[0,1,3], Set[2,4,5]]
21
+ uvs.last.should == [fsm, Set[3,4,5], Set[0,1,2]]
22
+ end
23
+
24
+ it 'should consider all architecture widths when generating the UV sets' do
25
+ fsm = mock FSM, :input_count => 6, :input_relevance => [0, 1, 2, nil, nil, nil, 3, 4, 5]
26
+ fsm.stub!(:expand_x).and_return fsm
27
+ archs = Set[Arch[3,1], Arch[2,1]]
28
+ uv_gen = UVGenerator::Relevance.new fsm, archs
29
+ uvs = uv_gen.uv_pairs.to_a
30
+ uvs.size.should == 42
31
+ uvs[0].should == [fsm, Set[0,1,2,3], Set[4,5]]
32
+ uvs[1].should == [fsm, Set[0,1,2,4], Set[3,5]]
33
+ uvs[2].should == [fsm, Set[0,1,2,5], Set[3,4]]
34
+ uvs[3].should == [fsm, Set[0,1,2], Set[3,4,5]]
35
+ uvs[4].should == [fsm, Set[0,1,2,3,4], Set[5]]
36
+ uvs[5].should == [fsm, Set[0,1,2,3,5], Set[4]]
37
+ uvs[6].should == [fsm, Set[0,1,2,4,5], Set[3]]
38
+ uvs[7].should == [fsm, Set[0,1,2,3,4,5], Set[]]
39
+ uvs[8].should == [fsm, Set[0,1,3,4], Set[2,5]]
40
+ uvs[9].should == [fsm, Set[0,1,3,5], Set[2,4]]
41
+ uvs[10].should == [fsm, Set[0,1,3], Set[2,4,5]]
42
+ uvs.last.should == [fsm, Set[3,4,5], Set[0,1,2]]
43
+ end
44
+
45
+ it 'should yield V-expanded FSMs' do
46
+ fsm = mock FSM, :input_count => 2, :input_relevance => [1, 0, nil, nil, nil]
47
+ fsm0, fsm1, fsm2, fsm3 = mock(FSM), mock(FSM), mock(FSM), mock(FSM)
48
+ fsm.should_receive(:expand_x).exactly(4).times.and_return(fsm0, fsm1, fsm2, fsm3)
49
+ archs = Set[Arch[3,1]]
50
+ uv_gen = UVGenerator::Relevance.new fsm, archs
51
+ uv_gen.uv_pairs.to_a.should == [
52
+ [fsm0, Set[0,1], Set[]],
53
+ [fsm1, Set[1], Set[0]],
54
+ [fsm2, Set[0], Set[1]],
55
+ [fsm3, Set[], Set[0,1]],
56
+ ]
57
+ end
58
+
59
+ end
60
+
61
+ end end
@@ -0,0 +1,20 @@
1
+ describe Enumerable do
2
+
3
+ it 'should provide an Enumerator for consecutive element pairs' do
4
+ set = Set[1,2,3,4]
5
+ set.pairs.to_a.should == [[1,2], [1,3], [1,4], [2,3], [2,4], [3,4]]
6
+ end
7
+
8
+ it 'should fall back to #combination for the pair selection if possible' do
9
+ array = [1,2,3,4]
10
+ array.should_receive(:combination).with 2
11
+ array.pairs
12
+ end
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
+ end
@@ -0,0 +1,15 @@
1
+ describe File do
2
+
3
+ it 'should be able to marshal an object to a given file' do
4
+ file = Tempfile.new rand
5
+ File.dump_object [:answer, 42, 'Deep Thought'], file.path
6
+ Marshal.load(File.read(file.path)).should == [:answer, 42, 'Deep Thought']
7
+ end
8
+
9
+ it 'should be able to dump arbitrary data to a given file' do
10
+ file = Tempfile.new rand
11
+ File.write_data '42', file.path
12
+ File.read(file.path).should == '42'
13
+ end
14
+
15
+ end
@@ -0,0 +1,16 @@
1
+ describe Integer do
2
+
3
+ it 'should return set bits' do
4
+ 0.bits.should == []
5
+ 0b111.bits.should == [0,1,2]
6
+ 0b1000.bits.should == [3]
7
+ 0b101010.bits.should == [1,3,5]
8
+ (2**69).bits.should == [69]
9
+ end
10
+
11
+ it 'should return ceil of base-2 logarithm' do
12
+ (0..9).map(&:log2_ceil).should == [0,0,1,2,2,3,3,3,3,4]
13
+ (2**69).log2_ceil.should == 69
14
+ end
15
+
16
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: UTF-8
2
+
3
+ describe Set do
4
+
5
+ it 'should side-step a MRI bug with Set#hash' do
6
+ Set[2305860601668175887].hash.should == Set[2305860601668175887].hash
7
+ end
8
+
9
+ context 'of Separations' do
10
+
11
+ B, Sep = ArtDecomp::B, ArtDecomp::Sep
12
+
13
+ it 'should provide a given block’s r-admissibility' do
14
+ b = B[1,2,3,4]
15
+ Set[Sep[1,5]].r_adm(b).should == 0
16
+ Set[Sep[1,4]].r_adm(b).should == 1
17
+ Set[Sep[1,2], Sep[5,6]].r_adm(b).should == 1
18
+ Set[Sep[1,2], Sep[3,4]].r_adm(b).should == 1
19
+ Set[Sep[1,3], Sep[1,4], Sep[2,3], Sep[2,4]].r_adm(b).should == 1
20
+ Set[Sep[1,3], Sep[1,4], Sep[2,3], Sep[2,4], Sep[3,4]].r_adm(b).should == 2
21
+ ArtDecomp::Blanket[B[1],B[2],B[3],B[4]].seps.r_adm(b).should == 2
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: UTF-8
2
+
3
+ describe String do
4
+
5
+ it 'should provide an expansion of don’t-cares when representing boolean inputs' do
6
+ '0'.dc_expand.should == ['0']
7
+ '-'.dc_expand.should == ['0', '1']
8
+ '-1-'.dc_expand.should == ['010', '011', '110', '111']
9
+ end
10
+
11
+ it 'the expansion should be limitable to just a given set of columns' do
12
+ '---'.dc_expand.should == ['000', '001', '010', '011', '100', '101', '110', '111']
13
+ '---'.dc_expand(Set[0,2]).should == ['0-0', '0-1', '1-0', '1-1']
14
+ '---'.dc_expand(Set[1]).should == ['-0-', '-1-']
15
+ end
16
+
17
+ end
data/spec/fixtures/ex5 ADDED
@@ -0,0 +1,36 @@
1
+ .i 2
2
+ .o 2
3
+ .p 32
4
+ .s 9
5
+ 00 1 0 --
6
+ 01 1 7 00
7
+ 10 1 5 11
8
+ 11 1 4 --
9
+ 00 2 1 --
10
+ 01 2 4 --
11
+ 10 2 0 --
12
+ 11 2 0 00
13
+ 00 3 3 --
14
+ 01 3 0 00
15
+ 10 3 0 --
16
+ 11 3 7 11
17
+ 00 4 5 00
18
+ 01 4 0 --
19
+ 10 4 1 --
20
+ 11 4 0 --
21
+ 00 5 0 11
22
+ 01 5 6 --
23
+ 10 5 0 11
24
+ 11 5 0 11
25
+ 00 6 0 11
26
+ 01 6 5 --
27
+ 10 6 1 11
28
+ 11 6 0 11
29
+ 00 7 6 --
30
+ 01 7 0 11
31
+ 10 7 2 --
32
+ 11 7 8 --
33
+ 00 8 3 --
34
+ 01 8 0 --
35
+ 10 8 1 00
36
+ 11 8 0 --
data/spec/fixtures/fsm ADDED
@@ -0,0 +1,24 @@
1
+ .i 4
2
+ .o 2
3
+ .p 20
4
+ .s 10
5
+ --00 init0 init1 00
6
+ 0100 init1 init1 00
7
+ --1- init1 init2 10
8
+ 1-10 init2 init4 10
9
+ -111 init4 init4 10
10
+ --01 init4 IOwait 01
11
+ 000- IOwait IOwait 01
12
+ 100- IOwait init1 01
13
+ 0110 IOwait read0 00
14
+ 1100 IOwait write0 11
15
+ 0111 IOwait RMACK 11
16
+ 1101 IOwait WMACK 00
17
+ -01- IOwait init2 01
18
+ 0010 RMACK RMACK 11
19
+ 0111 RMACK read0 00
20
+ 1100 WMACK WMACK 00
21
+ 1001 WMACK write0 01
22
+ 0001 read0 read1 11
23
+ 0010 read1 IOwait 01
24
+ 0100 write0 IOwait 01
@@ -0,0 +1,40 @@
1
+ 0000 IOwait IOwait 01
2
+ 0000 init0 init1 00
3
+ 0001 IOwait IOwait 01
4
+ 0001 init4 IOwait 01
5
+ 0001 read0 read1 11
6
+ 0010 IOwait init2 01
7
+ 0010 RMACK RMACK 11
8
+ 0010 init1 init2 10
9
+ 0010 read1 IOwait 01
10
+ 0011 IOwait init2 01
11
+ 0011 init1 init2 10
12
+ 0100 init0 init1 00
13
+ 0100 init1 init1 00
14
+ 0100 write0 IOwait 01
15
+ 0101 init4 IOwait 01
16
+ 0110 IOwait read0 00
17
+ 0110 init1 init2 10
18
+ 0111 IOwait RMACK 11
19
+ 0111 RMACK read0 00
20
+ 0111 init1 init2 10
21
+ 0111 init4 init4 10
22
+ 1000 IOwait init1 01
23
+ 1000 init0 init1 00
24
+ 1001 IOwait init1 01
25
+ 1001 WMACK write0 01
26
+ 1001 init4 IOwait 01
27
+ 1010 IOwait init2 01
28
+ 1010 init1 init2 10
29
+ 1010 init2 init4 10
30
+ 1011 IOwait init2 01
31
+ 1011 init1 init2 10
32
+ 1100 IOwait write0 11
33
+ 1100 WMACK WMACK 00
34
+ 1100 init0 init1 00
35
+ 1101 IOwait WMACK 00
36
+ 1101 init4 IOwait 01
37
+ 1110 init1 init2 10
38
+ 1110 init2 init4 10
39
+ 1111 init1 init2 10
40
+ 1111 init4 init4 10
@@ -0,0 +1,20 @@
1
+ --00 init0 init1 00
2
+ --01 init4 IOwait 01
3
+ --1- init1 init2 10
4
+ -01- IOwait init2 01
5
+ -111 init4 init4 10
6
+ 000- IOwait IOwait 01
7
+ 0001 read0 read1 11
8
+ 0010 RMACK RMACK 11
9
+ 0010 read1 IOwait 01
10
+ 0100 init1 init1 00
11
+ 0100 write0 IOwait 01
12
+ 0110 IOwait read0 00
13
+ 0111 IOwait RMACK 11
14
+ 0111 RMACK read0 00
15
+ 1-10 init2 init4 10
16
+ 100- IOwait init1 01
17
+ 1001 WMACK write0 01
18
+ 1100 IOwait write0 11
19
+ 1100 WMACK WMACK 00
20
+ 1101 IOwait WMACK 00
@@ -0,0 +1,4 @@
1
+ 00 0
2
+ 01 1
3
+ 10 1
4
+ 11 0