rb_maxima 0.1.0 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2001c84271ebb26844cf1217d8e5ae5c7844987c65d4fe14723700996e45d6a
4
- data.tar.gz: 579008bc8d879af91514e27597a6887c9cbcb9aebfac62091b4354ce0e304b0c
3
+ metadata.gz: d7f8a7781dde39239a581fe9e88b9d127b93bdd7225bb027b361950c84f7ad6a
4
+ data.tar.gz: 5393dfa5952b36216eb717a7b47c00ac8cc144f96815c60675f29ef68fa224be
5
5
  SHA512:
6
- metadata.gz: 4bee94b71cc6bb0e107c2f0408d88a6fada488868cdf4c25d005f5275f4ef212e1a75ea8212fea9a301daa703c0fb8849b0e9189a4a4e97cd7baadf702cae969
7
- data.tar.gz: 46afece761a21a62d9d7d018317d2ca74470fe2069028c7af4d767ae2ced93a56ce2dd90da91c2a5c48fd3d0c7dbc830aa6bbe958fbe6d2f9b87df2d66036be2
6
+ metadata.gz: 9d195381e9231e60d11f5dc9b2f814e69a4478e79e2fd45185e459b3866c6e626c22c1b4c0741e63984f8ee68939589acd1ec1077dc91ae93032a9a46392d83d
7
+ data.tar.gz: 287a8b6257429192fb76706750eecbe1a1eade21a0d55da9dce3f8f586bd31a9d8da6ba45e845382d93f172ca20aaf54904db26a38b0afdbe0b518059fe86932
@@ -13,7 +13,7 @@ module Maxima
13
13
  Command.new()
14
14
  .with_options(
15
15
  use_fast_arrays: true,
16
- float: true,
16
+ float: true
17
17
  ).tap do |c|
18
18
  yield c
19
19
  end.output_variables(*v)
@@ -34,10 +34,10 @@ module Maxima
34
34
 
35
35
  def let(variable_or_variables, expression, *unary_operations, **unary_operations_options)
36
36
  add_variable(variable_or_variables)
37
- expression = _apply_unary_operations(expression, *unary_operations, **unary_operations_options)
37
+
38
38
 
39
39
  variable = Maxima.mformat(variable_or_variables)
40
- expression = Maxima.mformat(expression)
40
+ expression = _apply_unary_operations(expression, *unary_operations, **unary_operations_options)
41
41
 
42
42
  _let(variable, expression)
43
43
  end
@@ -69,26 +69,28 @@ module Maxima
69
69
 
70
70
  [
71
71
  unary_operations.map { |unary_operation| "#{unary_operation}(" },
72
- expression,
72
+ Maxima.mformat(expression),
73
73
  ")" * unary_operations.count
74
74
  ].join()
75
75
  end
76
76
 
77
77
  OPTIONS = {
78
78
  float: -> (enabled) { "float: #{enabled}" },
79
- use_fast_arrays: -> (enabled) { "use_fast_arrays: #{enabled}" }
79
+ use_fast_arrays: -> (enabled) { "use_fast_arrays: #{enabled}" },
80
+ real_only: -> (enabled) { "realonly: #{enabled}" }
80
81
  }
81
82
 
82
83
  def options_commands()
83
84
  [].each do |commands|
84
85
  @options.each do |option, configuration|
86
+ # warn that option is not applicable
85
87
  next unless OPTIONS[option]
86
88
  commands << OPTIONS[option].call(configuration)
87
89
  end
88
90
  end
89
91
  end
90
92
 
91
- def run_shell(extract_variables = nil, debug: ENV["DEBUG"])
93
+ def run_shell(extract_variables = nil, debug: ENV["DEBUG_RB_MAXIMA"])
92
94
  inputs = [*dependencies_input, *options_commands(), *@commands]
93
95
 
94
96
  inputs << "grind(#{extract_variables.join(', ')})" if extract_variables
@@ -14,7 +14,7 @@ module Maxima
14
14
  end
15
15
 
16
16
  WHITESPACE_OR_PARENTHESES_REGEX = /(\s|\(|\))/
17
- COMPLEX_REGEX = /(-?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?)((?:\*)?(?:%)?i)?/
17
+ COMPLEX_REGEX = /(-?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?)((?:\*)?(?:%)?\s*i)?|((?:\s*)-?%i)/
18
18
 
19
19
  def self.parse(maxima_output)
20
20
  maxima_output = maxima_output.to_s unless maxima_output.is_a?(String)
@@ -23,8 +23,10 @@ module Maxima
23
23
  real = 0
