\documentclass{llncs}

\begin{document}

\title{YACAS: A Do-it-yourself Symbolic Algebra Environment}

\author{Ayal Zwi Pinkus\inst{1} \and Serge Winitzki\inst{2}}
\institute{3e Oosterparkstraat 109-III,
Amsterdam, The Netherlands
(\email{apinkus@xs4all.nl})
\and
Tufts Institute of Cosmology, Department of Physics and Astronomy, Tufts University, Medford, MA 02155, USA
(\email{serge@cosmos.phy.tufts.edu})
}

\maketitle

\begin{abstract}
We describe the design and implementation of \textsc{Yacas}, a free computer
algebra system currently under development.  The system consists of a core
interpreter and a library of scripts that implement symbolic algebra
functionality.  The interpreter provides a high-level weakly typed functional
language designed for quick prototyping of computer algebra algorithms, but the
language is suitable for all kinds of symbolic manipulation. It supports
conditional term rewriting of symbolic expression trees, closures (pure
functions) and delayed evaluation, dynamic creation of transformation rules,
arbitrary-precision numerical calculations, and flexible user-defined syntax
using infix notation.  The library of scripts currently provides basic
numerical and symbolic functionality. The main advantages of \textsc{Yacas} are: free (GPL)
software; a
flexible and easy-to-use programming language with a comfortable and adjustable
syntax; cross-platform portability and small resource requirements; and extensibility.
\end{abstract}

%%% Start of main text


\section{Introduction}
\textsc{Yacas} is a computer algebra system (CAS) which has been in development since the beginning of 1999.
The goal was to make a small system that allows to easily prototype and
research symbolic mathematics algorithms. A secondary future goal is to evolve
\textsc{Yacas} into a full-blown general purpose CAS.


\textsc{Yacas} is primarily intended to be a research tool for easy
exploration and prototyping of algorithms of symbolic
computation.  The main advantage of \textsc{Yacas}, besides being free software, is its rich and flexible
scripting language. The language is closely related to LISP \cite{WH89} but has
a recursive descent infix grammar parser \cite{ASU86}, includes expression
transformation (term rewriting), and supports defining infix operators at run time
similarly to Prolog \cite{B86}.


The \textsc{Yacas} language interpreter comes with a library of scripts that implement a set of computer algebra features. The \textsc{Yacas} script library
is in active development and at the present stage does not offer the rich functionality of
industrial-strength systems such as \textsc{Mathematica} or \textsc{Maple}.
Extensive
implementation of algorithms of symbolic computation is one of the future
development goals.

\textsc{Yacas} handles input and output in plain ASCII,
either interactively or in batch mode. (A graphical interface is under development.) There is also an optional plugin mechanism
whereby external libraries can be linked into the system to provide extra
functionality.

\textsc{Yacas} currently (at version 1.0.49) consists of approximately 22000 lines of C++ code and  13000 lines of 
script code, with 170 functions defined in the C++ kernel and 600 functions
defined in the script library.


\section{Basic design}

\textsc{Yacas} consists of a ``core engine" (kernel), which is an interpreter
for the \textsc{Yacas} scripting language, and a library of script code.

The
\textsc{Yacas} engine has been implemented in a subset of C++ which is
supported by almost all C++ compilers.
The design goals for \textsc{Yacas} core engine are: portability,
self-containment (no dependence on extra libraries or packages), ease of
implementing algorithms, code transparency, and flexibility. The \textsc{Yacas}
system as a whole falls into the ``prototype/hacker" rather than into the
``axiom/algebraic" category, according to the terminology of Fateman
\cite{F90}. There are relatively few specific design decisions related to
mathematics, but instead the emphasis is made on extensibility.


The kernel offers sufficiently rich but basic functionality through a limited
number of core functions. This core functionality includes substitutions and
rewriting of symbolic expression trees, an infix syntax parser, and arbitrary
precision numerics. The kernel does not contain any definitions of symbolic
mathematical operations and tries to be as general and free as possible of
predefined notions or policies in the domain of symbolic computation.

