SymEngine is a module in the extensions, and the classes are a part of it. So first you fire up the interpreter and load the file
*Note :* You will need to have libsymengine
(SymEngine C++ library) installed to be able to use the SymEngine extension with Ruby. libsymengine
installation instructions and other prerequisite installation instructions can be found here.
require 'symengine'
true
Go ahead and try a function
SymEngine.ascii_art
_____ _____ _ | __|_ _ _____| __|___ ___|_|___ ___ |__ | | | | __| | . | | | -_| |_____|_ |_|_|_|_____|_|_|_ |_|_|_|___| |___| |___|
or create a variable
basic = SymEngine::Basic.new
#<SymEngine::Basic:0x00000001e95290>
This shows that we have successfully loaded the module.
Just like there are variables like x, y, and z in a mathematical expression or equation, we have SymEngine::Symbol
in SymEngine to represent them. To use a variable, first we need to make a SymEngine::Symbol
object with the string we are going to represent the variable with.
puts x = SymEngine::Symbol.new("x")
puts y = SymEngine::Symbol.new("y")
puts z = SymEngine::Symbol.new("z")
x y z
Then we can construct expressions out of them
e = (x-y)*(x**y/z)
e.to_s
"x**y*(x - y)/z"
In SymEngine, every object is an instance of Basic or its subclasses. So, even an instance of SymEngine::Symbol
is a Basic object.
x.class
SymEngine::Symbol
x.is_a? SymEngine::Basic
true
Now that we have an expression, we would like to see it's expanded form using #expand
f = e.expand()
f.to_s
"x**(1 + y)/z - x**y*y/z"
Or check if two expressions are same
f == - (x**y*y/z) + (x**y*x/z)
true
But e
and f
are not equal since they are only mathematically equal, not structurally
e == f
false
Let us suppose you want to know what variables/symbols your expression has. You can do that with the #free_symbols
method. The method #free_symbols
returns a Set
of the symbols that are in an expression.
f.free_symbols
#<Set: {#<SymEngine::Basic:0x00000001f0ca70>, #<SymEngine::Basic:0x00000001f0ca48>, #<SymEngine::Basic:0x00000001f0ca20>}>
Let us use #map
method to see the elements of the Set
.
f.free_symbols.map { |x| x.to_s }
["x", "y", "z"]
#args
returns the terms of the expression,
f.args.map { |x| x.to_s }
["-x**y*y/z", "x**(1 + y)/z"]
or if it is a single term it breaks down the elements
f.args[0].args.map { |k| k.to_s }
["-1", "x**y", "y", "z**(-1)"]
You can make objects of class SymEngine::Integer
. It's like regular Integer
in ruby kernel, except it can do all the operations a Basic
object can like arithmetic operations, etc.
a = SymEngine::Integer.new(12)
b = SymEngine::Integer.new(64)
a**b
And yes it can support numbers of arbitrarily large length.
(a**x).to_s
"12**x"
You can also make objects of class SymEngine::Rational
that is the SymEngine counterpart for Rationals
in Ruby.
c = Rational('2/3')
d = SymEngine::Rational.new(c)
Like any other Basic
object arithmetic operations can be done on this one too.
(a-d).to_s
"34/3"
You need not create an instance of SymEngine::Integer
or SymEngine::Rational
, every time you want to use them in an expression that uses many Integer
s. Let us say you already have Integer
/Rational
object. Even then you can use them without having to create a new SymEngine
object.
k = (1 / (x * y) - x * y + 2) * (c + x * y) # c is a Rational object, not SymEngine::Rational
k.to_s
"(2/3 + x*y)*(2 + 1/(x*y) - x*y)"
As you can see, ruby kernel Integer
s and Rational
s interoperate seamlessly with the SymEngine
objects.
k.expand.to_s
"7/3 + (2/3)*1/(x*y) + (4/3)*x*y - x**2*y**2"