24
24
  imaginary = 0
25
25
 
26
- string.scan(COMPLEX_REGEX) do |(float, is_imaginary)|
27
- if is_imaginary
26
+ string.scan(COMPLEX_REGEX) do |(float, is_imaginary, is_just_imaginary_one)|
27
+ if is_just_imaginary_one
28
+ imaginary += (is_just_imaginary_one.start_with? "-") ? -1 : 1
29
+ elsif is_imaginary
28
30
  imaginary += float.to_f
29
31
  else
30
32
  real += float.to_f
@@ -38,15 +40,6 @@ module Maxima
38
40
  end
39
41
  end
40
42
 
41
- def pretty_to_s
42
- if real == 0
43
- "#{@imaginary}i"
44
- else
45
- operand = @real.positive? ? '+' : '-'
46
- "#{@imaginary}i #{operand} #{@real.abs}"
47
- end
48
- end
49
-
50
43
  def to_maxima_input
51
44
  return "#{@imaginary} * %i" if real == 0
52
45
 
@@ -59,7 +52,6 @@ module Maxima
59
52
  end
60
53
 
61
54
  # Definitions are somewhat contrived and not per se mathematically accurate.
62
-
63
55
  def positive?
64
56
  !negative?
65
57
  end
@@ -3,22 +3,23 @@ module Maxima
3
3
  Maxima::Function.new("((#{Maxima.mformat(e_1)}) #{bin_op} (#{Maxima.mformat(e_2)}))")
4
4
  end
5
5
 
6
- def self.cobyla(minimize_function, variables, constraint_function, initial_guess)
7
- Command.output(variables => Unit) do |c|
8
- initial_guess = mformat(initial_guess)
6
+ ## Alternative minimization function that needs it's own testing etc.
7
+ # def self.cobyla(minimize_function, variables, constraint_function, initial_guess)
8
+ # Command.output(variables => Unit) do |c|
9
+ # initial_guess = mformat(initial_guess)
9
10
 
10
- c.dependencies << "cobyla"
11
+ # c.dependencies << "cobyla"
11
12
 
12
- c.let :output, "fmin_cobyla(#{minimize_function}, #{mformat(variables)}, #{initial_guess},constraints = #{constraint_function})"
13
- c.let variables, "sublis(output[1], #{variables})"
14
- end
15
- end
13
+ # c.let :output, "fmin_cobyla(#{minimize_function}, #{mformat(variables)}, #{initial_guess},constraints = #{constraint_function})"
14
+ # c.let variables, "sublis(output[1], #{variables})"
15
+ # end
16
+ # end
16
17
 
17
- def self.interpolate(array)
18
- Command.output(lagrangian: Function) do |c|
18
+ def self.lagrangian_interpolation(array)
19
+ Command.output(function: Function) do |c|
19
20
  c.dependencies << "interpol"
20
- c.let :array, array.to_a
21
- c.let_simplified :lagrangian, "lagrange(array)"
21
+ c.let :array, array
22
+ c.let_simplified :function, "lagrange(array)"
22
23
  end
23
24
  end
24
25
 
@@ -90,6 +91,7 @@ module Maxima
90
91
 
91
92
  def self.lagrangian(minimize_function, variables, constraint_function, initial_guess, iterations: 5)
92
93
  Command.output(variables => Unit) do |c|
94
+ variables = mformat(variables)
93
95
  initial_guess = mformat(initial_guess)
94
96
  constraint_function = mformat(Array(constraint_function))
95
97
  optional_args = mformat(niter: iterations)
@@ -104,34 +106,39 @@ module Maxima
104
106
 
105
107
  def self.mformat(variable)
106
108
  case variable
107
- when String, Symbol
109
+ when String
108
110
  variable # the only truly `valid` input is a string
109
111
  when Hash
110
112
  variable.map do |key,value|
111
113
  "#{mformat(key)} = #{mformat(value)}"
112
114
  end.join(", ")
113
- when Array
114
- "[" + variable.map { |v| mformat(v) }.join(",") + "]"
115
+ when Array, Histogram
116
+ "[" + variable.to_a.map { |v| mformat(v) }.join(",") + "]"
115
117
  when ::Complex
116
- mformat Complex.new(variable, variable.real, variable.imag)
118
+ mformat Complex.new(variable.real, variable.imag)
117
119
  when Numeric
118
120
  mformat Float(variable)
119
121
  when Complex, Float, Function
120
122
  variable.to_maxima_input
121
123
  when nil
122
124
  throw :cannot_format_nil