The plugin inter-operability mechanism allows to extend the \textsc{Yacas} kernel or to use external libraries, e.g.~GUI toolkits or implementations of special-purpose algorithms. A simple C++ API is provided for writing ``stubs'' that make external functions appear in \textsc{Yacas} as new core functions. Plugins are on the same footing as the \textsc{Yacas} kernel and can in principle manipulate all \textsc{Yacas} internal structures. Plugins can be compiled either statically or dynamically as shared libraries to be loaded at runtime from \textsc{Yacas} scripts. 

%
The script library contains declarations of transformation rules and of function
syntax (prefix, infix etc.). The intention is that almost all symbolic manipulation algorithms and definitions
of mathematical functions should be held in the script library and not in the kernel. 
%The only exception so far is for a very small number of mathematical or utility functions that are frequently used; they are compiled into the core for speed.


For example, the mathematical operator ``\texttt{+}" is an infix operator defined in the
library scripts. To the kernel, this operator is on the same footing as any
other function defined by the user and can be redefined. The \textsc{Yacas} kernel
itself does not store any properties for this operator. Instead it relies
entirely on the script library to provide transformation rules for manipulating
expressions involving the operator ``\texttt{+}". In this way, the kernel does not need
to anticipate all possible meanings of the operator ``\texttt{+}" that users might need
in their calculations.

\section{Advantages of \textsc{Yacas}}

The ``policy-free" kernel design means that \textsc{Yacas} is highly configurable
through its scripting language. It is possible to create an entirely different
symbolic manipulation engine based on the same kernel, with different syntax
and different naming  conventions, by loading another script library. An example of the flexibility of the
\textsc{Yacas} system is a sample script \texttt{wordproblems.ys}. It contains
a set of rule definitions that make \textsc{Yacas} recognize simple English
sentences, e.g.~``Tom has 3 chairs" or ``Jane gave an apple to Jill", as
valid \textsc{Yacas} expressions. \textsc{Yacas} can then ``evaluate" these
sentences to \texttt{True} or \texttt{False} according to the semantics of the
described situation.

This example illustrates a major advantage of \textsc{Yacas}---the flexibility of its syntax. Although \textsc{Yacas}
works internally as a LISP-style interpreter,
the script language has a C-like grammar. Infix operators
defined in the script library or by the user may contain non-alphabetic characters such as ``\texttt{=}"
or ``\verb|#|". This means that the user works with a comfortable and adjustable infix syntax,
rather than a LISP-style syntax. The user can introduce such syntactic
conventions as are most convenient for a given problem.
For example, algebraic expressions can be entered
in the familiar infix form such as
%
\begin{quote}\small\begin{verbatim}
(x+1)^2 - (y-2*z)/(y+3) + Sin(x*Pi/2)
\end{verbatim}\end{quote}
%
The same syntactic flexibility is available for defining transformation rules.
Suppose the user needs to reorder expressions containing non-commutative
operators of quantum theory. It takes about 20
rules to define an infix operation ``\texttt{**}"
to express non-commutative multiplication with the appropriate commutation
relations and to automatically reorder all expressions involving both non-commutative and commutative factors. Thanks to the \textsc{Yacas} parser,
the rules for the new operator can be written in a simple and readable form. Once the operator
``\texttt{**}" is defined, the rules that express distributivity of this operation
with respect to addition may look like this:
\begin{quote}\small\begin{verbatim}
15 # (_x + _y) ** _z <-- x ** z + y ** z;
15 # _z ** (_x + _y) <-- z ** x + z ** y;
\end{verbatim}\end{quote}
Here, ``\verb|15 #|" is a specification of the rule precedence, ``\verb|_x|" denotes a
pattern-matching variable \texttt{x} and the expression to the right of ``\texttt{<--}" is to be
substituted instead of a matched expression on the left hand side.

