abst_int 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +22 -0
- data/.pryrc +18 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +34 -0
- data/Rakefile +12 -0
- data/abst_int.gemspec +26 -0
- data/lib/abst_int.rb +83 -0
- data/lib/abst_int/calculus_model/dfa.rb +287 -0
- data/lib/abst_int/calculus_model/nfa.rb +81 -0
- data/lib/abst_int/collection.rb +32 -0
- data/lib/abst_int/integer.rb +35 -0
- data/lib/abst_int/or_set.rb +105 -0
- data/lib/abst_int/set.rb +136 -0
- data/lib/abst_int/term.rb +125 -0
- data/lib/abst_int/variable.rb +18 -0
- data/lib/abst_int/version.rb +3 -0
- data/lib/fixnum.rb +10 -0
- data/spec/abst_int_spec.rb +37 -0
- data/spec/spec_helper.rb +94 -0
- metadata +141 -0
| @@ -0,0 +1,81 @@ | |
| 1 | 
            +
            require "set"
         | 
| 2 | 
            +
            require "abst_int/calculus_model/dfa"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module AbstInt::CalculusModel
         | 
| 5 | 
            +
              class Nfa
         | 
| 6 | 
            +
                def initialize
         | 
| 7 | 
            +
                  @states = Set.new
         | 
| 8 | 
            +
                  @initial_states = Set.new
         | 
| 9 | 
            +
                  @final_states = Set.new
         | 
| 10 | 
            +
                  @inputs = Set.new
         | 
| 11 | 
            +
                  @transition = {}
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def add_initial state
         | 
| 15 | 
            +
                  @states << state
         | 
| 16 | 
            +
                  @initial_states << state
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def add_final state
         | 
| 20 | 
            +
                  @states << state
         | 
| 21 | 
            +
                  @final_states << state
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                # [state] 1,2,3
         | 
| 25 | 
            +
                # [input] 'a', 'b', 'c'
         | 
| 26 | 
            +
                def add_trans state1, input, state2
         | 
| 27 | 
            +
                  @states << state1 << state2
         | 
| 28 | 
            +
                  @inputs << input
         | 
| 29 | 
            +
                  @transition[state1] ||= {}
         | 
| 30 | 
            +
                  @transition[state1][input] ||= Set.new
         | 
| 31 | 
            +
                  @transition[state1][input] << state2
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def exists_initial?
         | 
| 35 | 
            +
                  not @initial_states.empty?
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def to_dfa
         | 
| 39 | 
            +
                  dfa = AbstInt::CalculusModel::Dfa.new
         | 
| 40 | 
            +
                  dfa.set_initial @initial_states
         | 
| 41 | 
            +
                  dfa = generate_dfa dfa, @initial_states, Set.new
         | 
| 42 | 
            +
                  dfa.each_states do |states|
         | 
| 43 | 
            +
                    dfa.add_final states unless (states & @final_states).empty?
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
                  return dfa
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def to_s
         | 
| 49 | 
            +
                  puts "[states]"
         | 
| 50 | 
            +
                  @states.each {|state| puts "#{state.is_a?(Array) ? state.map(&:to_s) : state}, " }
         | 
| 51 | 
            +
                  puts "[initial_states]"
         | 
| 52 | 
            +
                  @initial_states.each {|state| puts "#{state.is_a?(Array) ? state.map(&:to_s) : state}, " }
         | 
| 53 | 
            +
                  puts "[final_states]"
         | 
| 54 | 
            +
                  @final_states.each {|state| puts "#{state.is_a?(Array) ? state.map(&:to_s) : state}, " }
         | 
| 55 | 
            +
                  puts "[inputs]"
         | 
| 56 | 
            +
                  @inputs.each {|input| puts "#{input}, " }
         | 
| 57 | 
            +
                  puts "[transition]"
         | 
| 58 | 
            +
                  @transition.each do |state1, value|
         | 
| 59 | 
            +
                    value.each do |input, value|
         | 
| 60 | 
            +
                      value.each do |state2|
         | 
| 61 | 
            +
                        puts "#{state1.is_a?(Array) ? state1.map(&:to_s) : state1}, #{input}, #{state2.is_a?(Array) ? state2.map(&:to_s) : state2}"
         | 
| 62 | 
            +
                      end if value
         | 
| 63 | 
            +
                    end if value
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                private
         | 
| 68 | 
            +
                def generate_dfa dfa, states, state_setset
         | 