123
- else
124
- variable
125
+ else # Symbol, etc.
126
+ variable.to_s
125
127
  end
126
128
  end
127
129
 
128
130
  def self.solve_polynomial(equations, variables_to_solve_for, ignore: nil, real_only: false)
131
+ variables_to_solve_for = Array(variables_to_solve_for)
132
+ equations = Array(equations)
133
+
134
+ throw :all_equations_must_include_equivalence unless equations.all? { |e| e.include?("=") }
135
+
129
136
  # regex match extract
130
- output = Command
131
- .with_options(real_only: real_only)
132
- .output(output: Unit) do |c|
133
- variables = mformat(Array(variables_to_solve_for))
134
- equations = mformat(Array(equations))
137
+ output = Command.output(output: Unit) do |c|
138
+ c.with_options(real_only: real_only)
139
+
140
+ variables = mformat(variables_to_solve_for)
141
+ equations = mformat(equations)
135
142
 
136
143
  c.let :output, "algsys(#{equations},#{variables})"
137
144
  end
@@ -17,10 +17,8 @@ module Maxima
17
17
 
18
18
  def <=>(other)
19
19
  case other
20
- when ::Float
21
- @real <=> other
22
- when Float
23
- @real <=> other.real
20
+ when ::Float, Float
21
+ @real <=> other.to_f
24
22
  else
25
23
  -1
26
24
  end
@@ -40,32 +40,34 @@ module Maxima
40
40
  @points = points
41
41
  end
42
42
 
43
+ def to_a
44
+ @points
45
+ end
46
+
47
+ # PDF
43
48
  def to_percentage()
44
49
  @to_percentage ||=
45
50
  begin
46
- sum = points.sum(&:x)
51
+ sum = points.sum(&:last)
47
52
  Histogram.new(
48
- points.map do |point|
49
- Point.new(
50
- point.x,
51
- point.y.fdiv(sum)
52
- )
53
+ points.map do |(x,y)|
54
+ [
55
+ x,
56
+ y.fdiv(sum)
57
+ ]
53
58
  end
54
59
  )
55
60
  end
56
61
  end
57
62
 
58
- def to_a
59
- @points
60
- end
61
-
63
+ # literal CDF
62
64
  def integral()
63
65
  begin
64
66
  sum = 0
65
67
  Histogram.new(
66
- points.map do |(one, two)|
67
- sum += two
68
- [one, sum]
68
+ points.map do |(x, y)|
69
+ sum += y
70
+ [x, sum]
69
71
  end
70
72
  )
71
73
  end
@@ -74,5 +76,14 @@ module Maxima
74
76
  def to_gnu_plot()
75
77
  [*points.map(&:to_a).transpose, w: "points"]
76
78
  end
79
+
80
+ def <=>(other)
81
+ case other
82
+ when Array, Histogram
83
+ self.to_a <=> other.to_a
84
+ else
85
+ -1
86
+ end
87
+ end
77
88
  end
78
89
  end
@@ -3,6 +3,7 @@ module Maxima
3
3
 
4
4
  def self.fit(histogram, degrees)
5
5
  throw :degrees_must_be_zero_or_positive if degrees < 0
6
+ degrees += 1
6
7
 
7
8
  equation_string, variables = polynomial_equation(degrees)
8
9
  results = Maxima.lsquares_estimation(histogram.to_a, [:x, :y], "y = #{equation_string}", variables)
@@ -13,37 +14,32 @@ module Maxima
13
14
  end
14
15
 
15
16
  {
16
- function: Maxima::Function.new(equation_string),
17
+ function: Maxima::Function.new(equation_string).simplified,
17
18
  mse: mse
18
19
  }
19
20
  end
20
21
 
21
- def self.fit_function(min, max, x: "x")
22
- Enumerator.new do |e|
23
- (min..max).each do |degrees|
24
- equation_string, variables = polynomial_equation(degrees, f_of: x)
25
- e.<<(equation_string, variables)
26
- end
27
- end
28
- end
29
-
30
22
  def self.polynomial_equation(degrees, f_of: "x")
31
- constant_variables = degrees.times.map { |degree| "c#{degree}" }
23
+ polynomials = []
24
+ constant_variables = []
25
+
26
+ degrees.times.each do |degree|
27
+ constant_variable = "c#{degree}"
28
+ constant_variables << constant_variable
32
29
 
33
- free_polynomial = constant_variables.each do |degree|
34
30
  case degree
35
31
  when 0
36
- "(#{constant_variable})"
32
+ polynomials << "(#{constant_variable})"
37
33
  when 1
