Mr.CAS —A minimalistic (pure) Ruby CAS for fast prototyping and code generation

There are Computer Algebra System (CAS) systems on the market with complete solutions for manipula-tionofanalyticalmodels.Butexportingamodelthatimplementsspecificalgorithmsonspecificplatforms, for target languages or for particular numerical library, is often a rigid procedure that requires manual post-processing. This work presents a Ruby library that exposes core CAS capabilities, i


Motivation and significance
Ruby [1] is a purely object-oriented scripting language designed in the mid-1990s by Yukihiro Matsumoto, internationally standardized since 2012 as ISO/IEC 30170.
With the advent of the Internet of Things, a compact version of the Ruby interpreter called mRuby (eMbedded Ruby) [2] was published on GitHub by Matsumoto, in 2014. The new interpreter is a lightweight implementation, aimed at both low power devices and personal computers, and complies with the standard [3]. mRuby has a completely new API, and it is designed to be embedded in complex projects as a front-end interface-for example, a numerical optimization suite may use mRuby for problem definition.
The Ruby code-base exposes a large set of utilities in core and standard libraries, that can be furthermore expanded through third party libraries, or gems. Among the large number of available gems, Ruby still lacks an Automatic and Symbolic Differentiation (ASD) [4] engine that handles basic computer algebra routines, compatible with all different Ruby interpreters.
Nowadays Ruby is mainly known thanks to the web-oriented Rails framework. Its expressiveness and elegance make it interesting for use in the scientific and technical field. An ASD-capable gem would prove a fundamental step in this direction, including the support for flexible code generation for high-level software-for example, IPOPT [5,6].
Mr.CAS 1 is a gem implemented in pure Ruby that supports symbolic differentiation (SD) and fundamentals computer algebra operations [7]. The library aims at supporting programmers in rapid prototyping of numerical algorithms and in code generation, for different target languages. It permits to implement mathematical models with a clean separation between actual mathematical formulations and conditioning rules for numerical instabilities, in order to support generation of code that is more robust with respect to issues that can be introduced by specific applications. As a long-term effort, it will become a complete open-source CAS system for the standard Ruby language.
Other CAS libraries for Ruby are available: Rucas, Symbolic: [8,9] milestone gems, yet at an early stage and with discontinued development status. Both offer basic simplification routines, although they lack differentiation. Symengine: [10] is a wrapper of the symengine C++ library. The back-end library is very complete, but it is compatible only with the vanilla C Ruby interpreter and has several dependencies. At best of Author knowledge, the gem does not work with Ruby 2.x interpreter.
In Section 2, Mr.CAS containers and tree structure are explained in detail and applied to basic CAS tasks. In Section 3, examples on how to use the library as code generator or as interface are described. Finally, the reasons behind the implementation and the long term desired impact are depicted in Section 4. All code listings are available at http://bit.ly/Mr_CAS_examples.

Software architecture
Mr.CAS is an object oriented ASD gem that supports computer algebra routines such as simplifications and substitutions.
When gem is required, it overloads methods of Fixnum and Float classes, making them compatible with fundamental symbolic classes.
Each symbolic expression (or operation) is the instance of an object, that inherits from a common virtual ancestor: CAS :: Op.
An operation encapsulates sub-operations recursively, building a tree, that is the mathematical equivalent of function composition: When a new operation is created, it is appended to the tree. The number of branches are determined by the parent container class of the current symbolic function. There are three possible containers: CAS :: Op single sub-tree operation-e.g. sin(·). CAS :: BinaryOp dual sub-tree operation-e.g. exponent x ythat inherits from CAS :: Op. CAS :: NaryOp operation with arbitrary number of sub-treee.g. sum x 1 + · · · + x N -that inherits from CAS :: Op. Fig. 1 contains a graphical representation of a expression tree. The different kind of containers allows to introduce some properties-i.e. associativity and commutativity for sums and multiplications [11]. Each container exposes the sub-tree as instance properties. Basic containers interfaces and inheritances are shown in Fig. 2. For a complete overview of all classes and inheritance, please refer to software documentation.
The terminal leaves of the graph are the classes CAS :: Constant, CAS :: Variable and CAS :: Function. The first models a simple numerical value, while the second represents an independent variable, that can be used to perform derivatives and evaluations, and the latter is a prototype of implicit functions. Those leaves exemplify only real scalar expressions, with definition of complex, vectorial, and matricial extensions as milestones for the next major release.
Simplifications are not executed automatically, after differentiation. Each node of the tree knows rules for simplify itself, and rules are called recursively, exactly like ASD. Simplifications that require a heuristic expansion of the sub-graph-i.e. some trigonometric identities-are not defined for now, but can be easily achieved through substitutions, as shown in Listing 2.

Listing 2: Simplification example
x, y = CAS :: vars 'x', 'y' # creates two variables f = CAS.log( CAS.sin( y ) ) # symbolic expression f.subs y => CAS.asin(CAS.exp(x)) # performs substitution f. simplify # simplifies expression # => x The tree is numerically evaluated when the independent variables values are provided in a feed dictionary. The graph is reduced recursively to a single numeric value, as shown in Listing 3.
Listing 3: Tree evaluation example Symbolic expressions can be used to create comparative expressions, that are stored in special container classes, modeled by the ancestor CAS :: Condition-for example, f (·) ≥ g(·). This allow the definition of piecewise functions, in CAS :: Piecewise. Internally, max(·) and min(·) functions are declared as operations that inherits from CAS :: Piecewise-for example, max(f (·), g(·)). Usage is shown in Listing 4.