| 69 | 
            +
                  return dfa if state_setset.include? states
         | 
| 70 | 
            +
                  old_dfa = dfa.dup
         | 
| 71 | 
            +
                  @inputs.each do |input|
         | 
| 72 | 
            +
                    next_states = states.inject(Set.new) do |result, state|
         | 
| 73 | 
            +
                      @transition.try(:[], state).try(:[], input) ? result + (@transition[state][input]) : result
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
                    dfa.add_trans states, input, next_states
         | 
| 76 | 
            +
                    dfa = generate_dfa dfa, next_states, (state_setset << states)
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                  return dfa
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
            end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            class AbstInt::Collection < BasicObject
         | 
| 2 | 
            +
              class NilClass
         | 
| 3 | 
            +
              end
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def initialize args
         | 
| 6 | 
            +
                @objects = args
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def == *args
         | 
| 10 | 
            +
                self.method_missing :==, *args
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              def != *args
         | 
| 14 | 
            +
                self.method_missing :"!=", *args
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def equal? *args
         | 
| 18 | 
            +
                self.method_missing :equal?, *args
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              def method_missing method_name, *args
         | 
| 22 | 
            +
                result = ::AbstInt::Collection::NilClass.new
         | 
| 23 | 
            +
                @objects.each do |object|
         | 
| 24 | 
            +
                  if result.is_a? ::AbstInt::Collection::NilClass
         | 
| 25 | 
            +
                    result = object.send(method_name, *args)
         | 
| 26 | 
            +
                  else
         | 
| 27 | 
            +
                    raise ::AbstInt::MultiResultError, "There are more results than one." unless result == object.send(method_name, *args)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
                return result
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            require "abst_int"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class AbstInt::Integer
         | 
| 4 | 
            +
              def initialize abst_int
         | 
| 5 | 
            +
                @abst_int = abst_int
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              def + abst_int_or_int
         | 
| 9 | 
            +
                @abst_int + abst_int_or_int
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def - abst_int_or_int
         | 
| 13 | 
            +
                @abst_int - abst_int_or_int
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              def * abst_int_or_int
         | 
| 17 | 
            +
                @abst_int * abst_int_or_int
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def / abst_int_or_int
         | 
| 21 | 
            +
                @abst_int / abst_int_or_int
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def % num
         | 
| 25 | 
            +
                @abst_int % num
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def to_s
         | 
| 29 | 
            +
                @abst_int.to_s
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def _terms
         | 
| 33 | 
            +
                @abst_int.terms
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,105 @@ | |
| 1 | 
            +
            require "abst_int/set"
         | 
| 2 | 
            +
            require "abst_int/calculus_model/nfa"
         | 
| 3 | 
            +
            require "abst_int/collection"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            class AbstInt::OrSet
         | 
| 6 | 
            +
              def initialize coefficient = nil, be_variable = false
         | 
| 7 | 
            +
                @elements = []
         | 
| 8 | 
            +
                if coefficient.is_a? Fixnum
         | 
| 9 | 
            +
                  self << (AbstInt::Set.new coefficient, be_variable)
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              def + orset
         | 
| 14 | 
            +
                return self if orset.nil?
         | 
| 15 | 
            +
                new_orset = AbstInt::OrSet.new
         | 
| 16 | 
            +
                orset.each do |set1|
         | 
| 17 | 
            +
                  self.each do |set2|
         | 
| 18 | 
            +
                    new_orset << (set1 + set2)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
                return new_orset
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def - orset
         | 
| 25 | 
            +
                self + orset * AbstInt::OrSet.new(-1)
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def * orset
         | 
| 29 | 
            +
                new_orset = AbstInt::OrSet.new
         | 
| 30 | 
            +
                orset.each do |set1|
         | 
| 31 | 
            +
                  self.each do |set2|
         | 
| 32 | 
            +
                    new_orset << (set1 * set2)
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
                return new_orset
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def % num
         | 
| 39 | 
            +
                current_mod = []
         | 
| 40 | 
            +
                self.each do |set|
         | 
| 41 | 
            +
                  mod = set % num
         | 
| 42 | 
            +
                  current_mod << mod
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
                return AbstInt::Collection.new(current_mod)
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              def | orset
         | 
| 48 | 
            +
                return self if orset.is_a? NilClass
         | 
| 49 | 
            +
                cloned_self = self.dup
         | 
| 50 | 
            +
                orset.each do |set|
         | 
