symbo 0.1.0pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'symbo/fraction'
4
+ require 'symbo/power'
5
+
6
+ module Symbo
7
+ class Sqrt
8
+ def self.[](x) # rubocop:disable Naming/MethodParameterName
9
+ Symbo::Power[x, Symbo::Fraction[1, 2]]
10
+ end
11
+ end
12
+
13
+ def √(x) # rubocop:disable Naming/MethodName, Naming/BinaryOperatorParameterName, Naming/MethodParameterName
14
+ Sqrt[x]
15
+ end
16
+ end
@@ -0,0 +1,211 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'symbo/expression'
4
+ require 'symbo/factorial'
5
+ require 'symbo/function'
6
+ require 'symbo/mergeable'
7
+ require 'symbo/product'
8
+
9
+ module Symbo
10
+ # シンボリックな和
11
+ class Sum < Expression
12
+ include Mergeable
13
+
14
+ using Symbo
15
+
16
+ # :section: Power Transformation Methods
17
+
18
+ # べき乗の低
19
+ #
20
+ # (:x + :y).base # => :x + :y
21
+ def base
22
+ dup
23
+ end
24
+
25
+ # べき指数
26
+ #
27
+ # (:x + :y).exponent # => 1
28
+ def exponent
29
+ 1
30
+ end
31
+
32
+ # :section: Basic Distributive Transformation Methods
33
+
34
+ # 同類項の項部分
35
+ #
36
+ # (:x + :y).term # => Product[:x + :y]
37
+ def term
38
+ Product[self]
39
+ end
40
+
41
+ # 同類項の定数部分
42
+ #
43
+ # (:x + :y).const # => 1
44
+ def const
45
+ 1
46
+ end
47
+
48
+ # :section: Order Relation Methods
49
+
50
+ # 交換法則によるオペランド並べ替えに使う順序関係
51
+ #
52
+ # - 相手が和の場合
53
+ # 最右のオペランドから順に compare していき、異なるものがあればそれで順序を決定する。
54
+ # どちらかのオペランドがなくなれば、短いほうが左側。
55
+ #
56
+ # (:a + :b).compare(:a + :c) # => true
57
+ # Sum[:a, :c, :d].compare(Sum[:b, :c, :d]) # => true
58
+ # (:c + :d).compare(Sum[:b, :c, :d]) # => true
59
+ #
60
+ # - 階乗、関数、シンボルの場合
61
+ # 相手を単項の和にして比較
62
+ #
63
+ # (1 + :x).compare(:y) # => true
64
+ #
65
+ # - それ以外の場合
66
+ # 次のルールで比較
67
+ #
68
+ # !other.compare(self)
69
+ #
70
+ # rubocop:disable Metrics/CyclomaticComplexity
71
+ def compare(other)
72
+ case other
73
+ when Sum
74
+ return @operands.last.compare(other.operands.last) if @operands.last != other.operands.last
75
+
76
+ m = length
77
+ n = other.length
78
+ if [m, n].min >= 2
79
+ 1.upto([m, n].min) do |j|
80
+ return operand(m - j).compare(other.operand(n - j)) if operand(m - j) != other.operand(n - j)
81
+ end
82
+ end
83
+ m < n
84
+ when Factorial, Function, Symbol
85
+ compare Sum[other]
86
+ else
87
+ !other.compare(self)
88
+ end
89
+ end
90
+ # rubocop:enable Metrics/CyclomaticComplexity
91
+
92
+ # :section:
93
+
94
+ # rubocop:disable Metrics/PerceivedComplexity
95
+ # rubocop:disable Metrics/CyclomaticComplexity
96
+ def evaluate
97
+ v = @operands[0].evaluate
98
+ w = @operands[1].evaluate
99
+
100
+ if (v.integer? || v.complex?) && (w.integer? || w.complex?)
101
+ v.plus w
102
+ elsif v.constant? && w.constant?
103
+ Fraction[Sum[Product[v.numerator, w.denominator].evaluate, Product[w.numerator, v.denominator].evaluate].evaluate,
104
+ Product[v.denominator, w.denominator].evaluate].evaluate
105
+ else
106
+ Sum[v.simplify, w.simplify]
107
+ end
108
+ end
109
+ # rubocop:enable Metrics/PerceivedComplexity
110
+ # rubocop:enable Metrics/CyclomaticComplexity
111
+
112
+ def simplify_rational_number
113
+ self
114
+ end
115
+
116
+ def to_s
117
+ elements = @operands.map do |each|
118
+ case each
119
+ when Sum
120
+ if each.length > 1
121
+ [' + ', "(#{each})"]
122
+ else
123
+ [' + ', each.to_s]
124
+ end
125
+ when Product
126
+ if each.length > 1 && each.operand(0) == -1
127
+ [' - ', Product[*each.operands[1..-1]].to_s]
128
+ else
129
+ [' + ', each.to_s]
130
+ end
131
+ else
132
+ [' + ', each.to_s]
133
+ end
134
+ end
135
+ elements.flatten[1..-1].join
136
+ end
137
+
138
+ protected
139
+
140
+ def _simplify
141
+ return UNDEFINED if @operands.include?(UNDEFINED)
142
+ return operand(0) if length == 1
143
+
144
+ v = simplify_rec(@operands)
145
+ if v.size == 1
146
+ v[0]
147
+ elsif v.size > 1
148
+ Sum[*v]
149
+ else
150
+ 0
151
+ end
152
+ end
153
+
154
+ private
155
+
156
+ # rubocop:disable Metrics/PerceivedComplexity
157
+ # rubocop:disable Metrics/CyclomaticComplexity
158
+ def simplify_rec(l) # rubocop:disable Naming/MethodParameterName
159
+ case l
160
+ in Constant, Constant
161
+ p = Sum[*l].simplify_rne
162
+ p.zero? ? [] : [p]
163
+ in u1, u2 if u1.zero? && !u2.sum?
164
+ [u2]
165
+ in u1, u2 if u2.zero? && !u1.sum?
166
+ [u1]
167
+ in u1, u2 if l.none?(:sum?) && u1.term == u2.term
168
+ s = Sum[u1.const, u2.const].simplify
169
+ p = Product[u1.term, s].simplify
170
+ p.zero? ? [] : [p]
171
+ in u1, u2 if l.none?(&:sum?) && u2.compare(u1)
172
+ [u2, u1]
173
+ in _, _ if l.none?(&:sum?)
174
+ l
175
+ in Sum => u1, Sum => u2
176
+ merge u1.operands, u2.operands
177
+ in Sum => u1, u2
178
+ merge u1.operands, [u2]
179
+ in u1, Sum => u2
180
+ merge [u1], u2.operands
181
+ in Sum => u1, *rest
182
+ merge u1.operands, simplify_rec(rest)
183
+ in u1, *rest
184
+ merge [u1], simplify_rec(rest)
185
+ end
186
+ end
187
+ # rubocop:enable Metrics/PerceivedComplexity
188
+ # rubocop:enable Metrics/CyclomaticComplexity
189
+
190
+ # rubocop:disable Metrics/PerceivedComplexity
191
+ def simplify_rne_rec
192
+ if length == 1
193
+ v = operand(0).simplify_rne_rec
194
+ if v.undefined?
195
+ UNDEFINED
196
+ else
197
+ v
198
+ end
199
+ elsif length == 2
200
+ v = operand(0).simplify_rne_rec
201
+ w = operand(1).simplify_rne_rec
202
+ if v.undefined? || w.undefined?
203
+ UNDEFINED
204
+ else
205
+ Sum[v, w].evaluate
206
+ end
207
+ end
208
+ end
209
+ # rubocop:enable Metrics/PerceivedComplexity
210
+ end
211
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'symbo/algebraic_operators'
4
+ require 'symbo/expression_type'
5
+ require 'symbo/relational_operators'
6
+
7
+ module Symbo
8
+ refine Symbol do
9
+ include AlgebraicOperators
10
+ include ExpressionType
11
+ include RelationalOperators
12
+
13
+ # :section: Simplification Methods
14
+
15
+ def simplify
16
+ self
17
+ end
18
+
19
+ # :section: Power Transformation Methods
20
+
21
+ # べき乗の低
22
+ #
23
+ # :x.base # => :x
24
+ def base
25
+ self
26
+ end
27
+
28
+ # べき指数
29
+ #
30
+ # :x.exponent # => 1
31
+ def exponent
32
+ 1
33
+ end
34
+
35
+ # :section: Basic Distributive Transformation Methods
36
+
37
+ # 同類項の項部分
38
+ #
39
+ # :x.term # => Product[:x]
40
+ def term
41
+ Product[self]
42
+ end
43
+
44
+ # 同類項の定数部分
45
+ #
46
+ # :x.const # => 1
47
+ def const
48
+ 1
49
+ end
50
+
51
+ # :section: Order Relation Methods
52
+
53
+ # 交換法則によるオペランド並べ替えに使う順序関係
54
+ #
55
+ # - 相手がシンボルの場合
56
+ # 辞書順で順序を決定
57
+ #
58
+ # :a.compare(:b) # => true
59
+ # :A.compare(:a) # => true
60
+ # :v1.compare(:v2) # => true
61
+ # :x1.compare(:xa) # => true
62
+ #
63
+ # - それ以外の場合
64
+ # :x.compare(:x**2) # => true
65
+ # :x.compare(Function(:x, :t)) # => true
66
+ # :x.compare(Function(:y, :t)) # => true
67
+ def compare(other)
68
+ if other.is_a?(Symbol)
69
+ if self == :π
70
+ -1
71
+ else
72
+ self < other
73
+ end
74
+ else
75
+ !other.compare(self)
76
+ end
77
+ end
78
+
79
+ # :section: Relational Operator Methods
80
+
81
+ def ==(other)
82
+ other.is_a?(Symbol) && to_s == other.to_s
83
+ end
84
+
85
+ # :category: Simplification Methods
86
+
87
+ def simplify_rational_number
88
+ raise unless self == UNDEFINED
89
+
90
+ UNDEFINED
91
+ end
92
+ end
93
+ end
94
+
95
+ # Matrix などの中で使われる Symbol#+ などをハイジャック
96
+ class Symbol
97
+ include Symbo::ExpressionType
98
+
99
+ def +(other)
100
+ Symbo::Sum[self, other]
101
+ end
102
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Symbo
4
+ class TensorProduct
5
+ def self.[](matrix0, matrix1)
6
+ col_ms = (0...matrix0.column_size).map do |col|
7
+ ms = (0...matrix0.row_size).map do |row|
8
+ matrix0[row, col] * matrix1
9
+ end
10
+ Matrix.vstack(*ms)
11
+ end
12
+ Matrix.hstack(*col_ms)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'symbo/function'
4
+
5
+ module Symbo
6
+ class TrigonometricFunction < Function
7
+ using Symbo
8
+
9
+ def x
10
+ @operands[1]
11
+ end
12
+
13
+ def simplify
14
+ self.class.new(x.simplify)._simplify
15
+ end
16
+
17
+ private
18
+
19
+ # rubocop:disable Metrics/AbcSize
20
+ def kn_pi?
21
+ x.product? && x.length == 2 && x.operand(0).constant? && x.operand(1) == PI &&
22
+ [1, 2, 3, 4, 6].include?(x.operand(0).denominator) && x.operand(0).numerator.integer?
23
+ end
24
+ # rubocop:enable Metrics/AbcSize
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Symbo
4
+ VERSION = '0.1.0pre'
5
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'symbo/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'symbo'
10
+ spec.version = Symbo::VERSION
11
+ spec.authors = ['Yasuhito Takamiya']
12
+ spec.email = ['yasuhito@gmail.com']
13
+
14
+ spec.summary = 'A simple CAS (computer algebra system) in Ruby'
15
+ spec.homepage = 'https://github.com/yasuhito/symbo'
16
+ spec.license = 'MIT'
17
+
18
+ spec.metadata['homepage_uri'] = spec.homepage
19
+ spec.metadata['source_code_uri'] = 'https://github.com/yasuhito/symbo'
20
+ spec.metadata['changelog_uri'] = 'https://github.com/yasuhito/symbo/blob/develop/CHANGELOG.md'
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ end
27
+ spec.bindir = 'exe'
28
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ['lib']
30
+
31
+ spec.add_development_dependency 'bundler'
32
+ spec.add_development_dependency 'rake'
33
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: symbo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0pre
5
+ platform: ruby
6
+ authors:
7
+ - Yasuhito Takamiya
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-03-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email:
43
+ - yasuhito@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".github/workflows/ruby.yml"
49
+ - ".gitignore"
50
+ - ".rubocop.yml"
51
+ - ".ruby-version"
52
+ - CHANGELOG.md
53
+ - Gemfile
54
+ - Gemfile.lock
55
+ - LICENSE
56
+ - README.md
57
+ - Rakefile
58
+ - bin/console
59
+ - bin/setup
60
+ - lib/symbo.rb
61
+ - lib/symbo/algebraic_operators.rb
62
+ - lib/symbo/complex.rb
63
+ - lib/symbo/constant.rb
64
+ - lib/symbo/cos.rb
65
+ - lib/symbo/diff.rb
66
+ - lib/symbo/e.rb
67
+ - lib/symbo/expression.rb
68
+ - lib/symbo/expression_type.rb
69
+ - lib/symbo/factorial.rb
70
+ - lib/symbo/float.rb
71
+ - lib/symbo/fraction.rb
72
+ - lib/symbo/function.rb
73
+ - lib/symbo/integer.rb
74
+ - lib/symbo/matrix.rb
75
+ - lib/symbo/mergeable.rb
76
+ - lib/symbo/pi.rb
77
+ - lib/symbo/power.rb
78
+ - lib/symbo/product.rb
79
+ - lib/symbo/qubit.rb
80
+ - lib/symbo/quot.rb
81
+ - lib/symbo/relational_operators.rb
82
+ - lib/symbo/sin.rb
83
+ - lib/symbo/sqrt.rb
84
+ - lib/symbo/sum.rb
85
+ - lib/symbo/symbol.rb
86
+ - lib/symbo/tensor_product.rb
87
+ - lib/symbo/trigonometric_function.rb
88
+ - lib/symbo/version.rb
89
+ - symbo.gemspec
90
+ homepage: https://github.com/yasuhito/symbo
91
+ licenses:
92
+ - MIT
93
+ metadata:
94
+ homepage_uri: https://github.com/yasuhito/symbo
95
+ source_code_uri: https://github.com/yasuhito/symbo
96
+ changelog_uri: https://github.com/yasuhito/symbo/blob/develop/CHANGELOG.md
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.3.1
111
+ requirements: []
112
+ rubygems_version: 3.1.2
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: A simple CAS (computer algebra system) in Ruby
116
+ test_files: []