Meta-programming and code-generation
Mr.CAS is developed explicitly for metaprogramming and code generation. Expressions can be exported as source code or used as Code generation should be flexible enough to export expression trees in a user's target language. Generation methods for common languages are included in specific plugins. Users can furthermore expand exporting capabilities by writing specific exportation rules, overriding method for existing plugin, or designing their own exporter, like the one shown in Listing 6:

Code generation as C library
This example shows how a user of Mr.CAS can export a mathematical model as a C library. The c-opt plugin implements advanced features such as code optimization and generation of libraries.
The library example implements the model: where the expression g(x) belongs to a external object, declared as g_impl, which interface is described in g_impl.h header. What should be noted is the corpus of the exported code: the intermediate operation x y is evaluated once, even if appears twice in Eq. (3). The C function that implements f (x, y) is declared with the token f_impl. The exporter uses as default type double for variables and function returned values. Library created by CLib contains the code shown in Listing 9.
Listing 7: Calling optimized-C exporter for library generation # Model x, y = CAS.vars :x, :y g = CAS. declare :g, x f = x ** y + g * CAS.log(CAS.sin(x ** y)) # Code Generation g. c_name = 'g_impl ' # g token CAS :: CLib. create " example " do include_local " g_impl " # g header implements_as " f_impl " , f # token for f end The function g(x) models the following operation: and may suffer from catastrophic numerical cancellation [13] when the x value is considerably greater than a. The user may decide to specialize code generation rules for this particular expression, stabilizing it through rationalization. Without modifying the actual model, g(x) the rationalization for differences of square roots 3 is inserted into the exportation rules, as in Listing 10. The rules are valid only for the current user script. For more insight about __to_c and __to_c_impl, refer to the software manual.
It should be noted the separation between the model, which does not contain stabilization, and the code generation rule. For this particular case, the code generation rule in Listing 10 overloads the predefined one, in order to obtain the conditioned code. Obviously, the user can decide to apply directly the conditioning on the model itself, but this may change the calculus behavior in further manipulation.

Using the module as interface
As example, an implementation of an algorithm that estimates the order of convergence for trapezoidal integration scheme [14] is provided, using the symbolic differentiation as interface.
Given a function f (x), the trapezoidal rule for primitive estimation for the interval [a, b] is: with h = (b − a)/n, where n mediates the step size of the integration. When exact primitive F (x) is known, approximation error is: The error has an asymptotic expansion of the form: 3 I.e.: where p is the convergence order. Using a different value for n, for example 2 n, the ratio (8) takes the approximate vale: E [2 n] ) . (8) The Listings 13 and 14 contain the implementation of the described procedure using the proposed gem and the well known Python [15] library SymPy [16].

ODE solver with Taylor's series
In this example, a solving step for a specific ordinary differential equation (ODE) using Taylor's series method [17] is derived. Given an ODE in the form: the integration step with order n has the form: where it is possible to substitute Eq. (9): For this algorithm, three methods are defined. The first evaluates the factorial, the second evaluates the list of required derivatives, and the third returns the integration step in a symbolic form. The result of the third method is transformed in a C function. In this particular case, the ODE is y ′ = xy. For the resulting C code of

Impact
Mr.CAS is a midpoint between a CAS and an ASD library. It allows one to manipulate expressions while maintaining the complete control on how the code is exported. Each rule is overloaded and applied run-time, without the need of compilation. Each user's model may include the mathematical description, code generation rules and high level logic that should be intrinsic to such a rule-for example, exporting a Hessian as pattern instead of matrix.
Our research group is including Mr.CAS in a solver for optimal control problem with indirect methods, as interface for problems description [18].
As a long term ambitious impact, this library will become a complete CAS for Ruby language, filling the empty space reported by SciRuby for symbolic math engines.

Conclusions
This work presents a pure Ruby library that implements a minimalistics CAS with automatic and symbolic differentiation that is aimed at code generation and meta-programming. Although at an early developing stage, Mr.CAS has promising feature, some of them shown in Section 3. Also, this is the only gem that implements symbolic manipulation for this language.  CAS :: CLib. create " g_impl " do define " PARAM_A () " , 1.0 # Arbitrary value for PARAM_A define " M_PI " , Math ::Pi implements_as " g_impl " , g end puts g # => (( sqrt ((x + PARAM_A ())) -sqrt(x)) + sqrtπ(( + x)))  df = coeff (f, n) y = $y for i in 0... df.size y = y + (( $h ** (i + 1))/( fact(i + 1)) * df[i]) end return y. simplify end # Example function for the integrator f = $x * $y # Exporting a C function clib = CAS :: CLib. create " taylor " do implements_as " taylor_step " , taylor (f, 4) end Language features and lack of dependencies simplify the use of the module as interface, extending model definition capabilities for numerical algorithms. All core functionalities and basic mathematics are defined, with the plan to include more features in next releases. Reopening a class guarantees a liquid behavior, in which users are free to modify core methods at their needs.
Library is published in rubygems.org repository and versioned on github.com, under MIT license. It can be included easily in projects and in inline interpreter, or installed as a standalone gem.