abst_int 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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