art-decomp 0.1.0 → 0.2.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.
- data/VERSION +1 -1
- data/bin/ad-fsm-info +48 -0
- data/lib/art-decomp.rb +3 -1
- data/lib/art-decomp/decomposer.rb +3 -2
- data/lib/art-decomp/executable.rb +1 -1
- data/lib/art-decomp/fsm.rb +34 -11
- data/lib/art-decomp/graph.rb +4 -6
- data/lib/art-decomp/logging.rb +4 -2
- data/lib/art-decomp/qu_generator/block_table.rb +4 -4
- data/lib/art-decomp/qu_generator/edge_labels.rb +2 -2
- data/lib/art-decomp/qv_generator/bipainting.rb +3 -3
- data/lib/art-decomp/qv_generator/graph_colouring.rb +2 -2
- data/lib/art-decomp/qv_generator/graph_merging.rb +3 -3
- data/lib/art-decomp/uv_generator/braindead.rb +7 -11
- data/lib/art-decomp/uv_generator/general_relevance.rb +7 -0
- data/lib/art-decomp/uv_generator/unique_relevance.rb +7 -0
- data/lib/art-decomp/uv_relevance_generator.rb +19 -0
- data/spec/art-decomp/decomposer_spec.rb +4 -4
- data/spec/art-decomp/executable_spec.rb +3 -4
- data/spec/art-decomp/fsm_spec.rb +32 -9
- data/spec/art-decomp/graph_spec.rb +5 -0
- data/spec/art-decomp/logging_spec.rb +18 -7
- data/spec/art-decomp/uv_generator/braindead_spec.rb +4 -4
- data/spec/art-decomp/uv_generator/general_relevance_spec.rb +11 -0
- data/spec/art-decomp/uv_generator/unique_relevance_spec.rb +11 -0
- data/spec/art-decomp/{uv_generator/relevance_spec.rb → uv_relevance_generator_spec.rb} +10 -10
- metadata +13 -9
- data/bin/ad-analyse +0 -30
- data/bin/ad-inputs +0 -26
- data/lib/art-decomp/uv_generator/relevance.rb +0 -23
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0. | 
| 1 | 
            +
            0.2.0
         | 
    
        data/bin/ad-fsm-info
    ADDED
    
    | @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # encoding: UTF-8
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require_relative '../lib/art-decomp'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            $stdout.sync = true
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ARGV.each do |fsm_file|
         | 
| 9 | 
            +
              fsm = ArtDecomp::FSM.from_kiss fsm_file
         | 
| 10 | 
            +
              puts "#{fsm_file}: #{fsm.stats}"
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              f_seps = fsm.beta_f.seps
         | 
| 13 | 
            +
              i_seps = Hash[(0...fsm.input_count).map { |i| [i, fsm.beta_x(Set[i]).seps & f_seps] }]
         | 
| 14 | 
            +
              i_seps['Q'] = fsm.beta_q.seps & f_seps
         | 
| 15 | 
            +
              o_seps = Hash[(0...fsm.output_count).map { |o| [o, fsm.beta_y(Set[o]).seps] }]
         | 
| 16 | 
            +
              o_seps['Q’'] = fsm.beta_qp.seps
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              u_i_seps = i_seps.map { |i, seps| seps.reject { |s| i_seps.any? { |o, os| o != i and o != 'Q' and os.include? s } } }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              puts "relevant separation counts: #{i_seps.values.map &:size}"
         | 
| 21 | 
            +
              puts "unique relevant sep counts: #{u_i_seps.map &:size}"
         | 
| 22 | 
            +
              puts "relevant separation counts by input: #{i_seps.values.map(&:size).each.with_index.sort.reverse.map &:last}"
         | 
| 23 | 
            +
              puts "unique relevant sep counts by input: #{u_i_seps.map(&:size).each.with_index.sort.reverse.map &:last}"
         | 
| 24 | 
            +
              puts "relevant state separations per pin: #{i_seps['Q'].size.to_f   / fsm.beta_q.pins}"
         | 
| 25 | 
            +
              puts "unique relevant state seps per pin: #{u_i_seps.last.size.to_f / fsm.beta_q.pins}"
         | 
| 26 | 
            +
              puts "unnecessary inputs: #{i_seps.select { |i, sep| sep.empty? }.keys.sort}"
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              i_seps.pairs.each do |(a, sep_a), (b, sep_b)|
         | 
| 29 | 
            +
                next if sep_a.empty? or sep_b.empty?
         | 
| 30 | 
            +
                puts "input inclusion: #{a} ⊂ #{b}" if sep_a.proper_subset?   sep_b
         | 
| 31 | 
            +
                puts "input inclusion: #{a} = #{b}" if sep_a ==               sep_b
         | 
| 32 | 
            +
                puts "input inclusion: #{a} ⊃ #{b}" if sep_a.proper_superset? sep_b
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              o_seps.each do |o, o_sep|
         | 
| 36 | 
            +
                required = Set[]
         | 
| 37 | 
            +
                o_sep.each do |separation|
         | 
| 38 | 
            +
                  required << i_seps.select { |i, s| s.include? separation }.keys.to_set
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
                required.delete_if do |this|
         | 
| 41 | 
            +
                  required.any? { |other| this != other and this.superset? other }
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
                puts "sufficient for o#{o}: #{required.map(&:to_a)}"
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              puts
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            end
         | 
    
        data/lib/art-decomp.rb
    CHANGED
    
    | @@ -61,5 +61,7 @@ require_relative 'art-decomp/qv_generator/bipainting' | |
| 61 61 | 
             
            require_relative 'art-decomp/qv_generator/graph_colouring'
         | 
| 62 62 | 
             
            require_relative 'art-decomp/qv_generator/graph_merging'
         | 
| 63 63 | 
             
            require_relative 'art-decomp/sep'
         | 
| 64 | 
            +
            require_relative 'art-decomp/uv_relevance_generator'
         | 
| 64 65 | 
             
            require_relative 'art-decomp/uv_generator/braindead'
         | 
| 65 | 
            -
            require_relative 'art-decomp/uv_generator/ | 
| 66 | 
            +
            require_relative 'art-decomp/uv_generator/general_relevance'
         | 
| 67 | 
            +
            require_relative 'art-decomp/uv_generator/unique_relevance'
         | 
| @@ -2,7 +2,8 @@ module ArtDecomp class Decomposer | |
| 2 2 |  | 
| 3 3 | 
             
              def initialize params
         | 
| 4 4 | 
             
                @archs   = params[:archs]
         | 
| 5 | 
            -
                @ | 
| 5 | 
            +
                @fsm     = params[:fsm]
         | 
| 6 | 
            +
                @uv_gens = params[:uv_gens].map &:new
         | 
| 6 7 | 
             
                @qu_gens = params[:qu_gens].map &:new
         | 
| 7 8 | 
             
                @qv_gens = params[:qv_gens].map &:new
         | 
| 8 9 | 
             
              end
         | 
| @@ -11,7 +12,7 @@ module ArtDecomp class Decomposer | |
| 11 12 | 
             
                @seen = Set[]
         | 
| 12 13 | 
             
                Enumerator.new do |yielder|
         | 
| 13 14 | 
             
                  @uv_gens.each do |uv_gen|
         | 
| 14 | 
            -
                    uv_gen.uv_pairs.each do |fsm, u, v|
         | 
| 15 | 
            +
                    uv_gen.uv_pairs(@fsm, @archs).each do |fsm, u, v|
         | 
| 15 16 | 
             
                      unless @seen.include? [fsm, u, v]
         | 
| 16 17 | 
             
                        @qu_gens.each do |qu_gen|
         | 
| 17 18 | 
             
                          qu_gen.blankets(fsm, u, v).each do |qu|
         | 
| @@ -9,7 +9,7 @@ module ArtDecomp class Executable | |
| 9 9 | 
             
                  opt :archs,        'Target architecture(s)',               :type => :strings
         | 
| 10 10 | 
             
                  opt :outdir,       'Output directory',                     :type => :string
         | 
