Using the SymEngine gem


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.

In [1]:
require 'symengine'
Out[1]:
true

Go ahead and try a function

In [2]:
SymEngine.ascii_art
 _____           _____         _
|   __|_ _ _____|   __|___ ___|_|___ ___
|__   | | |     |   __|   | . | |   | -_|
|_____|_  |_|_|_|_____|_|_|_  |_|_|_|___|
      |___|               |___|          

or create a variable

In [3]:
basic = SymEngine::Basic.new
Out[3]:
#<SymEngine::Basic:0x00000001e95290>

This shows that we have successfully loaded the module.

SymEngine::Symbol

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.

In [25]:
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

In [26]:
e = (x-y)*(x**y/z)
e.to_s
Out[26]:
"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.

In [5]:
x.class
Out[5]:
SymEngine::Symbol
In [6]:
x.is_a? SymEngine::Basic
Out[6]:
true

Now that we have an expression, we would like to see it's expanded form using #expand

In [27]:
f = e.expand()
f.to_s
Out[27]:
"x**(1 + y)/z - x**y*y/z"

Or check if two expressions are same

In [8]:
f == - (x**y*y/z) + (x**y*x/z)
Out[8]:
true

But e and f are not equal since they are only mathematically equal, not structurally

In [9]:
e == f
Out[9]:
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.

In [10]:
f.free_symbols
Out[10]:
#<Set: {#<SymEngine::Basic:0x00000001f0ca70>, #<SymEngine::Basic:0x00000001f0ca48>, #<SymEngine::Basic:0x00000001f0ca20>}>

Let us use #map method to see the elements of the Set.

In [11]:
f.free_symbols.map { |x| x.to_s }
Out[11]:
["x", "y", "z"]

#args returns the terms of the expression,

In [12]:
f.args.map { |x| x.to_s }
Out[12]:
["-x**y*y/z", "x**(1 + y)/z"]

or if it is a single term it breaks down the elements

In [13]:
f.args[0].args.map { |k| k.to_s }
Out[13]:
["-1", "x**y", "y", "z**(-1)"]

SymEngine::Integer

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.

In [14]:
a = SymEngine::Integer.new(12)
b = SymEngine::Integer.new(64)
a**b
Out[14]:
1168422057627266461843148138873451659428421700563161428957815831003136

And yes it can support numbers of arbitrarily large length.

In [15]:
(a**x).to_s
Out[15]:
"12**x"

SymEngine::Rational

You can also make objects of class SymEngine::Rational that is the SymEngine counterpart for Rationals in Ruby.

In [16]:
c = Rational('2/3')
d = SymEngine::Rational.new(c)
Out[16]:
2/3

Like any other Basic object arithmetic operations can be done on this one too.

In [17]:
(a-d).to_s
Out[17]:
"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 Integers. Let us say you already have Integer/Rational object. Even then you can use them without having to create a new SymEngine object.

In [18]:
k = (1 / (x * y) - x * y + 2) * (c + x * y) # c is a Rational object, not SymEngine::Rational
k.to_s
Out[18]:
"(2/3 + x*y)*(2 + 1/(x*y) - x*y)"

As you can see, ruby kernel Integers and Rationals interoperate seamlessly with the SymEngine objects.

In [19]:
k.expand.to_s
Out[19]:
"7/3 + (2/3)*1/(x*y) + (4/3)*x*y - x**2*y**2"