| 51 | 
            +
                  cloned_self << set
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
                return cloned_self
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              def & orset
         | 
| 57 | 
            +
                left_dfa = (self.to_nfa.to_dfa)
         | 
| 58 | 
            +
                right_dfa = (orset.to_nfa.to_dfa)
         | 
| 59 | 
            +
                result = left_dfa & right_dfa
         | 
| 60 | 
            +
                result = result.to_orset
         | 
| 61 | 
            +
                return result
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
              def not
         | 
| 65 | 
            +
                return self.to_nfa.to_dfa.not.to_orset
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              def star
         | 
| 69 | 
            +
                new_orset = AbstInt::OrSet.new
         | 
| 70 | 
            +
                self.each do |set|
         | 
| 71 | 
            +
                  new_orset << set.star
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
                return new_orset
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
              def to_s
         | 
| 77 | 
            +
                @elements.map{|element| element.to_s}.join("|")
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
              protected
         | 
| 81 | 
            +
              def to_nfa
         | 
| 82 | 
            +
                nfa = AbstInt::CalculusModel::Nfa.new
         | 
| 83 | 
            +
                self.each do |set|
         | 
| 84 | 
            +
                  nfa = set.generate_nfa nfa
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
                return nfa
         | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
              def each &block
         | 
| 90 | 
            +
                @elements.each(&block)
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
              def << set
         | 
| 94 | 
            +
                expanded = false
         | 
| 95 | 
            +
                @elements.each { |self_set|
         | 
| 96 | 
            +
                  next if expanded
         | 
| 97 | 
            +
                  expanded_set = self_set.expand(set) || set.expand(self_set)
         | 
| 98 | 
            +
                  next if expanded_set.nil?
         | 
| 99 | 
            +
                  expanded = true
         | 
| 100 | 
            +
                  @elements = @elements - [self_set]
         | 
| 101 | 
            +
                  self << expanded_set
         | 
| 102 | 
            +
                }
         | 
| 103 | 
            +
                @elements << set unless expanded
         | 
| 104 | 
            +
              end
         | 
| 105 | 
            +
            end
         | 
    
        data/lib/abst_int/set.rb
    ADDED
    
    | @@ -0,0 +1,136 @@ | |
| 1 | 
            +
            require "abst_int/term"
         | 
| 2 | 
            +
            require "abst_int/calculus_model/nfa"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            class AbstInt::Set
         | 
| 5 | 
            +
              def initialize coefficient = nil, be_variable = false
         | 
| 6 | 
            +
                @elements = []
         | 
| 7 | 
            +
                if coefficient.is_a? Fixnum
         | 
| 8 | 
            +
                  self  << (AbstInt::Term.new coefficient, be_variable)
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def + set
         | 
| 13 | 
            +
                cloned_self = self.dup
         | 
| 14 | 
            +
                set.each do |term|
         | 
| 15 | 
            +
                  cloned_self << term
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
                return cloned_self
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def - set
         | 
| 21 | 
            +
                self + set * AbstInt::Set.new(-1)
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def * set
         | 
| 25 | 
            +
                result = AbstInt::Set.new
         | 
| 26 | 
            +
                cloned_self = self.dup
         | 
| 27 | 
            +
                cloned_self.each do |self_term|
         | 
| 28 | 
            +
                  set.each do |term|
         | 
| 29 | 
            +
                    result << (self_term * term)
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
                return result
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              def % num
         | 
| 36 | 
            +
                @elements.inject(0){|result, term| [result, term % num].max }
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              def star
         | 
| 40 | 
            +
                result = AbstInt::Set.new
         | 
| 41 | 
            +
                self.each do |term|
         | 
| 42 | 
            +
                  result << term.star
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
                return result
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              def to_s
         | 
| 48 | 
            +
                @elements.map{|element| element.to_s}.join("+")
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              def generate_nfa nfa
         | 
| 52 | 
            +
                self.each do |term|
         | 
| 53 | 
            +
                  # 各termごとの設定
         | 
| 54 | 
            +
                  nfa = term.generate_nfa nfa, self
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
                unless nfa.exists_initial?
         | 
| 57 | 
            +
                  nfa.add_initial self
         | 
| 58 | 
            +
                  nfa.add_final self
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
                return nfa
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              def include? set
         | 
| 64 | 
            +
                # setの変数に0を代入して計算
         | 
| 65 | 
            +
                set_offset = set.calc 0
         | 