Rule-based and functional programming can be freely combined with procedural
programming style when the latter is more appropriate for reasons of efficiency or simplicity. Standard
patterns of procedural programming, such as subroutines that return values,
with code blocks and temporary local variables, the familiar \texttt{if} /
\texttt{else} construct and \texttt{For()},
\texttt{ForEach()} loop functions are defined in the script library for the
convenience of users. The \textsc{Yacas} interpreter is sufficiently powerful
to define these functions in the script library itself rather than in the
kernel. This power is fully given to the user, since the library scrips are on
the same footing as any user-defined code. Many library functions are intended
mainly as tools available to a \textsc{Yacas} user to make algorithm
implementation more comfortable.

% more advantages?
%

\section{The \textsc{Yacas} kernel functionality}

\textsc{Yacas} script is a functional language based on various ideas that
seemed useful for an implementation of a CAS: list-based data structures,
object properties, functional programming (\`{a} la LISP); term rewriting
\cite{BN98} with pattern matching somewhat along the lines of
\textsc{Mathematica}; user-defined infix operators \'{a} la PROLOG; delayed
evaluation of expressions; and arbitrary precision arithmetic. Garbage
collection is implemented through reference counting.


The kernel provides three basic data types: numbers, strings, and atoms and
two container types: list and static array (for speed). Additional container or data types (``generic objects'') can be made available through C++ plugins. Atoms are implemented
as strings that can be assigned values and evaluated. Boolean values are simply
atoms \texttt{True} and \texttt{False}. Hash tables, stacks, and
closures (pure functions) are implemented using nested lists. Kernel primitives are available for arbitrary
precision arithmetic, string and list manipulation, control flow, defining
transformation rules, and declaring function  syntax. Expression trees are
internally represented by nested lists. Expressions can be ``tagged" (assigned a
``property object" \`{a} la LISP).

The interpreter engine recursively evaluates expression trees according to
the transformation rules from the script library.
Evaluation proceeds from the leaves of the tree upwards. The engine tries to apply all existing rules to each subexpression, rewriting leaves or branches of the expression tree, until no more rules apply.
%
This type of semantic matching has been implemented in the past
(see, e.g., \cite{C86}). However, the \textsc{Yacas} language
includes some advanced features to create a more flexible and powerful term
rewriting system.

Rules have predicates that determine whether a
rule should be applied to an expression. Predicates can be any \textsc{Yacas}
expressions that evaluate to the atoms \texttt{True} or \texttt{False} and are typically
functions of pattern variables.

All rules are assigned a precedence value (a positive integer) and
rule matching is attempted in the order of precedence. (Thus \textsc{Yacas} provides somewhat better control
over the automatic recursion than e.g.~the pattern-matching system of \textsc{Mathematica}
which does not allow for rule precedence.)
% example
Using rule precedence and predicates, a
recursive implementation of the integer factorial function may look like this:
%
\begin{quote}\small\begin{verbatim}
10 # Factorial(0) <-- 1;
20 # Factorial(n_IsInteger) _ (n>0) <-- n*Factorial(n-1);
\end{verbatim}\end{quote}
%
The rules have precedence $10$ and $20$, therefore the first rule will be tried first and the recursion will stop when $n = 0$ is reached.

New rules can be defined dynamically as a side-effect of evaluation.
This means that there is no predefined ``ranking alphabet" of ``ground terms"
(in the terminology of \cite{TATA99}). It is possible to define a ``rule closure"
that defines rules depending on its arguments, or to erase rules. Thus, a
(read-only) \textsc{Yacas} script library does not actually represent a
fixed tree rewriting automaton; an implementation of machine learning is
possible.

%A \texttt{HoldArg()} primitive is provided to not evaluate certain arguments of certain functions before passing them on as parameters to these functions. The \texttt{Hold()} and \texttt{Eval()} primitives, similarly to LISP's \texttt{QUOTE} and \texttt{EVAL}, can be used to stop the recursive application of rules at a certain point and obtain an unevaluated expression, or to initiate evaluation of an expression which was previously held unevaluated.

The Knuth-Bendix termination algorithm \cite{KB70} is not used because rules in \textsc{Yacas} are not an expression of mathematical equivalence but a programming technique. Termination is the responsibility of the user who has complete control over the order of rule application.


\section{Current status}

Currently, the script library implements basic algorithms of computer algebra:
manipulation of polynomials and elementary functions, limits, derivatives and
(basic) symbolic integration, solution of (simple) equations, and some special-purpose
functions. (The primary sources of inspiration were the books \cite{K98}, \cite{GG99} and
\cite{B86}.) The system is free (GNU GPL) software and comes with ample documentation to facilitate cooperative development. The main Internet site for \textsc{Yacas} is \texttt{http://www.xs4all.nl/\homedir apinkus/}.

The main development platform is GNU/Linux, but \textsc{Yacas} runs also
under various Unix flavors,  Windows environments, Psion organizers (EPOC32),
Ipaq PDAs running the Linux kernel, BeOS, and Mac OS X. Creating an
executable for another platform (including embedded platforms) should not be
difficult.

In the future, \textsc{Yacas} is intended to grow into a general-purpose CAS as well as a repository and a testbed of algorithms.
In our opinion, \textsc{Yacas} is a promising research tool for exploring symbolic computation.

%%% End of main text

\begin{thebibliography}{TATW99}

\bibitem[ASU86]{ASU86} A. Aho, R. Sethi and J. Ullman, \emph{Compilers (Principles, Techniques and Tools)}, Addison-Wesley, 1986.


\bibitem[B86]{B86} I. Bratko, \emph{Prolog (Programming for Artificial Intelligence)}, Addison-Wesley, 1986.


\bibitem[BN98]{BN98} F. Baader and T. Nipkow, \emph{Term rewriting and all that}, Cambridge University Press, 1998.


\bibitem[C86]{C86} G. Cooperman, \emph{A semantic matcher for computer algebra}, in Proceedings of the symposium on symbolic and algebraic computation (1986), Waterloo, Ontario, Canada (ACM Press, NY).


\bibitem[F90]{F90} R. Fateman, \emph{On the design and construction of algebraic manipulation systems}, also published as: ACM Proceedings of the ISSAC-90, Tokyo, Japan.


\bibitem[GG99]{GG99} J. von zur Gathen and J. Gerhard, \emph{Modern Computer Algebra}, Cambridge University Press, 1999.


\bibitem[K98]{K98} D. E. Knuth, \emph{The Art of Computer Programming (Volume 2, Seminumerical Algorithms)}, Addison-Wesley, 1998.

\bibitem[KB70]{KB70} D. E. Knuth and P. B. Bendix, \emph{Simple word problems in universal algebras}, in \emph{Computational problems in abstract algebra}, ed.~J. Leech, p.~263, Pergamon Press, 1970.


%\bibitem[M98]{M98} See, for example, M. B. Monagan \emph{et al.}: \emph{Maple V programming guide,} Springer-Verlag, Berlin, 1998.


\bibitem[TATA99]{TATA99} H. Comon, M. Dauchet, R. Gilleron, F. Jacquemard, D. Lugiez, S. Tison, and M. Tommasi, \emph{Tree Automata Techniques and Applications}, 1999, online book: {\small \verb|http://www.grappa.univ-lille3.fr/tata|}


%\bibitem[W96]{W96} S. Wolfram, \emph{The Mathematica book}, Wolfram Media, Champain, 1996.


\bibitem[WH89]{WH89} P. Winston and B. Horn, \emph{LISP}, Addison-Wesley, 1989.


\end{thebibliography}

\end{document}