| 11 11 | 
             
                  opt :iters,        'Number of iterations, 0 for infinite', :default => 1
         | 
| 12 | 
            -
                  opt :uv,           'UV generator(s)',                      :default => [' | 
| 12 | 
            +
                  opt :uv,           'UV generator(s)',                      :default => ['GeneralRelevance']
         | 
| 13 13 | 
             
                  opt :qu,           'Qu generator(s)',                      :default => ['EdgeLabels']
         | 
| 14 14 | 
             
                  opt :qv,           'Qv generator(s)',                      :default => ['GraphColouring']
         | 
| 15 15 | 
             
                  opt :binary,       'Compute binary decompositions',        :default => false
         | 
    
        data/lib/art-decomp/fsm.rb
    CHANGED
    
    | @@ -41,9 +41,16 @@ module ArtDecomp class FSM | |
| 41 41 | 
             
                Blanket.from_array @state
         | 
| 42 42 | 
             
              end
         | 
| 43 43 |  | 
| 44 | 
            +
              def beta_qp
         | 
| 45 | 
            +
                Blanket.from_array @next_state
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 44 48 | 
             
              def beta_x ins
         | 
| 45 | 
            -
                 | 
| 46 | 
            -
             | 
| 49 | 
            +
                beta @inputs, ins
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              def beta_y ins
         | 
| 53 | 
            +
                beta @outputs, ins
         | 
| 47 54 | 
             
              end
         | 
| 48 55 |  | 
| 49 56 | 
             
              alias eql? ==
         | 
| @@ -58,26 +65,22 @@ module ArtDecomp class FSM | |
| 58 65 | 
             
                Arch[input_count + beta_q.pins, output_count + beta_q.pins].cells archs
         | 
| 59 66 | 
             
              end
         | 
| 60 67 |  | 
| 68 | 
            +
              def general_relevance
         | 
| 69 | 
            +
                relevance false
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
             | 
| 61 72 | 
             
              def hash
         | 
| 62 73 | 
             
                @inputs.hash ^ @outputs.hash ^ @state.hash ^ @next_state.hash
         | 
| 63 74 | 
             
              end
         | 
| 64 75 |  | 
| 65 76 | 
             
              def implementable_in? archs
         | 
| 66 | 
            -
                 | 
| 67 | 
            -
                input_count + beta_q.pins <= archs.map(&:pins).max
         | 
| 77 | 
            +
                not fsm_cells(archs).nil?
         | 
| 68 78 | 
             
              end
         | 
| 69 79 |  | 
| 70 80 | 
             
              def input_count
         | 
| 71 81 | 
             
                @inputs.size
         | 
| 72 82 | 
             
              end
         | 
| 73 83 |  | 
| 74 | 
            -
              def input_relevance
         | 
| 75 | 
            -
                seps = beta_f.seps
         | 
| 76 | 
            -
                perpin = (beta_q.seps & seps).size.to_f / beta_q.pins
         | 
| 77 | 
            -
                more, less = (0...input_count).map { |i| [(beta_x(Set[i]).seps & seps).size, i] }.sort.reverse.reject { |rel, i| rel.zero? }.partition { |rel, i| rel > perpin }
         | 
| 78 | 
            -
                more.map(&:last) + [nil] * beta_q.pins + less.map(&:last)
         | 
| 79 | 
            -
              end
         | 
| 80 | 
            -
             | 
| 81 84 | 
             
              def q_encoding rows
         | 
| 82 85 | 
             
                # FIXME: consider tr DontCare, '*'
         | 
| 83 86 | 
             
                encoding @state, rows
         | 
| @@ -109,6 +112,10 @@ module ArtDecomp class FSM | |
| 109 112 | 
             
                @state.all? { |s| s == DontCare } and @next_state.all? { |ns| ns == DontCare }
         | 
| 110 113 | 
             
              end
         | 
| 111 114 |  | 
| 115 | 
            +
              def unique_relevance
         | 
| 116 | 
            +
                relevance true
         | 
| 117 | 
            +
              end
         | 
| 118 | 
            +
             | 
| 112 119 | 
             
              def x_encoding ins, rows
         | 
| 113 120 | 
             
                ins.map { |i| encoding @inputs[i], rows }.join
         | 
| 114 121 | 
             
              end
         | 
| @@ -123,6 +130,11 @@ module ArtDecomp class FSM | |
| 123 130 |  | 
| 124 131 | 
             
              private
         | 
| 125 132 |  | 
| 133 | 
            +
              def beta column, ins
         | 
| 134 | 
            +
                return Blanket[B[*0...@state.size]] if ins.empty?
         | 
| 135 | 
            +
                ins.map { |i| Blanket.from_array column[i] }.inject :*
         | 
| 136 | 
            +
              end
         | 
| 137 | 
            +
             | 
| 126 138 | 
             
              def encoding column, rows
         | 
| 127 139 | 
             
                encs = rows.bits.map { |row| column[row] }.uniq - [DontCare]
         | 
| 128 140 | 
             
                case encs.size
         | 
| @@ -132,4 +144,15 @@ module ArtDecomp class FSM | |
| 132 144 | 
             
                end
         | 
| 133 145 | 
             
              end
         | 
| 134 146 |  | 
| 147 | 
            +
              def relevance unique
         | 
| 148 | 
            +
                f_seps = beta_f.seps
         | 
| 149 | 
            +
                i_seps = Hash[(0...input_count).map { |i| [i, beta_x(Set[i]).seps & f_seps] }]
         | 
| 150 | 
            +
                q_seps = beta_q.seps & f_seps
         | 
| 151 | 
            +
                q_seps -= i_seps.values.inject :+ if unique
         | 
| 152 | 
            +
                perpin = q_seps.size.to_f / beta_q.pins
         | 
| 153 | 
            +
                i_seps = Hash[i_seps.map { |i, seps| [i, seps - i_seps.reject { |o,| o == i }.values.inject(Set[], :+)] }] if unique
         | 
| 154 | 
            +
                more, less = i_seps.map { |i, seps| [seps.size, i] }.sort.reverse.reject { |rel,| rel.zero? }.partition { |rel,| rel > perpin }
         | 
| 155 | 
            +
                more.map(&:last) + [nil] * beta_q.pins + less.map(&:last)
         | 
| 156 | 
            +
              end
         | 
| 157 | 
            +
             | 
| 135 158 | 
             
            end end
         | 
    
        data/lib/art-decomp/graph.rb
    CHANGED
    
    | @@ -5,12 +5,10 @@ module ArtDecomp class Graph | |
| 5 5 | 
             
              def initialize blanket, seps
         | 
| 6 6 | 
             
                @vertices = blanket.ints.dup
         | 
| 7 7 | 
             
                @vertices.delete_if { |this| @vertices.any? { |other| other != this and other & this == this } }
         | 
| 8 | 
            -
                 | 
| 9 | 
            -
                 | 
| 10 | 
            -
                   | 
| 11 | 
            -
             | 
| 12 | 
            -
                  end
         | 
| 13 | 
            -
                end
         | 
| 8 | 
            +
                relevant = Hash[@vertices.map { |v| [v, seps.select { |s| v&s != 0 and v&s != s }.to_set] }]
         | 
| 9 | 
            +
                @edges = @vertices.pairs.select do |a, b|
         | 
| 10 | 
            +
                  (relevant[a] & relevant[b]).any? { |s| a&s != b&s }
         | 
| 11 | 
            +
                end.map(&:to_set).to_set
         | 
| 14 12 | 
             
              end
         | 
| 15 13 |  | 
| 16 14 | 
             
              def adjacent *vertices
         | 
    
        data/lib/art-decomp/logging.rb
    CHANGED
    
    | @@ -19,6 +19,7 @@ module ArtDecomp class Logging < Gazer::Aspect::Base | |
| 19 19 | 
             
                @@log.formatter = proc { |sev, date, name, msg| "#{date} #{msg}\n" }
         | 
| 20 20 | 
             
                @@indent = ''
         | 
| 21 21 | 
             
                apply!
         | 
| 22 | 
            +
                @@start = Time.now
         | 
| 22 23 | 
             
              end
         | 
| 23 24 |  | 
| 24 25 | 
             
              def self.off
         | 
| @@ -27,14 +28,15 @@ module ArtDecomp class Logging < Gazer::Aspect::Base | |
| 27 28 | 
             
              end
         | 
| 28 29 |  | 
| 29 30 | 
             
              after instances_of(Executable) => :run do |point|
         | 
| 30 | 
            -
                 | 
| 31 | 
            +
                secs = (Time.now - @@start).to_i
         | 
| 32 | 
            +
                @@log.info "#{point.object.best ? "final best decomposition: #{point.object.best} cells" : 'no final decomposition'}; done in #{secs}s (#{secs / 60 / 60}h #{secs / 60 % 60}m #{secs % 60}s)"
         | 
| 31 33 | 
             
              end
         | 
| 32 34 |  | 
| 33 35 | 
             
              before instances_of(Executable) => :decompositions do |point|
         | 
| 34 36 | 
             
                @@indent = '  ' * (point.object.iters - point.args[1])
         | 
| 35 37 | 
             
                path     = point.args[2][point.object.dir.size+1..-1]
         | 
| 36 38 | 
             
                archs    = point.object.archs.map(&:to_s).sort.reverse.join '+'
         | 
| 37 | 
            -
                @@log.info "#{@@indent}FSM #{point.args[0].stats} → #{archs} (#{path}) with #{point.object.gens} – best so far: #{point.object.best} cells"
         | 
| 39 | 
            +
                @@log.info "#{@@indent}FSM #{point.args[0].stats} → #{archs} (#{path}) with #{point.object.gens} – #{point.object.best ? "best so far: #{point.object.best} cells" : 'no decomposition so far'}"
         | 
| 38 40 | 
             
              end
         | 
| 39 41 |  | 
| 40 42 | 
             
              before instances_of(UVGenerator.constants.map { |c| eval("UVGenerator::#{c}") }) => :uv_pairs do |point|
         | 
| @@ -1,11 +1,11 @@ | |
| 1 1 | 
             
            module ArtDecomp class QuGenerator::BlockTable
         | 
| 2 2 |  | 
| 3 3 | 
             
              def blankets fsm, u, v
         | 
| 4 | 
            +
                @seps   = fsm.beta_f.seps
         | 
| 5 | 
            +
                @rows   = fsm.beta_q.ints.dup
         | 
| 6 | 
            +
                @cols   = fsm.beta_x(u).ints
         | 
| 7 | 
            +
                @r_adms = {}
         | 
| 4 8 | 
             
                Enumerator.new do |yielder|
         | 
| 5 | 
            -
                  @seps   = fsm.beta_f.seps
         | 
| 6 | 
            -
                  @rows   = fsm.beta_q.ints.dup
         | 
| 7 | 
            -
                  @cols   = fsm.beta_x(u).ints
         | 
| 8 | 
            -
                  @r_adms = {}
         | 
| 9 9 | 
             
                  fold_matching!
         | 
| 10 10 | 
             
                  yielder.yield Blanket.new @rows
         | 
| 11 11 | 
             
                  while @rows.size > 1
         | 
| @@ -1,9 +1,9 @@ | |
| 1 1 | 
             
            module ArtDecomp class QuGenerator::EdgeLabels
         | 
| 2 2 |  | 
| 3 3 | 
             
              def blankets fsm, u, v
         | 
| 4 | 
            +
                seps   = fsm.beta_f.seps - fsm.beta_x(u).seps
         | 
| 5 | 
            +
                @graph = Graph.new fsm.beta_q, seps
         | 
| 4 6 | 
             
                Enumerator.new do |yielder|
         | 
| 5 | 
            -
                  seps = fsm.beta_f.seps - fsm.beta_x(u).seps
         | 
| 6 | 
            -
                  @graph = Graph.new fsm.beta_q, seps
         | 
| 7 7 | 
             
                  initial_merge
         | 
| 8 8 | 
             
                  yielder.yield Blanket.new @graph.vertices
         | 
| 9 9 | 
             
                  while @graph.vertices.size > 1
         | 
| @@ -1,10 +1,10 @@ | |
| 1 1 | 
             
            module ArtDecomp class QvGenerator::Bipainting
         | 
| 2 2 |  | 
| 3 3 | 
             
              def blankets fsm, u, v, beta_qu
         | 
| 4 | 
            +
                beta_u    = fsm.beta_x u
         | 
| 5 | 
            +
                beta_v    = fsm.beta_x v
         | 
| 6 | 
            +
                bipainter = Bipainter.new fsm.beta_q, beta_v, fsm.beta_f.seps - beta_u.seps - beta_qu.seps
         | 
| 4 7 | 
             
                Enumerator.new do |yielder|
         | 
| 5 | 
            -
                  beta_u = fsm.beta_x u
         | 
| 6 | 
            -
                  beta_v = fsm.beta_x v
         | 
| 7 | 
            -
                  bipainter = Bipainter.new fsm.beta_q, beta_v, fsm.beta_f.seps - beta_u.seps - beta_qu.seps
         | 
| 8 8 | 
             
                  yielder.yield bipainter.blankets
         | 
| 9 9 | 
             
                end
         | 
| 10 10 | 
             
              end
         | 
| @@ -1,9 +1,9 @@ | |
| 1 1 | 
             
            module ArtDecomp class QvGenerator::GraphColouring
         | 
| 2 2 |  | 
| 3 3 | 
             
              def blankets fsm, u, v, beta_qu
         | 
| 4 | 
            +
                beta_u = fsm.beta_x u
         | 
| 5 | 
            +
                beta_v = fsm.beta_x v
         | 
| 4 6 | 
             
                Enumerator.new do |yielder|
         | 
| 5 | 
            -
                  beta_u  = fsm.beta_x u
         | 
| 6 | 
            -
                  beta_v  = fsm.beta_x v
         | 
| 7 7 | 
             
                  beta_g  = Graph.new(fsm.beta_q * beta_v, fsm.beta_f.seps - beta_u.seps - beta_qu.seps).blanket_from_colouring
         | 
| 8 8 | 
             
                  beta_qv = Graph.new(fsm.beta_q, beta_g.seps - beta_v.seps).blanket_from_colouring
         | 
| 9 9 | 
             
                  yielder.yield beta_qv, beta_g
         | 
| @@ -1,10 +1,10 @@ | |
| 1 1 | 
             
            module ArtDecomp class QvGenerator::GraphMerging
         | 
| 2 2 |  | 
| 3 3 | 
             
              def blankets fsm, u, v, beta_qu
         | 
| 4 | 
            +
                beta_u   = fsm.beta_x u
         | 
| 5 | 
            +
                beta_v   = fsm.beta_x v
         | 
| 6 | 
            +
                qv_graph = Graph.new fsm.beta_q, fsm.beta_f.seps - beta_u.seps - beta_qu.seps - beta_v.seps
         | 
| 4 7 | 
             
                Enumerator.new do |yielder|
         | 
| 5 | 
            -
                  beta_u = fsm.beta_x u
         | 
| 6 | 
            -
                  beta_v = fsm.beta_x v
         | 
| 7 | 
            -
                  qv_graph = Graph.new fsm.beta_q, fsm.beta_f.seps - beta_u.seps - beta_qu.seps - beta_v.seps
         | 
| 8 8 | 
             
                  loop do
         | 
| 9 9 | 
             
                    beta_qv = Blanket.new qv_graph.vertices
         | 
| 10 10 | 
             
                    g_graph = Graph.new beta_qv * beta_v, fsm.beta_f.seps - beta_u.seps - beta_qu.seps
         | 
| @@ -1,20 +1,16 @@ | |
| 1 1 | 
             
            module ArtDecomp class UVGenerator::Braindead
         | 
| 2 2 |  | 
| 3 | 
            -
              def  | 
| 4 | 
            -
                 | 
| 5 | 
            -
                 | 
| 6 | 
            -
                 | 
| 7 | 
            -
              end
         | 
| 8 | 
            -
             | 
| 9 | 
            -
              def uv_pairs
         | 
| 3 | 
            +
              def uv_pairs fsm, archs
         | 
| 4 | 
            +
                input_count = fsm.input_count
         | 
| 5 | 
            +
                inputs      = (0...input_count).to_a
         | 
| 6 | 
            +
                max_v_size  = archs.map(&:pins).max
         | 
| 10 7 | 
             
                Enumerator.new do |yielder|
         | 
| 11 | 
            -
                   | 
| 12 | 
            -
                  (0...2**@input_count).each do |vector|
         | 
| 8 | 
            +
                  (0...2**input_count).each do |vector|
         | 
| 13 9 | 
             
                    u, v = Set[], Set[]
         | 
| 14 | 
            -
                     | 
| 10 | 
            +
                    input_count.times do |bit|
         | 
| 15 11 | 
             
                      (vector[bit].zero? ? u : v) << inputs[bit]
         | 
| 16 12 | 
             
                    end
         | 
| 17 | 
            -
                    yielder.yield  | 
| 13 | 
            +
                    yielder.yield fsm.expand_x(v), u, v if v.size <= max_v_size
         | 
| 18 14 | 
             
                  end
         | 
| 19 15 | 
             
                end
         | 
| 20 16 | 
             
              end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            module ArtDecomp class UVRelevanceGenerator
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              def uv_pairs fsm, archs, method
         | 
| 4 | 
            +
                relevance   = fsm.send(method).reverse
         | 
| 5 | 
            +
                max_v_sizes = archs.map(&:pins).to_set
         | 
| 6 | 
            +
                cache       = Set[]
         | 
| 7 | 
            +
                Enumerator.new do |yielder|
         | 
| 8 | 
            +
                  (0...2**relevance.size).each do |vector|
         | 
| 9 | 
            +
                    bits = vector.bits
         | 
| 10 | 
            +
                    next unless max_v_sizes.include? bits.size
         | 
| 11 | 
            +
                    v = relevance.values_at(*bits).compact.to_set
         | 
| 12 | 
            +
                    u = (relevance - v.to_a).compact.to_set
         | 
| 13 | 
            +
                    yielder.yield fsm.expand_x(v), u, v unless cache.include? v
         | 
| 14 | 
            +
                    cache << v
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            end end
         | 
| @@ -6,8 +6,7 @@ module ArtDecomp describe Decomposer do | |
| 6 6 | 
             
                uv1, uv2 = mock('UVGenerator class'), mock('UVGenerator class')
         | 
| 7 7 | 
             
                qu1, qu2 = mock('QuGenerator class'), mock('QuGenerator class')
         | 
| 8 8 | 
             
                qv1, qv2 = mock('QvGenerator class'), mock('QvGenerator class')
         | 
| 9 | 
            -
                [uv1, uv2].each | 
| 10 | 
            -
                [qu1, qu2, qv1, qv2].each { |gen| gen.should_receive(:new).with no_args }
         | 
| 9 | 
            +
                [uv1, uv2, qu1, qu2, qv1, qv2].each { |gen| gen.should_receive(:new).with no_args }
         | 
| 11 10 | 
             
                Decomposer.new :fsm => fsm, :archs => archs, :uv_gens => [uv1, uv2], :qu_gens => [qu1, qu2], :qv_gens => [qv1, qv2]
         | 
| 12 11 | 
             
              end
         | 
| 13 12 |  | 
| @@ -26,6 +25,7 @@ module ArtDecomp describe Decomposer do | |
| 26 25 |  | 
| 27 26 | 
             
                it 'should poll the generators and yield the resulting decompositions one by one' do
         | 
| 28 27 | 
             
                  fsm = mock FSM, :beta_q => mock(Blanket, :pins => 3, :size => 5), :input_count => 4
         | 
| 28 | 
            +
                  archs = Set[Arch[5,1]]
         | 
| 29 29 |  | 
| 30 30 | 
             
                  u_a, v_a = Set[0,1], Set[2] # for this U/V pair: two Qu generating one Qv/G pair each
         | 
| 31 31 | 
             
                  qu_a1, qv_a1, g_a1 = mock(Blanket, :pins => 2, :size => 4), mock(Blanket, :pins => 3, :size => 5), mock(Blanket, :pins => 2)
         | 
| @@ -36,14 +36,14 @@ module ArtDecomp describe Decomposer do | |
| 36 36 | 
             
                  qv_bA, g_bA = mock(Blanket, :pins => 3, :size => 5), mock(Blanket, :pins => 2)
         | 
| 37 37 | 
             
                  qv_bB, g_bB = mock(Blanket, :pins => 3, :size => 5), mock(Blanket, :pins => 2)
         | 
| 38 38 |  | 
| 39 | 
            -
                  uv_gen = mock UVGenerator, :new => StubGenerator.new({[] => [[fsm, u_a, v_a], [fsm, u_b, v_b]]})
         | 
| 39 | 
            +
                  uv_gen = mock UVGenerator, :new => StubGenerator.new({[fsm, archs] => [[fsm, u_a, v_a], [fsm, u_b, v_b]]})
         | 
| 40 40 | 
             
                  qu_gen = mock QuGenerator, :new => StubGenerator.new({[fsm, u_a, v_a] => [qu_a1, qu_a2],
         | 
| 41 41 | 
             
                                                                        [fsm, u_b, v_b] => [qu_b]})
         | 
| 42 42 | 
             
                  qv_gen = mock QvGenerator, :new => StubGenerator.new({[fsm, u_a, v_a, qu_a1] => [[qv_a1, g_a1]],
         | 
| 43 43 | 
             
                                                                        [fsm, u_a, v_a, qu_a2] => [[qv_a2, g_a2]],
         | 
| 44 44 | 
             
                                                                        [fsm, u_b, v_b, qu_b]  => [[qv_bA, g_bA], [qv_bB, g_bB]]})
         | 
| 45 45 |  | 
| 46 | 
            -
                  decomposer = Decomposer.new :archs =>  | 
| 46 | 
            +
                  decomposer = Decomposer.new :archs => archs, :fsm => fsm, :uv_gens => [uv_gen], :qu_gens => [qu_gen], :qv_gens => [qv_gen]
         | 
| 47 47 | 
             
                  results = decomposer.decompositions.to_a
         | 
| 48 48 | 
             
                  results.size.should  == 4
         | 
| 49 49 | 
             
                  results.first.should == Decomposition.new(fsm, u_a, v_a, qu_a1, qv_a1, g_a1)
         | 
| @@ -3,7 +3,6 @@ | |
| 3 3 | 
             
            module ArtDecomp describe Executable do
         | 
| 4 4 |  | 
| 5 5 | 
             
              before do
         | 
| 6 | 
            -
                @orig_stderr = $stderr
         | 
| 7 6 | 
             
                $stderr = StringIO.new
         | 
| 8 7 | 
             
                @fsm = 'spec/fixtures/fsm'
         | 
| 9 8 | 
             
                @dir = "#{Dir.tmpdir}/#{rand.to_s}"
         | 
| @@ -11,7 +10,7 @@ module ArtDecomp describe Executable do | |
| 11 10 | 
             
              end
         | 
| 12 11 |  | 
| 13 12 | 
             
              after do
         | 
| 14 | 
            -
                $stderr =  | 
| 13 | 
            +
                $stderr = STDERR
         | 
| 15 14 | 
             
                FileUtils.rmtree @dir if Dir.exists? @dir
         | 
| 16 15 | 
             
              end
         | 
| 17 16 |  | 
| @@ -84,7 +83,7 @@ module ArtDecomp describe Executable do | |
| 84 83 | 
             
                dec = Decomposition.new fsm, Set[0], Set[1], Blanket[B[0],B[1],B[2]], Blanket[], Blanket[]
         | 
| 85 84 |  | 
| 86 85 | 
             
                decomposer = mock Decomposer, :decompositions => [dec, dec].each
         | 
| 87 | 
            -
                Decomposer.should_receive(:new).with(:fsm => fsm, :archs => an_instance_of(Set), :uv_gens => [UVGenerator:: | 
| 86 | 
            +
                Decomposer.should_receive(:new).with(:fsm => fsm, :archs => an_instance_of(Set), :uv_gens => [UVGenerator::GeneralRelevance], :qu_gens => [QuGenerator::EdgeLabels], :qv_gens => [QvGenerator::GraphColouring]).and_return decomposer
         | 
| 88 87 |  | 
| 89 88 | 
             
                Executable.new(@args).run false
         | 
| 90 89 | 
             
                Marshal.load(File.read("#{@dir}/decompositions")).should == [dec, dec]
         | 
| @@ -120,7 +119,7 @@ module ArtDecomp describe Executable do | |
| 120 119 | 
             
                FSM.should_receive(:from_kiss).with(@fsm).and_return fsm
         | 
| 121 120 |  | 
| 122 121 | 
             
                decomposer = mock Decomposer, :decompositions => [].each
         | 
| 123 | 
            -
                Decomposer.should_receive(:new).with(:fsm => fsm, :archs => Set[Arch[5,1]], :uv_gens => [UVGenerator::Braindead, UVGenerator:: | 
| 122 | 
            +
                Decomposer.should_receive(:new).with(:fsm => fsm, :archs => Set[Arch[5,1]], :uv_gens => [UVGenerator::Braindead, UVGenerator::GeneralRelevance, UVGenerator::UniqueRelevance], :qu_gens => [QuGenerator::BlockTable, QuGenerator::EdgeLabels], :qv_gens => [QvGenerator::Bipainting, QvGenerator::GraphColouring,QvGenerator::GraphMerging]).and_return decomposer
         | 
| 124 123 |  | 
| 125 124 | 
             
                args = ['--archs', '5/1', '--uv', 'all', '--qu', 'all', '--qv', 'all', '--outdir', @dir, @fsm]
         | 
| 126 125 | 
             
                Executable.new(args).run
         | 
    
        data/spec/art-decomp/fsm_spec.rb
    CHANGED
    
    | @@ -47,6 +47,12 @@ module ArtDecomp describe FSM do | |
| 47 47 | 
             
                  @mc.beta_q.should   == Blanket[B[0,1,2], B[3,4], B[5,6,7], B[8,9]]
         | 
| 48 48 | 
             
                end
         | 
| 49 49 |  | 
| 50 | 
            +
                it 'should properly generate the Q’ Blanket' do
         | 
| 51 | 
            +
                  @opus.beta_qp.should == Blanket[B[0,1], B[2,3,9], B[4,14], B[5,6], B[7,8,20,21], B[10,16], B[11,18], B[12,15], B[13,17], B[19]]
         | 
| 52 | 
            +
                  @lion.beta_qp.should == Blanket[B[0,1,4], B[2,3,7], B[5,6,10], B[8,9]]
         | 
| 53 | 
            +
                  @mc.beta_qp.should   == Blanket[B[0,1,9], B[2,3], B[4,5], B[6,7,8]]
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 50 56 | 
             
                it 'should properly generate the F Blanket' do
         | 
| 51 57 | 
             
                  @opus.beta_f.should == Blanket[B[0,1], B[2,3,9], B[4,14], B[5,6], B[7,8,20,21], B[10,16], B[11,18], B[12,15], B[13,17], B[19]]
         | 
| 52 58 | 
             
                  @lion.beta_f.should == Blanket[B[0,1,4], B[2], B[2,3,7], B[5,6,10], B[8,9]]
         | 
| @@ -59,6 +65,12 @@ module ArtDecomp describe FSM do | |
| 59 65 | 
             
                  @mc.beta_x(Set[]).should    == Blanket[B[0,1,2,3,4,5,6,7,8,9]]
         | 
| 60 66 | 
             
                end
         | 
| 61 67 |  | 
| 68 | 
            +
                it 'should properly generate selected output Blankets' do
         | 
| 69 | 
            +
                  @mc.beta_y(Set[4]).should   == Blanket[B[0,1,2,3,4,5,6,7], B[8,9]]
         | 
| 70 | 
            +
                  @mc.beta_y(Set[2,3]).should == Blanket[B[0,1,2], B[3,4], B[5,6,7,8,9]]
         | 
| 71 | 
            +
                  @mc.beta_y(Set[]).should    == Blanket[B[0,1,2,3,4,5,6,7,8,9]]
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
             | 
| 62 74 | 
             
                it 'should properly generate its KISS representation' do
         | 
| 63 75 | 
             
                  @opus.to_kiss.should == File.read('spec/fixtures/opus.to_kiss')
         | 
| 64 76 | 
             
                  @lion.to_kiss.should == File.read('spec/fixtures/lion.to_kiss')
         | 
| @@ -139,15 +151,26 @@ module ArtDecomp describe FSM do | |
| 139 151 | 
             
                  @s8.fsm_cells(Set[Arch[4,1]]).should   == 0
         | 
| 140 152 | 
             
                end
         | 
| 141 153 |  | 
| 142 | 
            -
                it 'should report its input relevance, and drop irrelevant inputs' do
         | 
| 143 | 
            -
                  @ex4. | 
| 144 | 
            -
                  @fsm. | 
| 145 | 
            -
                  @lion. | 
| 146 | 
            -
                  @mark1. | 
| 147 | 
            -
                  @mc. | 
| 148 | 
            -
                  @opus. | 
| 149 | 
            -
                  @s8. | 
| 150 | 
            -
                  @tt. | 
| 154 | 
            +
                it 'should report its general input relevance, and drop irrelevant inputs' do
         | 
| 155 | 
            +
                  @ex4.general_relevance.should   == [nil, nil, nil, nil, 2, 1, 5, 4, 3]
         | 
| 156 | 
            +
                  @fsm.general_relevance.should   == [2, 1, 3, 0, nil, nil, nil, nil]
         | 
| 157 | 
            +
                  @lion.general_relevance.should  == [0, nil, nil, 1]
         | 
| 158 | 
            +
                  @mark1.general_relevance.should == [nil, nil, nil, nil, 0, 3, 2, 4, 1]
         | 
| 159 | 
            +
                  @mc.general_relevance.should    == [nil, nil, 2, 1, 0]
         | 
| 160 | 
            +
                  @opus.general_relevance.should  == [nil, nil, nil, nil, 2, 3, 4, 0, 1]
         | 
| 161 | 
            +
                  @s8.general_relevance.should    == [3, 2, 1, 0, nil, nil, nil]
         | 
| 162 | 
            +
                  @tt.general_relevance.should    == [1, 3, 2]
         | 
| 163 | 
            +
                end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                it 'should report its unique input relevance, and drop irrelevant inputs' do
         | 
| 166 | 
            +
                  @ex4.unique_relevance.should   == [nil, nil, nil, nil, 2, 1, 5, 4, 3]
         | 
| 167 | 
            +
                  @fsm.unique_relevance.should   == [2, 1, 0, 3, nil, nil, nil, nil]
         | 
| 168 | 
            +
                  @lion.unique_relevance.should  == [0, nil, nil, 1]
         | 
| 169 | 
            +
                  @mark1.unique_relevance.should == [nil, nil, nil, nil, 0, 3, 2, 4, 1]
         | 
| 170 | 
            +
                  @mc.unique_relevance.should    == [nil, nil, 2, 1, 0]
         | 
| 171 | 
            +
                  @opus.unique_relevance.should  == [2, nil, nil, nil, nil, 3, 4, 1, 0]
         | 
| 172 | 
            +
                  @s8.unique_relevance.should    == [nil, nil, nil]
         | 
| 173 | 
            +
                  @tt.unique_relevance.should    == [1, 3, 2]
         | 
| 151 174 | 
             
                end
         | 
| 152 175 |  | 
| 153 176 | 
             
                it 'should report whether it’s a truth table or a full-blown FSM' do
         | 
| @@ -66,4 +66,9 @@ module ArtDecomp describe Graph do | |
| 66 66 | 
             
                @graph.adjacent(B[5,6], B[7]).should == Set[B[3,4], B[8,9]]
         | 
| 67 67 | 
             
              end
         | 
| 68 68 |  | 
| 69 | 
            +
              it 'should only create the necessary edges' do
         | 
| 70 | 
            +
                blanket = Blanket[B[1,2,3], B[1,2,4], B[1,5], B[2,6]]
         | 
| 71 | 
            +
                Graph.new(blanket, Set[Sep[1,2]]).edges.should == Set[Set[B[1,5], B[2,6]]]
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
             | 
| 69 74 | 
             
            end end
         | 
| @@ -6,6 +6,7 @@ module ArtDecomp describe Logging do | |
| 6 6 |  | 
| 7 7 | 
             
              before do
         | 
| 8 8 | 
             
                @dir = "#{Dir.tmpdir}/#{rand.to_s}"
         | 
| 9 | 
            +
                @fsm = mock FSM, :beta_f => Blanket[], :beta_q => Blanket[], :beta_x => Blanket[]
         | 
| 9 10 | 
             
                @log = StringIO.new
         | 
| 10 11 | 
             
                Logging.log = @log
         | 
| 11 12 | 
             
              end
         | 
| @@ -23,27 +24,37 @@ module ArtDecomp describe Logging do | |
| 23 24 | 
             
              it 'should log Executable’s decompositions calls on simple cases' do
         | 
| 24 25 | 
             
                args = ['-a', '5/1', '4/2', '-o', @dir, 'spec/fixtures/lion']
         | 
| 25 26 | 
             
                Executable.new(args).run
         | 
| 26 | 
            -
                log.should =~ rex('final best decomposition: 2')
         | 
| 27 | 
            +
                log.should =~ rex('final best decomposition: 2 cells; done in 0s (0h 0m 0s)')
         | 
| 27 28 | 
             
              end
         | 
| 28 29 |  | 
| 29 30 | 
             
              it 'should log Executable’s decompositions calls on typical cases' do
         | 
| 31 | 
            +
                Decomposer.should_receive(:new).and_return mock(Decomposer, :decompositions => [].each)
         | 
| 32 | 
            +
                args = ['-a', '5/1', '4/2', '-o', @dir, 'spec/fixtures/fsm']
         | 
| 33 | 
            +
                ex = Executable.new(args)
         | 
| 34 | 
            +
                ex.stub!(:best).and_return 69
         | 
| 35 | 
            +
                ex.run
         | 
| 36 | 
            +
                log.should =~ rex('FSM 4/2+10s → 5/1+4/2 () with GeneralRelevance, EdgeLabels, GraphColouring – best so far: 69 cells')
         | 
| 37 | 
            +
                log.should =~ rex('final best decomposition: 69 cells; done in 0s (0h 0m 0s)')
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              it 'should log Executable’s decompositions calls on problematic cases' do
         | 
| 30 41 | 
             
                Decomposer.should_receive(:new).and_return mock(Decomposer, :decompositions => [].each)
         | 
| 31 42 | 
             
                args = ['-a', '5/1', '4/2', '-o', @dir, 'spec/fixtures/fsm']
         | 
| 32 43 | 
             
                Executable.new(args).run
         | 
| 33 | 
            -
                log.should =~ rex('FSM 4/2+10s → 5/1+4/2 () with  | 
| 34 | 
            -
                log.should =~ rex('final  | 
| 44 | 
            +
                log.should =~ rex('FSM 4/2+10s → 5/1+4/2 () with GeneralRelevance, EdgeLabels, GraphColouring – no decomposition so far')
         | 
| 45 | 
            +
                log.should =~ rex('no final decomposition; done in 0s (0h 0m 0s)')
         | 
| 35 46 | 
             
              end
         | 
| 36 47 |  | 
| 37 48 | 
             
              it 'should log UVGenerators’ uv_pairs calls' do
         | 
| 38 | 
            -
                uv = UVGenerator::Braindead.new | 
| 39 | 
            -
                uv.uv_pairs
         | 
| 49 | 
            +
                uv = UVGenerator::Braindead.new
         | 
| 50 | 
            +
                uv.uv_pairs mock(FSM, :input_count => 2), Set[Arch[5,1]]
         | 
| 40 51 | 
             
                log.should =~ rex('UV with Braindead')
         | 
| 41 52 | 
             
              end
         | 
| 42 53 |  | 
| 43 54 | 
             
              it 'should log QuGenerators’ blankets calls' do
         | 
| 44 55 | 
             
                qu = QuGenerator::BlockTable.new
         | 
| 45 56 | 
             
                [[Set[0], Set[1]], [Set[1], Set[0]]].each do |u, v|
         | 
| 46 | 
            -
                  qu.blankets  | 
| 57 | 
            +
                  qu.blankets @fsm, u, v
         | 
| 47 58 | 
             
                end
         | 
| 48 59 | 
             
                log.should =~ rex('U = [0], V = [1], Qu with BlockTable')
         | 
| 49 60 | 
             
                log.should =~ rex('U = [1], V = [0], Qu with BlockTable')
         | 
| @@ -53,7 +64,7 @@ module ArtDecomp describe Logging do | |
| 53 64 | 
             
                Logging.level = Logger::DEBUG
         | 
| 54 65 | 
             
                qv = QvGenerator::GraphColouring.new
         | 
| 55 66 | 
             
                [mock(Blanket, :size => 8), mock(Blanket, :size => 4)].each do |qu|
         | 
| 56 | 
            -
                  qv.blankets  | 
| 67 | 
            +
                  qv.blankets @fsm, Set[0], Set[1], qu
         | 
| 57 68 | 
             
                end
         | 
| 58 69 | 
             
                log.should =~ rex('|Qu| = 8, Qv+G with GraphColouring')
         | 
| 59 70 | 
             
                log.should =~ rex('|Qu| = 4, Qv+G with GraphColouring')
         | 
| @@ -6,8 +6,8 @@ module ArtDecomp describe UVGenerator::Braindead do | |
| 6 6 | 
             
                  fsm = mock FSM, :input_count => 4
         | 
| 7 7 | 
             
                  fsm.stub!(:expand_x).and_return fsm
         | 
| 8 8 | 
             
                  archs = Set[Arch[3,1]]
         | 
| 9 | 
            -
                  uv_gen = UVGenerator::Braindead.new | 
| 10 | 
            -
                  uvs = uv_gen.uv_pairs.to_a
         | 
| 9 | 
            +
                  uv_gen = UVGenerator::Braindead.new
         | 
| 10 | 
            +
                  uvs = uv_gen.uv_pairs(fsm, archs).to_a
         | 
| 11 11 | 
             
                  uvs.size.should  == 15
         | 
| 12 12 | 
             
                  uvs.first.should == [fsm, Set[0,1,2,3], Set[]]
         | 
| 13 13 | 
             
                  uvs[7].should    == [fsm, Set[3], Set[0,1,2]]
         | 
| @@ -19,8 +19,8 @@ module ArtDecomp describe UVGenerator::Braindead do | |
| 19 19 | 
             
                  fsm0, fsm1, fsm2, fsm3 = mock(FSM), mock(FSM), mock(FSM), mock(FSM)
         | 
| 20 20 | 
             
                  fsm.should_receive(:expand_x).exactly(4).times.and_return(fsm0, fsm1, fsm2, fsm3)
         | 
| 21 21 | 
             
                  archs = Set[Arch[3,1]]
         | 
| 22 | 
            -
                  uv_gen = UVGenerator::Braindead.new | 
| 23 | 
            -
                  uv_gen.uv_pairs.to_a.should == [
         | 
| 22 | 
            +
                  uv_gen = UVGenerator::Braindead.new
         | 
| 23 | 
            +
                  uv_gen.uv_pairs(fsm, archs).to_a.should == [
         | 
| 24 24 | 
             
                    [fsm0, Set[0,1], Set[]],
         | 
| 25 25 | 
             
                    [fsm1, Set[1],   Set[0]],
         | 
| 26 26 | 
             
                    [fsm2, Set[0],   Set[1]],
         | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ArtDecomp describe UVGenerator::GeneralRelevance do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              it 'should call UVRelevanceGenerator’s uv_pairs method with proper args' do
         | 
| 6 | 
            +
                fsm = mock FSM
         | 
| 7 | 
            +
                fsm.should_receive(:general_relevance).and_return []
         | 
| 8 | 
            +
                UVGenerator::GeneralRelevance.new.uv_pairs fsm, Set[Arch[5,1]]
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            end end
         | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ArtDecomp describe UVGenerator::UniqueRelevance do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              it 'should call UVRelevanceGenerator’s uv_pairs method with proper args' do
         | 
| 6 | 
            +
                fsm = mock FSM
         | 
| 7 | 
            +
                fsm.should_receive(:unique_relevance).and_return []
         | 
| 8 | 
            +
                UVGenerator::UniqueRelevance.new.uv_pairs fsm, Set[Arch[5,1]]
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            end end
         | 
| @@ -1,13 +1,13 @@ | |
| 1 | 
            -
            module ArtDecomp describe  | 
| 1 | 
            +
            module ArtDecomp describe UVRelevanceGenerator do
         | 
| 2 2 |  | 
| 3 3 | 
             
              context 'given a certain FSM and a Set of Archs' do
         | 
| 4 4 |  | 
| 5 5 | 
             
                it 'should yield U and V combinations in a relevance-based order' do
         | 
| 6 | 
            -
                  fsm = mock FSM, :input_count => 6, : | 
| 6 | 
            +
                  fsm = mock FSM, :input_count => 6, :common_relevance => [0, 1, 2, nil, nil, nil, 3, 4, 5]
         | 
| 7 7 | 
             
                  fsm.stub!(:expand_x).and_return fsm
         | 
| 8 8 | 
             
                  archs = Set[Arch[3,1]]
         | 
| 9 | 
            -
                  uv_gen =  | 
| 10 | 
            -
                  uvs = uv_gen.uv_pairs.to_a
         | 
| 9 | 
            +
                  uv_gen = UVRelevanceGenerator.new
         | 
| 10 | 
            +
                  uvs = uv_gen.uv_pairs(fsm, archs, :common_relevance).to_a
         | 
| 11 11 | 
             
                  uvs.size.should == 42
         | 
| 12 12 | 
             
                  uvs[0].should   == [fsm, Set[0,1,2], Set[3,4,5]]
         | 
| 13 13 | 
             
                  uvs[1].should   == [fsm, Set[0,1,2,3], Set[4,5]]
         | 
| @@ -22,11 +22,11 @@ module ArtDecomp describe UVGenerator::Relevance do | |
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 24 | 
             
                it 'should consider all architecture widths when generating the UV sets' do
         | 
| 25 | 
            -
                  fsm = mock FSM, :input_count => 6, : | 
| 25 | 
            +
                  fsm = mock FSM, :input_count => 6, :common_relevance => [0, 1, 2, nil, nil, nil, 3, 4, 5]
         | 
| 26 26 | 
             
                  fsm.stub!(:expand_x).and_return fsm
         | 
| 27 27 | 
             
                  archs = Set[Arch[3,1], Arch[2,1]]
         | 
| 28 | 
            -
                  uv_gen =  | 
| 29 | 
            -
                  uvs = uv_gen.uv_pairs.to_a
         | 
| 28 | 
            +
                  uv_gen = UVRelevanceGenerator.new
         | 
| 29 | 
            +
                  uvs = uv_gen.uv_pairs(fsm, archs, :common_relevance).to_a
         | 
| 30 30 | 
             
                  uvs.size.should == 42
         | 
| 31 31 | 
             
                  uvs[0].should   == [fsm, Set[0,1,2,3], Set[4,5]]
         | 
| 32 32 | 
             
                  uvs[1].should   == [fsm, Set[0,1,2,4], Set[3,5]]
         | 
| @@ -43,12 +43,12 @@ module ArtDecomp describe UVGenerator::Relevance do | |
| 43 43 | 
             
                end
         | 
| 44 44 |  | 
| 45 45 | 
             
                it 'should yield V-expanded FSMs' do
         | 
| 46 | 
            -
                  fsm = mock FSM, :input_count => 2, : | 
| 46 | 
            +
                  fsm = mock FSM, :input_count => 2, :common_relevance => [1, 0, nil, nil, nil]
         | 
| 47 47 | 
             
                  fsm0, fsm1, fsm2, fsm3 = mock(FSM), mock(FSM), mock(FSM), mock(FSM)
         | 
| 48 48 | 
             
                  fsm.should_receive(:expand_x).exactly(4).times.and_return(fsm0, fsm1, fsm2, fsm3)
         | 
| 49 49 | 
             
                  archs = Set[Arch[3,1]]
         | 
| 50 | 
            -
                  uv_gen =  | 
| 51 | 
            -
                  uv_gen.uv_pairs.to_a.should == [
         | 
| 50 | 
            +
                  uv_gen = UVRelevanceGenerator.new
         | 
| 51 | 
            +
                  uv_gen.uv_pairs(fsm, archs, :common_relevance).to_a.should == [
         | 
| 52 52 | 
             
                    [fsm0, Set[0,1], Set[]],
         | 
| 53 53 | 
             
                    [fsm1, Set[1],   Set[0]],
         | 
| 54 54 | 
             
                    [fsm2, Set[0],   Set[1]],
         | 
    
        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.2.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: 2009-12- | 
| 12 | 
            +
            date: 2009-12-13 00:00:00 +01:00
         | 
| 13 13 | 
             
            default_executable: 
         | 
| 14 14 | 
             
            dependencies: 
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -77,8 +77,7 @@ email: p.szotkowski@tele.pw.edu.pl | |
| 77 77 | 
             
            executables: 
         | 
| 78 78 | 
             
            - ad-validate
         | 
| 79 79 | 
             
            - ad-console
         | 
| 80 | 
            -
            - ad- | 
| 81 | 
            -
            - ad-inputs
         | 
| 80 | 
            +
            - ad-fsm-info
         | 
| 82 81 | 
             
            - art-decomp
         | 
| 83 82 | 
             
            extensions: []
         | 
| 84 83 |  | 
| @@ -90,9 +89,8 @@ files: | |
| 90 89 | 
             
            - README
         | 
| 91 90 | 
             
            - Rakefile
         | 
| 92 91 | 
             
            - VERSION
         | 
| 93 | 
            -
            - bin/ad-analyse
         | 
| 94 92 | 
             
            - bin/ad-console
         | 
| 95 | 
            -
            - bin/ad- | 
| 93 | 
            +
            - bin/ad-fsm-info
         | 
| 96 94 | 
             
            - bin/ad-validate
         | 
| 97 95 | 
             
            - bin/art-decomp
         | 
| 98 96 | 
             
            - lib/art-decomp.rb
         | 
| @@ -115,7 +113,9 @@ files: | |
| 115 113 | 
             
            - lib/art-decomp/qv_generator/graph_merging.rb
         | 
| 116 114 | 
             
            - lib/art-decomp/sep.rb
         | 
| 117 115 | 
             
            - lib/art-decomp/uv_generator/braindead.rb
         | 
| 118 | 
            -
            - lib/art-decomp/uv_generator/ | 
| 116 | 
            +
            - lib/art-decomp/uv_generator/general_relevance.rb
         | 
| 117 | 
            +
            - lib/art-decomp/uv_generator/unique_relevance.rb
         | 
| 118 | 
            +
            - lib/art-decomp/uv_relevance_generator.rb
         | 
| 119 119 | 
             
            - lib/core/enumerable.rb
         | 
| 120 120 | 
             
            - lib/core/file.rb
         | 
| 121 121 | 
             
            - lib/core/integer.rb
         | 
| @@ -139,7 +139,9 @@ files: | |
| 139 139 | 
             
            - spec/art-decomp/qv_generator/graph_merging_spec.rb
         | 
| 140 140 | 
             
            - spec/art-decomp/sep_spec.rb
         | 
| 141 141 | 
             
            - spec/art-decomp/uv_generator/braindead_spec.rb
         | 
| 142 | 
            -
            - spec/art-decomp/uv_generator/ | 
| 142 | 
            +
            - spec/art-decomp/uv_generator/general_relevance_spec.rb
         | 
| 143 | 
            +
            - spec/art-decomp/uv_generator/unique_relevance_spec.rb
         | 
| 144 | 
            +
            - spec/art-decomp/uv_relevance_generator_spec.rb
         | 
| 143 145 | 
             
            - spec/core/enumerable_spec.rb
         | 
| 144 146 | 
             
            - spec/core/file_spec.rb
         | 
| 145 147 | 
             
            - spec/core/integer_spec.rb
         | 
| @@ -209,6 +211,7 @@ test_files: | |
| 209 211 | 
             
            - spec/art-decomp/fsm_spec.rb
         | 
| 210 212 | 
             
            - spec/art-decomp/sep_spec.rb
         | 
| 211 213 | 
             
            - spec/art-decomp/bipainter_spec.rb
         | 
| 214 | 
            +
            - spec/art-decomp/uv_relevance_generator_spec.rb
         | 
| 212 215 | 
             
            - spec/art-decomp/blanket_spec.rb
         | 
| 213 216 | 
             
            - spec/art-decomp/kiss_spec.rb
         | 
| 214 217 | 
             
            - spec/art-decomp/qv_generator/graph_colouring_spec.rb
         | 
| @@ -218,7 +221,8 @@ test_files: | |
| 218 221 | 
             
            - spec/art-decomp/decomposer_spec.rb
         | 
| 219 222 | 
             
            - spec/art-decomp/qu_generator/edge_labels_spec.rb
         | 
| 220 223 | 
             
            - spec/art-decomp/qu_generator/block_table_spec.rb
         | 
| 221 | 
            -
            - spec/art-decomp/uv_generator/ | 
| 224 | 
            +
            - spec/art-decomp/uv_generator/general_relevance_spec.rb
         | 
| 225 | 
            +
            - spec/art-decomp/uv_generator/unique_relevance_spec.rb
         | 
| 222 226 | 
             
            - spec/art-decomp/uv_generator/braindead_spec.rb
         | 
| 223 227 | 
             
            - spec/art-decomp/decomposition_spec.rb
         | 
| 224 228 | 
             
            - spec/art-decomp/b_spec.rb
         | 
    
        data/bin/ad-analyse
    DELETED
    
    | @@ -1,30 +0,0 @@ | |
| 1 | 
            -
            #!/usr/bin/env ruby
         | 
| 2 | 
            -
            # encoding: UTF-8
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            require 'rubygems'      if RUBY_VERSION < '1.9'
         | 
| 5 | 
            -
            require 'backports/1.9' if RUBY_VERSION < '1.9'
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            require_relative '../lib/art-decomp'
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            input_limit = ARGV.first.to_i.zero? ? 0 : ARGV.shift.to_i
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            $stdout.sync = true
         | 
| 12 | 
            -
             | 
| 13 | 
            -
            ARGV.each do |fsm_file|
         | 
| 14 | 
            -
              fsm = ArtDecomp::FSM.from_kiss fsm_file
         | 
| 15 | 
            -
              seps = fsm.beta_f.seps
         | 
| 16 | 
            -
              input_seps = (0...fsm.input_count).map { |i| fsm.beta_x(Set[i]).seps & seps }
         | 
| 17 | 
            -
             | 
| 18 | 
            -
              puts
         | 
| 19 | 
            -
              puts fsm_file
         | 
| 20 | 
            -
              puts "X seps: #{input_seps.map(&:size).inspect}"
         | 
| 21 | 
            -
             | 
| 22 | 
            -
              input_seps.each_with_index { |a, i| puts "#{i} insignificant" if a.empty? }
         | 
| 23 | 
            -
             | 
| 24 | 
            -
              (0...input_seps.size).pairs.to_a.each do |a, b|
         | 
| 25 | 
            -
                next if input_seps[a].empty? or input_seps[b].empty?
         | 
| 26 | 
            -
                puts "#{a} ⊂ #{b}" if input_seps[a].proper_subset?   input_seps[b]
         | 
| 27 | 
            -
                puts "#{a} = #{b}" if input_seps[a] ==               input_seps[b]
         | 
| 28 | 
            -
                puts "#{a} ⊃ #{b}" if input_seps[a].proper_superset? input_seps[b]
         | 
| 29 | 
            -
              end
         | 
| 30 | 
            -
            end
         | 
    
        data/bin/ad-inputs
    DELETED
    
    | @@ -1,26 +0,0 @@ | |
| 1 | 
            -
            #!/usr/bin/env ruby
         | 
| 2 | 
            -
            # encoding: UTF-8
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            require 'rubygems'      if RUBY_VERSION < '1.9'
         | 
| 5 | 
            -
            require 'backports/1.9' if RUBY_VERSION < '1.9'
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            require_relative '../lib/art-decomp'
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            input_limit = ARGV.first.to_i.zero? ? 0 : ARGV.shift.to_i
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            $stdout.sync = true
         | 
| 12 | 
            -
             | 
| 13 | 
            -
            ARGV.each do |fsm_file|
         | 
| 14 | 
            -
              fsm = ArtDecomp::FSM.from_kiss fsm_file
         | 
| 15 | 
            -
              next if fsm.input_count < input_limit
         | 
| 16 | 
            -
              seps = fsm.beta_f.seps
         | 
| 17 | 
            -
              rel_q = (fsm.beta_q.seps & seps).size
         | 
| 18 | 
            -
              puts
         | 
| 19 | 
            -
              puts fsm_file
         | 
| 20 | 
            -
              puts "inputs: #{fsm.input_count}"
         | 
| 21 | 
            -
              puts "βf sep: #{seps.size}"
         | 
| 22 | 
            -
              puts "βq sep: #{rel_q}"
         | 
| 23 | 
            -
              puts "βq.pin: #{fsm.beta_q.pins}"
         | 
| 24 | 
            -
              puts "perpin: #{rel_q.to_f / fsm.beta_q.pins}"
         | 
| 25 | 
            -
              puts "X seps: #{(0...fsm.input_count).map { |i| (fsm.beta_x(Set[i]).seps & seps).size }.sort.reverse.inspect}"
         | 
| 26 | 
            -
            end
         | 
| @@ -1,23 +0,0 @@ | |
| 1 | 
            -
            module ArtDecomp class UVGenerator::Relevance
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              def initialize fsm, archs
         | 
| 4 | 
            -
                @fsm         = fsm
         | 
| 5 | 
            -
                @relevance   = fsm.input_relevance.reverse
         | 
| 6 | 
            -
                @max_v_sizes = archs.map(&:pins).to_set
         | 
| 7 | 
            -
              end
         | 
| 8 | 
            -
             | 
| 9 | 
            -
              def uv_pairs
         | 
| 10 | 
            -
                @cache = Set[]
         | 
| 11 | 
            -
                Enumerator.new do |yielder|
         | 
| 12 | 
            -
                  (0...2**@relevance.size).each do |vector|
         | 
| 13 | 
            -
                    bits = vector.bits
         | 
| 14 | 
            -
                    next unless @max_v_sizes.include? bits.size
         | 
| 15 | 
            -
                    v = @relevance.values_at(*bits).compact.to_set
         | 
| 16 | 
            -
                    u = (@relevance - v.to_a).compact.to_set
         | 
| 17 | 
            -
                    yielder.yield @fsm.expand_x(v), u, v unless @cache.include? v
         | 
| 18 | 
            -
                    @cache << v
         | 
| 19 | 
            -
                  end
         | 
| 20 | 
            -
                end
         | 
| 21 | 
            -
              end
         | 
| 22 | 
            -
             | 
| 23 | 
            -
            end end
         |