symbolic 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -14,7 +14,7 @@ Currently I've implemented only naive optimizations to simplify math expressions
14
14
  x = var :name => 'x'
15
15
  y = var :name => 'y'
16
16
 
17
- f = symbolic { (4 - 2*(-x) + y*(-1.0))*x - 0*y + 0 - 2 }
17
+ f = (4 - 2*(-x) + y*(-1.0))*x - 0*y + 0 - 2
18
18
  puts f # => (4+2*x-y)*x-2
19
19
 
20
20
  p f.detailed_operations # => {"+"=>1, "-"=>2, "*"=>2}
@@ -26,7 +26,7 @@ Currently I've implemented only naive optimizations to simplify math expressions
26
26
  puts f.value # => 6
27
27
 
28
28
 
29
- g = symbolic { Math.cos(y) }
29
+ g = Symbolic::Math.cos(y)
30
30
  puts g # => cos(y)
31
31
  y.value = 0
32
32
  puts g.value # => 1.0
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "symbolic"
8
- gem.version = '0.2.0'
8
+ gem.version = '0.2.1'
9
9
  gem.summary = 'Symbolic math for ruby'
10
10
  gem.description = %Q{Symbolic math can be really helpful if you want to simplify some giant equation or if you don't want to get a performance hit re-evaluating big math expressions every time when few variables change.}
11
11
  gem.email = "ravwar@gmail.com"
data/lib/symbolic.rb CHANGED
@@ -1,57 +1,58 @@
1
+ Symbolic = Module.new
2
+
3
+ require 'symbolic/operation'
4
+ require 'symbolic/operation/unary'
5
+ require 'symbolic/operation/unary/minus'
6
+ require 'symbolic/operation/binary'
7
+ require 'symbolic/operation/binary/addition'
8
+ require 'symbolic/operation/binary/subtraction'
9
+ require 'symbolic/operation/binary/multiplication'
10
+ require 'symbolic/operation/binary/division'
11
+ require 'symbolic/operation/binary/exponentiation'
12
+
13
+ require 'symbolic/coerced'
14
+ require 'symbolic/variable'
15
+ require 'symbolic/function'
16
+ require 'symbolic/math'
17
+
18
+ require 'extensions/kernel'
19
+ require 'extensions/numeric'
20
+ require 'extensions/matrix'
21
+
1
22
  module Symbolic
2
- def self.operations
3
- { :* => :multiplication,
4
- :+ => :addition,
5
- :- => :subtraction,
6
- :/ => :division }
23
+ def -@
24
+ Operation::Unary::Minus.for self
7
25
  end
8
26
 
9
- operations.each do |sign, name|
10
- method = <<-CODE
11
- def #{sign}(value)
12
- Optimization.#{name} self, value
13
- end
14
- CODE
15
- class_eval method, __FILE__, __LINE__
27
+ def +@
28
+ self
16
29
  end
17
30
 
18
- def self.math_operations
19
- [:cos, :sin]
31
+ def +(var)
32
+ Operation::Binary::Addition.for self, var
20
33
  end
21
34
 
22
- def -@
23
- UnaryMinus.create self
35
+ def -(var)
36
+ Operation::Binary::Subtraction.for self, var
24
37
  end
25
38
 
26
- def +@
27
- self
39
+ def *(var)
40
+ Operation::Binary::Multiplication.for self, var
28
41
  end
29
42
 
30
- def coerce(numeric)
31
- return Coerced.new(self), numeric
43
+ def /(var)
44
+ Operation::Binary::Division.for self, var
45
+ end
46
+
47
+ def **(var)
48
+ Operation::Binary::Exponentiation.for self, var
32
49
  end
33
50
 
34
- def undefined?
35
- !value
51
+ def coerce(numeric)
52
+ return Coerced.new(self), numeric
36
53
  end
37
54
 
38
55
  def operations
39
56
  detailed_operations.values.inject(0) {|sum,it| sum + it }
40
57
  end
41
- end
42
-
43
- require 'symbolic/coerced'
44
- require 'symbolic/optimization'
45
- require 'symbolic/optimization/base'
46
- require 'symbolic/optimization/addition'
47
- require 'symbolic/optimization/subtraction'
48
- require 'symbolic/optimization/multiplication'
49
- require 'symbolic/optimization/division'
50
- require 'symbolic/variable'
51
- require 'symbolic/expression'
52
- require 'symbolic/method'
53
- require 'symbolic/unary_minus'
54
-
55
- require 'extensions/kernel'
56
- require 'extensions/numeric'
57
- require 'extensions/matrix'
58
+ end
@@ -4,13 +4,24 @@ module Symbolic
4
4
  @symbolic = symbolic
5
5
  end
6
6
 
7
- Symbolic.operations.each do |sign, name|
8
- method = <<-CODE
9
- def #{sign}(numeric)
10
- Optimization.#{name} numeric, @symbolic
11
- end
12
- CODE
13
- class_eval method, __FILE__, __LINE__
14
- end # Symbolic.operations.each
15
- end # Coerced
16
- end # Symbolic
7
+ def +(numeric)
8
+ Operation::Binary::Addition.for numeric, @symbolic
9
+ end
10
+
11
+ def -(numeric)
12
+ Operation::Binary::Subtraction.for numeric, @symbolic
13
+ end
14
+
15
+ def *(numeric)
16
+ Operation::Binary::Multiplication.for numeric, @symbolic
17
+ end
18
+
19
+ def /(numeric)
20
+ Operation::Binary::Division.for numeric, @symbolic
21
+ end
22
+
23
+ def **(numeric)
24
+ Operation::Binary::Exponentiation.for numeric, @symbolic
25
+ end
26
+ end
27
+ end
@@ -1,7 +1,6 @@
1
1
  module Symbolic
2
- class Method
2
+ class Function
3
3
  include Symbolic
4
-
5
4
  def initialize(variable, operation)
6
5
  @variable, @operation = variable, operation
7
6
  end
@@ -0,0 +1,9 @@
1
+ module Symbolic::Math
2
+ def self.cos(argument)
3
+ Symbolic::Function.new argument, :cos
4
+ end
5
+
6
+ def self.sin(argument)
7
+ Symbolic::Function.new argument, :sin
8
+ end
9
+ end
@@ -0,0 +1,48 @@
1
+ class Symbolic::Operation
2
+ include Symbolic
3
+
4
+ def self.for(*args)
5
+ simplify(*args) || new(*args)
6
+ end
7
+
8
+ def self.negative?(var)
9
+ var.is_a?(Unary::Minus) || (var.is_a?(Numeric) && var < 0)
10
+ end
11
+
12
+ private
13
+
14
+ def operation(expression)
15
+ case expression
16
+ when Unary::Minus then :unary_minus
17
+ when Binary::Addition then :addition
18
+ when Binary::Subtraction then :subtraction
19
+ when Binary::Multiplication then :multiplication
20
+ when Binary::Division then :division
21
+ when Symbolic::Variable then :variable
22
+ end
23
+ end
24
+
25
+ def unary_minus?(expression)
26
+ operation(expression) == :unary_minus
27
+ end
28
+
29
+ def addition?(expression)
30
+ operation(expression) == :addition
31
+ end
32
+
33
+ def subtraction?(expression)
34
+ operation(expression) == :subtraction
35
+ end
36
+
37
+ def multiplication?(expression)
38
+ operation(expression) == :multiplication
39
+ end
40
+
41
+ def division?(expression)
42
+ operation(expression) == :division
43
+ end
44
+
45
+ def variable?(expression)
46
+ operation(expession) == :variable
47
+ end
48
+ end
@@ -0,0 +1,64 @@
1
+ class Symbolic::Operation::Binary < Symbolic::Operation
2
+ def self.simplify(var1, var2)
3
+ simplify_first_arg(var1, var2) || simplify_second_arg(var1, var2)
4
+ end
5
+
6
+ def self.symmetric
7
+ def self.simplify(var1, var2)
8
+ simplify_first_arg(var1, var2) || simplify_first_arg(var2, var1)
9
+ end
10
+
11
+ def ==(object)
12
+ (object.class == self.class) &&
13
+ ((object.var1 == @var1 && object.var2 == @var2) || (object.var1 == @var2 && object.var2 == @var1))
14
+ end
15
+ end
16
+
17
+ def self.brackets_for(*operations)
18
+ def brackets(var)
19
+ operations.include?(operation var) ? "(#{var})" : var.to_s
20
+ end
21
+ end
22
+
23
+ def initialize(var1, var2)
24
+ @var1, @var2 = var1, var2
25
+ end
26
+
27
+ def variables
28
+ @var1.variables | @var2.variables
29
+ end
30
+
31
+ def undefined_variables
32
+ variables.select {|it| it.value.nil? }
33
+ end
34
+
35
+ def value
36
+ @var1.value.send sign, @var2.value if undefined_variables.empty?
37
+ end
38
+
39
+ def detailed_operations
40
+ operations_of(@var1).tap {|it| it.merge!(operations_of @var2)[sign] += 1 }
41
+ end
42
+
43
+ def to_s
44
+ "#{brackets @var1}#{sign}#{brackets @var2}"
45
+ end
46
+
47
+ def ==(object)
48
+ (object.class == self.class) && (object.var1 == @var1 && object.var2 == @var2)
49
+ end
50
+
51
+ protected
52
+
53
+ attr_reader :var1, :var2
54
+
55
+ private
56
+
57
+ def operations_of(var)
58
+ var.is_a?(Symbolic) ? var.detailed_operations : Hash.new(0)
59
+ end
60
+
61
+ def brackets(var)
62
+ var.to_s
63
+ end
64
+ end
@@ -0,0 +1,15 @@
1
+ class Symbolic::Operation::Binary::Addition < Symbolic::Operation::Binary
2
+ symmetric
3
+
4
+ def self.simplify_first_arg(var1, var2)
5
+ if var1 == 0
6
+ var2
7
+ elsif negative?(var1)
8
+ var2 - var1.abs
9
+ end
10
+ end
11
+
12
+ def sign
13
+ '+'
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ class Symbolic::Operation::Binary::Division < Symbolic::Operation::Binary
2
+ brackets_for :unary_minus, :addition, :subtraction
3
+
4
+ def self.simplify_first_arg(var1, var2)
5
+ if var1 == 0
6
+ 0
7
+ elsif negative?(var1)
8
+ -(var1.abs / var2)
9
+ end
10
+ end
11
+
12
+ def self.simplify_second_arg(var1, var2)
13
+ if var2 == 1
14
+ var1
15
+ elsif negative?(var2)
16
+ -(var1 / var2.abs)
17
+ end
18
+ end
19
+
20
+ def sign
21
+ '/'
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ class Symbolic::Operation::Binary::Exponentiation < Symbolic::Operation::Binary
2
+ brackets_for :unary_minus, :addition, :subtraction, :multiplication, :division
3
+
4
+ def self.simplify_first_arg(var1, var2)
5
+ # add conditional for negative?(var1) and even or odd values of var2
6
+ if var1 == 0
7
+ 0
8
+ elsif var1 == 1
9
+ 1
10
+ end
11
+ end
12
+
13
+ def self.simplify_second_arg(var1, var2)
14
+ if var2 == 0
15
+ 1
16
+ elsif var2 == 1
17
+ var1
18
+ end
19
+ end
20
+
21
+ def sign
22
+ '**'
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ class Symbolic::Operation::Binary::Multiplication < Symbolic::Operation::Binary
2
+ symmetric
3
+ brackets_for :unary_minus, :addition, :subtraction
4
+
5
+ def self.simplify_first_arg(var1, var2)
6
+ if var1 == 0
7
+ 0
8
+ elsif var1 == 1
9
+ var2
10
+ elsif negative?(var1)
11
+ -(var1.abs * var2)
12
+ end
13
+ end
14
+
15
+ def sign
16
+ '*'
17
+ end
18
+
19
+ # def initialize(var1, var2)
20
+ # super
21
+ # coef, numerators, denominators = unite_factors factors_of(var1), factors_of(var2)
22
+ # end
23
+
24
+ def unite_factors(factors1, factors2)
25
+ c1, n1, d1 = factors1
26
+ c2, n2, d2 = factors2
27
+ return c1*c2, n1+n2, d1+d2
28
+ end
29
+
30
+ def factors_of(var)
31
+ case var
32
+ when Numeric
33
+ [var, [], []]
34
+ when Unary::Minus
35
+ unite_factors [-1, [], []], factors_of(var.abs)
36
+ when Binary::Multiplication
37
+ [var.coef, var.nominators, var.denominators]
38
+ else
39
+ [[], [var], []]
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,17 @@
1
+ class Symbolic::Operation::Binary::Subtraction < Symbolic::Operation::Binary
2
+ def self.simplify_first_arg(var1, var2)
3
+ -var2 if var1 == 0
4
+ end
5
+
6
+ def self.simplify_second_arg(var1, var2)
7
+ if var2 == 0
8
+ var1
9
+ elsif negative?(var2)
10
+ var1 + var2.abs
11
+ end
12
+ end
13
+
14
+ def sign
15
+ '-'
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ class Symbolic::Operation::Unary < Symbolic::Operation
2
+ def initialize(expression)
3
+ @expression = expression
4
+ end
5
+
6
+ def variables
7
+ @expression.variables
8
+ end
9
+
10
+ def undefined_variables
11
+ @expression.undefined_variables
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ class Symbolic::Operation
2
+ class Unary::Minus < Unary
3
+ def self.simplify(expression)
4
+ expression.abs if expression.is_a? Unary::Minus
5
+ end
6
+
7
+ def abs
8
+ # TODO: implement Symbolic#abs
9
+ @expression
10
+ end
11
+
12
+ def to_s
13
+ if [:variable, :multiplication, :division].include? operation(@expression)
14
+ "-#{@expression}"
15
+ else
16
+ "(-#{@expression})"
17
+ end
18
+ end
19
+
20
+ def value
21
+ -@expression.value if undefined_variables.empty?
22
+ end
23
+
24
+ def ==(object)
25
+ object.is_a?(Unary::Minus) && object.abs == @expression
26
+ end
27
+
28
+ def detailed_operations
29
+ @expression.detailed_operations.tap {|it| it['-@'] += 1}
30
+ end
31
+ end
32
+ end
@@ -1,7 +1,6 @@
1
1
  module Symbolic
2
2
  class Variable
3
3
  include Symbolic
4
-
5
4
  attr_accessor :name, :proc
6
5
  attr_writer :value
7
6
 
@@ -7,7 +7,15 @@ describe "Symbolic" do
7
7
  end
8
8
 
9
9
  def expression(string)
10
- eval string.gsub(/[a-z]+/, '@\0')
10
+ eval string.gsub(/[xy]/, '@\0')
11
+ end
12
+
13
+ def self.should_equal(conditions)
14
+ conditions.each do |non_optimized, optimized|
15
+ it non_optimized do
16
+ expression(non_optimized).should == expression(optimized)
17
+ end
18
+ end
11
19
  end
12
20
 
13
21
  describe "evaluation (x=1, y=2):" do
@@ -39,18 +47,13 @@ describe "Symbolic" do
39
47
  'y/2' => 1,
40
48
  'x/2.0' => 0.5,
41
49
  '-2/x' => -2,
42
- '4/(-y)' => -2
50
+ '4/(-y)' => -2,
51
+ 'x**2' => 1,
52
+ '4**y' => 16,
53
+ 'y**x' => 2
43
54
  end
44
55
 
45
56
  describe "optimization:" do
46
- def self.should_equal(conditions)
47
- conditions.each do |non_optimized, optimized|
48
- it non_optimized do
49
- expression(non_optimized).should == expression(optimized)
50
- end
51
- end
52
- end
53
-
54
57
  should_equal \
55
58
  '-(-x)' => 'x',
56
59
 
@@ -81,7 +84,22 @@ describe "Symbolic" do
81
84
  '-x*y' => '-(x*y)',
82
85
  '(-x)*(-y)' => 'x*y',
83
86
 
84
- 'x / 1' => 'x'
87
+ '0 / x' => '0',
88
+ 'x / 1' => 'x',
89
+
90
+ '0**x' => '0',
91
+ '1**x' => '1',
92
+ 'x**0' => '1',
93
+ 'x**1' => 'x'
94
+ end
95
+
96
+ describe 'general methods:' do
97
+ should_equal \
98
+ 'x.variables' => '[x]',
99
+ '(-(x-y)).variables' => '[x,y]',
100
+ '(x+y).undefined_variables' => '[]',
101
+ '(-x-4*y+5-y/x).detailed_operations' =>
102
+ '{"+" => 1, "-" => 2, "*" => 1, "/" => 1, "-@" => 1}'
85
103
  end
86
104
 
87
105
  describe "formulas" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: symbolic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - brainopia
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-07 00:00:00 +03:00
12
+ date: 2009-12-08 00:00:00 +03:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -39,15 +39,17 @@ files:
39
39
  - lib/extensions/numeric.rb
40
40
  - lib/symbolic.rb
41
41
  - lib/symbolic/coerced.rb
42
- - lib/symbolic/expression.rb
43
- - lib/symbolic/method.rb
44
- - lib/symbolic/optimization.rb
45
- - lib/symbolic/optimization/addition.rb
46
- - lib/symbolic/optimization/base.rb
47
- - lib/symbolic/optimization/division.rb
48
- - lib/symbolic/optimization/multiplication.rb
49
- - lib/symbolic/optimization/subtraction.rb
50
- - lib/symbolic/unary_minus.rb
42
+ - lib/symbolic/function.rb
43
+ - lib/symbolic/math.rb
44
+ - lib/symbolic/operation.rb
45
+ - lib/symbolic/operation/binary.rb
46
+ - lib/symbolic/operation/binary/addition.rb
47
+ - lib/symbolic/operation/binary/division.rb
48
+ - lib/symbolic/operation/binary/exponentiation.rb
49
+ - lib/symbolic/operation/binary/multiplication.rb
50
+ - lib/symbolic/operation/binary/subtraction.rb
51
+ - lib/symbolic/operation/unary.rb
52
+ - lib/symbolic/operation/unary/minus.rb
51
53
  - lib/symbolic/variable.rb
52
54
  - spec/spec.opts
53
55
  - spec/spec_helper.rb
@@ -1,66 +0,0 @@
1
- module Symbolic
2
- class Expression
3
- include Symbolic
4
-
5
- attr_reader :var1, :var2, :operation
6
-
7
- def initialize(var1, var2, operation)
8
- @var1, @var2, @operation = var1, var2, operation
9
- end
10
-
11
- def to_s
12
- "#{brackets @var1}#{@operation}#{brackets @var2}"
13
- end
14
-
15
- def plus?
16
- @operation == '+'
17
- end
18
-
19
- def minus?
20
- @operation == '-'
21
- end
22
-
23
- def multiply?
24
- @operation == '*'
25
- end
26
-
27
- def divide?
28
- @operation == '/'
29
- end
30
-
31
- def value
32
- @var1.value.send @operation, @var2.value if undefined_variables.empty?
33
- end
34
-
35
- def variables
36
- @var1.variables | @var2.variables
37
- end
38
-
39
- def undefined_variables
40
- variables.select &:undefined?
41
- end
42
-
43
- def ==(object)
44
- object.is_a?(Expression) && (object.operation == @operation) &&
45
- ((object.var1 == @var1 && object.var2 == @var2) || ((plus? || multiply?) && (object.var1 == @var2 && object.var2 == @var1)))
46
- end
47
-
48
- def detailed_operations
49
- operations_of(@var1).tap {|it| it.merge!(operations_of @var2)[@operation] += 1 }
50
- end
51
-
52
- private
53
-
54
- def brackets(var)
55
- brackets_conditional(var) ? "(#{var})" : var.to_s
56
- end
57
-
58
- def brackets_conditional(var)
59
- %w(* /).include?(@operation) && (var.is_a?(UnaryMinus) || var.is_a?(Expression) && (var.plus? || var.minus?))
60
- end
61
-
62
- def operations_of(var)
63
- var.is_a?(Symbolic) ? var.detailed_operations : Hash.new(0)
64
- end
65
- end
66
- end
@@ -1,12 +0,0 @@
1
- module Symbolic
2
- module Optimization
3
- Symbolic.operations.each do |operation_sign, operation_name|
4
- method = <<-CODE
5
- def #{operation_name}(var1, var2)
6
- #{operation_name.to_s.capitalize}.optimize(var1, var2) || Expression.new(var1, var2, '#{operation_sign}')
7
- end
8
- CODE
9
- instance_eval method, __FILE__, __LINE__
10
- end
11
- end
12
- end
@@ -1,15 +0,0 @@
1
- module Symbolic::Optimization::Addition
2
- extend Symbolic::Optimization::Base
3
-
4
- def self.optimize_first_arg(var1, var2)
5
- if var1 == 0
6
- var2
7
- elsif negative?(var1)
8
- var2 - var1.abs
9
- end
10
- end
11
-
12
- def self.optimize_second_arg(var1, var2)
13
- optimize_first_arg var2, var1
14
- end
15
- end
@@ -1,9 +0,0 @@
1
- module Symbolic::Optimization::Base
2
- def optimize(var1, var2)
3
- optimize_first_arg(var1, var2) || optimize_second_arg(var1, var2)
4
- end
5
-
6
- def negative?(var)
7
- var.is_a?(Symbolic::UnaryMinus) || (var.is_a?(Numeric) && var < 0)
8
- end
9
- end
@@ -1,19 +0,0 @@
1
- module Symbolic::Optimization::Division
2
- extend Symbolic::Optimization::Base
3
-
4
- def self.optimize_first_arg(var1, var2)
5
- if var1 == 0
6
- 0
7
- elsif negative?(var1)
8
- -(var1.abs / var2)
9
- end
10
- end
11
-
12
- def self.optimize_second_arg(var1, var2)
13
- if var2 == 1
14
- var1
15
- elsif negative?(var2)
16
- -(var1 / var2.abs)
17
- end
18
- end
19
- end
@@ -1,17 +0,0 @@
1
- module Symbolic::Optimization::Multiplication
2
- extend Symbolic::Optimization::Base
3
-
4
- def self.optimize_first_arg(var1, var2)
5
- if var1 == 0
6
- 0
7
- elsif var1 == 1
8
- var2
9
- elsif negative?(var1)
10
- -(var1.abs * var2)
11
- end
12
- end
13
-
14
- def self.optimize_second_arg(var1, var2)
15
- optimize_first_arg var2, var1
16
- end
17
- end
@@ -1,15 +0,0 @@
1
- module Symbolic::Optimization::Subtraction
2
- extend Symbolic::Optimization::Base
3
-
4
- def self.optimize_first_arg(var1, var2)
5
- -var2 if var1 == 0
6
- end
7
-
8
- def self.optimize_second_arg(var1, var2)
9
- if var2 == 0
10
- var1
11
- elsif negative?(var2)
12
- var1 + var2.abs
13
- end
14
- end
15
- end
@@ -1,46 +0,0 @@
1
- module Symbolic
2
- class UnaryMinus
3
- include Symbolic
4
-
5
- def self.create(var)
6
- var.is_a?(UnaryMinus) ? var.abs : new(var)
7
- end
8
-
9
- def initialize(variable)
10
- @variable = variable
11
- end
12
-
13
- def to_s
14
- if @variable.is_a? Variable
15
- "-#{@variable}"
16
- else
17
- "(-#{@variable})"
18
- end
19
- end
20
-
21
- def abs
22
- # TODO: add a common method for Symbolic which will point to an instance of Abs(magnitude) class
23
- @variable
24
- end
25
-
26
- def value
27
- -@variable.value if undefined_variables.empty?
28
- end
29
-
30
- def variables
31
- @variable.variables
32
- end
33
-
34
- def undefined_variables
35
- @variable.undefined_variables
36
- end
37
-
38
- def ==(object)
39
- object.is_a?(UnaryMinus) && object.abs == @variable
40
- end
41
-
42
- def detailed_operations
43
- @variable.detailed_operations.tap {|it| it['-@'] += 1}
44
- end
45
- end
46
- end