| 66 | 
            +
                # その値がselfに含まれているか確認
         | 
| 67 | 
            +
                input_string = set_offset < 0 ? "b" * (- set_offset) : "a" * set_offset
         | 
| 68 | 
            +
                return false unless self.to_nfa.to_dfa.accept? input_string
         | 
| 69 | 
            +
                # 含まれているならば、変数項の係数の包含関係をチェック
         | 
| 70 | 
            +
                set.each do |term|
         | 
| 71 | 
            +
                  next unless term.variable_exists?
         | 
| 72 | 
            +
                  include_check = false
         | 
| 73 | 
            +
                  self.each do |self_term|
         | 
| 74 | 
            +
                    next unless self_term.variable_exists?
         | 
| 75 | 
            +
                    include_check = include_check || self_term.include?(term)
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                  return false unless include_check
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
                return true
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
              def expand set
         | 
| 83 | 
            +
                return self if self.include? set
         | 
| 84 | 
            +
                return nil unless self.check_lank == 1 && set.check_lank == 0
         | 
| 85 | 
            +
                set_offset = set.calc 0
         | 
| 86 | 
            +
                if self.calc(-1) == set_offset
         | 
| 87 | 
            +
                  new_set = AbstInt::Set.new
         | 
| 88 | 
            +
                  new_set << AbstInt::Term.new(set_offset)
         | 
| 89 | 
            +
                  self.each do |term|
         | 
| 90 | 
            +
                    new_set << term if term.variable_exists?
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
                  return new_set
         | 
| 93 | 
            +
                else
         | 
| 94 | 
            +
                  return nil
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
              end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
              def check_lank
         | 
| 99 | 
            +
                lank = 0
         | 
| 100 | 
            +
                self.each do |term|
         | 
| 101 | 
            +
                  lank += 1 if term.variable_exists?
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
                return lank
         | 
| 104 | 
            +
              end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
              protected
         | 
| 107 | 
            +
              def each &block
         | 
| 108 | 
            +
                @elements.each(&block)
         | 
| 109 | 
            +
              end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
              def << term
         | 
| 112 | 
            +
                new_elements = []
         | 
| 113 | 
            +
                added_flag = false
         | 
| 114 | 
            +
                @elements.each do |element|
         | 
| 115 | 
            +
                  if (element =~ term) && (not added_flag)
         | 
| 116 | 
            +
                    new_elements << (element + term)
         | 
| 117 | 
            +
                    added_flag = true
         | 
| 118 | 
            +
                  else
         | 
| 119 | 
            +
                    new_elements << element
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
                new_elements << term unless added_flag
         | 
| 123 | 
            +
                @elements = new_elements
         | 
| 124 | 
            +
                return nil
         | 
| 125 | 
            +
              end
         | 
| 126 | 
            +
             | 
| 127 | 
            +
              def to_nfa
         | 
| 128 | 
            +
                nfa = AbstInt::CalculusModel::Nfa.new
         | 
| 129 | 
            +
                nfa = self.generate_nfa nfa
         | 
| 130 | 
            +
                return nfa
         | 
| 131 | 
            +
              end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
              def calc num
         | 
| 134 | 
            +
                @elements.inject(0){|sum, x| sum + (x.calc num)}
         | 
| 135 | 
            +
              end
         | 
| 136 | 
            +
            end
         | 
| @@ -0,0 +1,125 @@ | |
| 1 | 
            +
            require "abst_int/variable"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class AbstInt::Term
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def initialize coefficient = nil, be_variable = false
         | 
| 6 | 
            +
                @coefficient = coefficient || 1
         | 
| 7 | 
            +
                @variables = []
         | 
| 8 | 
            +
                self << AbstInt::Variable.new if be_variable
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              def << variable
         | 
| 12 | 
            +
                @variables << variable
         | 
| 13 | 
            +
                @variables.sort!
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              # like terms check
         | 
| 17 | 
            +
              def =~ term
         | 
| 18 | 
            +
                return false unless @variables.length == term.variables.length
         | 
| 19 | 
            +
                @variables.each_with_index do |variable, i|
         | 
| 20 | 
            +
                  return false unless variable.id == term.variables[i].id
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
                return true
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              # collect like terms
         | 
| 26 | 
            +
              def + term
         | 
| 27 | 
            +
                raise "this is not like terms." unless self =~ term
         | 
| 28 | 
            +
                cloned_term = self.clone
         | 
