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.
@@ -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