class CAS::Op
___ _ _ / __|___ _ _| |_ __ _(_)_ _ ___ _ _ ___
| (__/ _ \ ' \ _/ _` | | ' / -_) '_(_-<
\___\___/_||_\__\__,_|_|_||_\___|_| /__/
___ / _ \ _ __
| (_) | '_ \
\___/| .__/ |_|
Attributes
Argument of the operation
Public Class Methods
Initializes the simplification dictionary (one for each class)
-
returns: `Hash` with simplification dictionary
# File lib/operators/op.rb, line 234 def self.init_simplify_dict @simplify_dict = { } end
Initialize a new empty operation container. This is a virtual class and the other must inherit from this basic container. Some methods raise a `CAS::CASError` if called. The input element is a Numric, to create a constant. `CAS::Op` specifies operations with a single variable
* **argument**: `Numeric` to be converted in `CAS::Constant` or `CAS::Op` child operation * **returns**: `CAS::Op` instance
# File lib/operators/op.rb, line 46 def initialize(x) if x.is_a? Numeric x = Op.numeric_to_const x end CAS::Help.assert(x, CAS::Op) @x = x end
# File lib/operators/op.rb, line 55 def self.numeric_to_const(x) if CAS::NumericToConst[x] return CAS::NumericToConst[x] else return CAS::const x end end
Returns an element of a
# File lib/operators/op.rb, line 239 def self.simplify_dict(k) @simplify_dict.keys.each do |op| return @simplify_dict[op] if op.simplify == k.simplify end return nil end
Public Instance Methods
Disequality operator, the standard operator is overloaded :warning: this operates on the graph, not on the math See `CAS::equal`, etc.
* **argument**: `CAS::Op` to be tested against * **returns**: `FalseClass` if equal, `TrueClass` if differs
# File lib/operators/op.rb, line 274 def !=(op) not self.==(op) end
Returns a product of two `CAS::Op`s
* **argument**: `CAS::Op` tree * **returns**: `CAS::Op` new object
# File lib/operators/op.rb, line 182 def *(op) CAS::Prod.new [self, op] end
Returns the power of two `CAS::Op`s
* **argument**: `CAS::Op` tree * **returns**: `CAS::Op` new object
# File lib/operators/op.rb, line 198 def **(op) CAS.pow(self, op) end
Returns a sum of two `CAS::Op`s
* **argument**: `CAS::Op` tree * **returns**: `CAS::Op` new object
# File lib/operators/op.rb, line 166 def +(op) CAS::Sum.new [self, op] end
Returns a difference of two `CAS::Op`s
* **argument**: `CAS::Op` tree * **returns**: `CAS::Op` new object
# File lib/operators/op.rb, line 174 def -(op) CAS::Diff.new self, op end
Unary operator for inversion of a `CAS::Op`
* **returns**: `CAS::Op` new object
# File lib/operators/op.rb, line 205 def -@ CAS.invert(self) end
Returns a division of two `CAS::Op`s
* **argument**: `CAS::Op` tree * **returns**: `CAS::Op` new object
# File lib/operators/op.rb, line 190 def /(op) CAS::Div.new self, op end
Equality operator, the standard operator is overloaded :warning: this operates on the graph, not on the math See `CAS::equal`, etc.
* **argument**: `CAS::Op` to be tested against * **returns**: `TrueClass` if equal, `FalseClass` if differs
# File lib/operators/op.rb, line 259 def ==(op) # CAS::Help.assert(op, CAS::Op) if op.is_a? CAS::Op return false if op.is_a? CAS::BinaryOp return (self.class == op.class and @x == op.x) end false end
Returns a list of all `CAS::Variable`s of the current tree
* **returns**: `Array` of `CAS::Variable`s
# File lib/operators/op.rb, line 303 def args @x.args.uniq end
Evaluates the proc against a given context. It is like having a snapshot of the tree transformed in a callable object. Obviously **if the tree changes, the generated proc does notchanges**. The proc takes as input a feed dictionary in which each variable is identified through the `CAS::Variable#name` key.
The proc is evaluated in the context devined by the input `Binding` object If `nil` is passed, the `eval` will run in this local context
* **argument**: `Binding` or `NilClass` that is the context of the Ruby VM * **returns**: `Proc` object with a single argument as an `Hash`
# File lib/operators/op.rb, line 289 def as_proc(bind=nil) args_ext = self.args.map { |e| "#{e} = fd[\"#{e}\"];" } code = "Proc.new do |fd|; #{args_ext.join " "} #{self.to_code}; end" if bind # All objects have eval value, we bind when not nil # CAS::Help.assert(bind, Binding) bind.eval(code) else eval(code) end end
Call resolves the operation tree in a `Numeric` (if `Fixnum`) or `Float` (depends upon promotions). As input, it requires an hash with `CAS::Variable` or `CAS::Variable#name` as keys, and a `Numeric` as a value
“` ruby x, y = CAS::vars
:x, :y f = (x ** 2) + (y ** 2) f.call({x => 1, y => 2}) # => 2 “`
* **argument**: `Hash` with feed dictionary * **returns**: `Numeric`
# File lib/operators/op.rb, line 112 def call(f) CAS::Help.assert(f, Hash) @x.call(f) end
Return the dependencies of the operation. Requires a `CAS::Variable` and it is one of the recursve method (implicit tree resolution)
* **argument**: `CAS::Variable` instance * **returns**: `TrueClass` if depends, `FalseClass` if not
# File lib/operators/op.rb, line 68 def depend?(v) CAS::Help.assert(v, CAS::Op) @x.depend? v end
Return the derivative of the operation using the chain rule The input is a `CAS::Op` because it can handle derivatives with respect to functions. E.g.:
“`
f(x) = (ln(x))**2 g(x) = ln(x) d f(x) ------ = 2 ln(x) d g(x)
“`
* **argument**: `CAS::Op` object of the derivative * **returns**: `CAS::Op` a derivated object, or `CAS::Zero` for constants
# File lib/operators/op.rb, line 89 def diff(v) CAS::Help.assert(v, CAS::Op) if @x.depend? v return @x.diff(v) end CAS::Zero end
Return the local Graphviz node of the tree
* **returns**: `String` of local Graphiz node
# File lib/Mr.CAS/graphviz.rb, line 42 def dot_graph cls = "#{self.class.to_s.gsub("CAS::", "")}_#{self.object_id}" "#{cls} -> #{@x.dot_graph}\n" end
Shortcut for creating equality condition.
* **argument**: `CAS::Op` ther element of the condition * **returns**: `CAS::Equal` new instance
# File lib/functions/fnc-conditions.rb, line 344 def equal(v) CAS.equal(self, v) end
Shortcut for creating greater kind condition.
* **argument**: `CAS::Op` ther element of the condition * **returns**: `CAS::Greater` new instance
# File lib/functions/fnc-conditions.rb, line 352 def greater(v) CAS.greater(self, v) end
Shortcut for creating a greater equal kind condition.
* **argument**: `CAS::Op` ther element of the condition * **returns**: `CAS::GreaterEqual` new instance
# File lib/functions/fnc-conditions.rb, line 368 def greater_equal(v) CAS.greater_equal(self, v) end
Inspector for the current object
* **returns**: `String`
# File lib/operators/op.rb, line 249 def inspect "#{self.class}(#{@x.inspect})" end
Shortcut for creating a new box condition. It requires limits and type:
* **argument**: `CAS::Constant` lower limit * **argument**: `CAs::Constant` upper limit * **argument**: `Symbol` of condition type it can be: - `:closed` for `CAs::BoxConditionClosed` - `:open` for `CAs::BoxConditionOpen` - `:upper_closed` for `CAs::BoxConditionUpperClosed` - `:lower_closed` for `CAs::BoxConditionLowerClosed` * **returns**: `CAS::BoxCondition` new instance
# File lib/functions/fnc-box-conditions.rb, line 338 def limit(a, b, type=:closed) return CAS::box(self, a, b, type) end
Simplification callback. It simplify the subgraph of each node until all possible simplification are performed (thus the execution time is not deterministic).
* **returns**: `CAS::Op` simplified version
# File lib/operators/op.rb, line 214 def simplify hash = @x.to_s @x = @x.simplify while @x.to_s != hash hash = @x.to_s @x = @x.simplify end end
Simplify dictionary performs a dictionary simplification that is the class variable `@simplify_dict`
* **returns**: `CAS::Op` self
# File lib/operators/op.rb, line 227 def simplify_dictionary self.class.simplify_dict(@x) || self end
Shortcut for creating a smaller kind condition.
* **argument**: `CAS::Op` ther element of the condition * **returns**: `CAS::Smaller` new instance
# File lib/functions/fnc-conditions.rb, line 360 def smaller(v) CAS.smaller(self, v) end
Shortcut for creating a smaller equal kind condition.
* **argument**: `CAS::Op` ther element of the condition * **returns**: `CAS::SmallerEqual` new instance
# File lib/functions/fnc-conditions.rb, line 376 def smaller_equal(v) CAS.smaller_equal(self, v) end
Perform substitution of a part of the graph using a data table:
“` ruby x, y = CAS::vars
:x, :y f = (x ** 2) + (y ** 2) puts f # => (x^2) + (y^2) puts f.subs({x => CAS::ln(y)
}) # => (ln(y)^2) + (y^2) “`
* **argument**: `Hash` with substitution table * **returns**: `CAS::Op` (`self`) with substitution performed
# File lib/operators/op.rb, line 131 def subs(dt) CAS::Help.assert(dt, Hash) sub = dt.keys.select { |e| e == @x }[0] if sub if dt[sub].is_a? CAS::Op @x = dt[sub] elsif dt[sub].is_a? Numeric @x = CAS::const dt[sub] else raise CAS::CASError, "Impossible subs. Received a #{dt[@x].class} = #{dt[@x]}" end else @x.subs(dt) end return self end
# File lib/Mr.CAS/c-opt.rb, line 229 def to_c_lib(name) CAS::Help.assert(name, String) [CAS::C_PLUGIN.write_header(self, name), CAS::C_PLUGIN.write_source(self, name)] end
Convert expression to code (internal, for `CAS::Op#to_proc` method)
* **returns**: `String` that represent Ruby code to be parsed in `CAS::Op#to_proc`
# File lib/operators/op.rb, line 158 def to_code "#{@x}" end
Convert expression to string
* **returns**: `String` to print on screen
# File lib/operators/op.rb, line 151 def to_s "#{@x}" end