38
- "(#{constant_variable}) * #{f_of}"
34
+ polynomials << "(#{constant_variable}) * #{f_of}"
39
35
  else
40
- "(#{constant_variable}) * #{f_of} ^ #{degree}"
36
+ polynomials << "(#{constant_variable}) * #{f_of} ^ #{degree}"
41
37
  end
42
38
  end
43
39
 
44
40
  [
45
- free_polynomial.join(" + "),
46
- variables
41
+ polynomials.join(" + "),
42
+ constant_variables
47
43
  ]
48
44
  end
49
45
  end
@@ -3,22 +3,22 @@ module Maxima
3
3
 
4
4
  attr_accessor :numerator, :denominator
5
5
 
6
- def initialize(string, numerator, denominator, title = nil)
7
- super(string, title)
6
+ def initialize(numerator, denominator, **options)
7
+ super(**options)
8
8
  @numerator = numerator
9
9
  @denominator = denominator
10
10
  end
11
11
 
12
- REGEX = /(\d+)\/(\d+)/
13
- def self.parse(input_string)
14
- _, numerator, denominator = REGEX.match(input_string).to_a
12
+ REGEX = /\s*(\d+)\s*\/\s*(\d+)\s*/
13
+ def self.parse(maxima_output)
14
+ _, numerator, denominator = REGEX.match(maxima_output).to_a
15
15
 
16
- return nil if numerator.nil? || denominator.nil?
16
+ return if numerator.nil? || denominator.nil?
17
17
 
18
18
  if numerator == 0
19
- Float.new(input_string, 0)
19
+ Float.new(0, maxima_output: maxima_output)
20
20
  else
21
- Rational.new(input_string, numerator.to_i, denominator.to_i)
21
+ Rational.new(numerator.to_f, denominator.to_f, maxima_output: maxima_output)
22
22
  end
23
23
  rescue StandardError
24
24
  nil
@@ -35,5 +35,14 @@ module Maxima
35
35
  def to_f
36
36
  @to_f ||= numerator.fdiv(denominator)
37
37
  end
38
+
39
+ def <=>(other)
40
+ case other
41
+ when ::Float, ::Rational, Float, Rational
42
+ self.to_f <=> other.to_f
43
+ else
44
+ -1
45
+ end
46
+ end
38
47
  end
39
48
  end
@@ -37,10 +37,6 @@ module Maxima
37
37
  end
38
38
  end
39
39
 
40
- # def absolute_difference(other)
41
- # Function.new("abs(#{self - other})")
42
- # end
43
-
44
40
  def simplified
45
41
  @simplified ||= through_maxima(:expand)
46
42
  end
@@ -52,10 +48,6 @@ module Maxima
52
48
  end[:itself]
53
49
  end
54
50
 
55
- def simplified!
56
- simplified.to_s
57
- end
58
-
59
51
  def to_maxima_input
60
52
  to_s
61
53
  end
@@ -1,3 +1,3 @@
1
1
  module Maxima
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rb_maxima
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Ackerman
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-18 00:00:00.000000000 Z
11
+ date: 2018-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -139,9 +139,9 @@ dependencies:
139
139
  description: Ruby developers have, for as long as I can remember, had a disheveled
140
140
  heap of scientific and mathematical libraries - many of which operate in pure ruby
141
141
  code. Given a problem we either kludge together some cobbled mess or turn to Python/R/etc.
142
- And to this I say no more! `rb_maxima` allows a ruby developer to directly leverage
142
+ And to this I say no more! rb_maxima allows a ruby developer to directly leverage
143
143
  the unbridled power of the open source, lisp powered, computer algebra system that
144
- is `Maxima`!
144
+ is Maxima!
145
145
  email:
146
146
  - daniel.joseph.ackerman@gmail.com
147
147
  executables: []
@@ -161,7 +161,7 @@ files:
161
161
  - lib/maxima/rational.rb
162
162
  - lib/maxima/unit.rb
163
163
  - lib/maxima/version.rb
164
- homepage:
164
+ homepage: https://github.com/Danieth/rb_maxima
165
165
  licenses:
166
166
  - MIT
167
167
  metadata: {}
@@ -184,6 +184,6 @@ rubyforge_project:
184
184
  rubygems_version: 2.7.3
185
185
  signing_key:
186
186
  specification_version: 4
187
- summary: A gem that allows for mathematical calculations using the open source `Maxima`
187
+ summary: A gem that allows for mathematical calculations using the open source Maxima
188
188
  library!
189
189
  test_files: []