| 29 | 
            +
                cloned_term.coefficient += term.coefficient
         | 
| 30 | 
            +
                return cloned_term
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              def * abst_int_or_term
         | 
| 34 | 
            +
                cloned_term = self.clone
         | 
| 35 | 
            +
                term = abst_int_or_term
         | 
| 36 | 
            +
                cloned_term.coefficient *= term.coefficient
         | 
| 37 | 
            +
                term.variables.each do |variable|
         | 
| 38 | 
            +
                  cloned_term << variable
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
                return cloned_term
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              def % num
         | 
| 44 | 
            +
                if @variables.empty?
         | 
| 45 | 
            +
                  return (@coefficient % num)
         | 
| 46 | 
            +
                else
         | 
| 47 | 
            +
                  raise AbstInt::MultiResultError, "There are more results than one." if @coefficient % num != 0
         | 
| 48 | 
            +
                  return 0
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              def star
         | 
| 53 | 
            +
                cloned_term = AbstInt::Term.new
         | 
| 54 | 
            +
                cloned_term.coefficient = @coefficient
         | 
| 55 | 
            +
                cloned_term.variables = @variables
         | 
| 56 | 
            +
                cloned_term.variables = cloned_term.variables + [AbstInt::Variable.new] if @variables.empty? && @coefficient != 0
         | 
| 57 | 
            +
                return cloned_term
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              def generate_nfa nfa, set
         | 
| 61 | 
            +
                if @variables.empty?
         | 
| 62 | 
            +
                  if @coefficient == 0
         | 
| 63 | 
            +
                  elsif @coefficient < 0
         | 
| 64 | 
            +
                    nfa.add_initial [self, @coefficient]
         | 
| 65 | 
            +
                    nfa.add_final set
         | 
| 66 | 
            +
                    state_proc = proc { |x| (x == 0) ? set : [self, x] }
         | 
| 67 | 
            +
                    (@coefficient...0).each do |i|
         | 
| 68 | 
            +
                      nfa.add_trans state_proc.call(i), 'b', state_proc.call(i+1)
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
                  else
         | 
| 71 | 
            +
                    nfa.add_initial set
         | 
| 72 | 
            +
                    nfa.add_final [self, @coefficient]
         | 
| 73 | 
            +
                    state_proc = proc { |x| (x == 0) ? set : [self, x] }
         | 
| 74 | 
            +
                    (0...@coefficient).each do |i|
         | 
| 75 | 
            +
                      nfa.add_trans state_proc.call(i), 'a', state_proc.call(i+1)
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                else
         | 
| 79 | 
            +
                  state_proc = proc { |x| (x == 0 || x == @coefficient) ? set : [self, x] }
         | 
| 80 | 
            +
                  alphabet = @coefficient < 0 ? 'b' : 'a'
         | 
| 81 | 
            +
                  unsigned_coefficient = @coefficient < 0 ? -@coefficient : @coefficient
         | 
| 82 | 
            +
                  @coefficient.times do |i|
         | 
| 83 | 
            +
                    nfa.add_trans state_proc.call(i), alphabet, state_proc.call(i+1)
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
                return nfa
         | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
              # for debug
         | 
| 90 | 
            +
              def to_s
         | 
| 91 | 
            +
                "#{@coefficient}#{@variables.map{|var| var.to_s}.join}"
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
              def calc num
         | 
| 95 | 
            +
                return @variables.empty? ?  @coefficient : @coefficient * num
         | 
| 96 | 
            +
              end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
              def variable_exists?
         | 
| 99 | 
            +
                return not(@variables.empty?)
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
              # 一旦、変数ありterm同士の包含比較
         | 
| 103 | 
            +
              def include? term
         | 
| 104 | 
            +
                return false unless self.variable_exists? && term.variable_exists?
         | 
| 105 | 
            +
                return true if term.coefficient % self.coefficient == 0
         | 
| 106 | 
            +
                return false
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
              protected
         | 
| 110 | 
            +
              def coefficient
         | 
| 111 | 
            +
                @coefficient
         | 
| 112 | 
            +
              end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
              def coefficient= coefficient
         | 
| 115 | 
            +
                @coefficient = coefficient
         | 
| 116 | 
            +
              end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
              def variables
         | 
| 119 | 
            +
                @variables
         | 
| 120 | 
            +
              end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
              def variables= variables
         | 
| 123 | 
            +
                @variables = variables
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
            end
         |