art-decomp 0.0.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.
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