Using Symengine or SymPy from C++

1,129 views
Skip to first unread message

ardi

unread,
Jan 16, 2017, 5:08:17 AM1/16/17
to symengine
Hi,

Searching the net, I found several questions similar to mine, but I didn't find any recommended procedure, or detailed steps for achieving it:

I'd like to use some of the SymPy functionality from my C++ programs. In particular, my current needs would be evaluating physics formulas with units (I mean variables have units) and solving linear and quadratic equations (also with units) and systems of linear equations, as well as converting the expressions to LaTeX syntax. These are my current needs, but in a mid-term future I foresee the need to also evaluate physics formulas that work with matrices and vectors, and differentiation/integration.

Should I use Symengine for this, or is it not finished yet for these tasks?

If the recommendation is to directly use SymPy 1.0, is there any C++ (or C) sample code that shows how to interface with SymPy by using a text-based interface? What I need is to be able to have a sort of command-line interface from C++, so that I have a function for sending a string to SymPy, and then get the SymPy result as either another string or a floating point number (if the result was a number). Of course I'd need that this interface keeps the SymPy session alive (so that variables/symbols created in previous commands are still alive).

I know Python has a C API, but, I'm guessing somebody must have needed this kind of SymPy interface from C++/C in the past, so reusing a well-tested C-based command-line interface would seem to be wiser than writing it from scratch.

Thanks a lot in advance!
 

Ondřej Čertík

unread,
Jan 16, 2017, 2:09:04 PM1/16/17
to symengine
Hi Ardi,

On Mon, Jan 16, 2017 at 3:04 AM, ardi <ardillas...@gmail.com> wrote:
> Hi,
>
> Searching the net, I found several questions similar to mine, but I didn't
> find any recommended procedure, or detailed steps for achieving it:
>
> I'd like to use some of the SymPy functionality from my C++ programs. In
> particular, my current needs would be evaluating physics formulas with units
> (I mean variables have units) and solving linear and quadratic equations
> (also with units) and systems of linear equations, as well as converting the
> expressions to LaTeX syntax. These are my current needs, but in a mid-term
> future I foresee the need to also evaluate physics formulas that work with
> matrices and vectors, and differentiation/integration.
>
> Should I use Symengine for this, or is it not finished yet for these tasks?

I think we do not have units support in SymEngine. We can solve linear systems:

https://github.com/symengine/symengine/blob/9a20615f493f071c778bd40ea42bbe7a278e0aec/symengine/matrix.h#L184

I think we don't have quadratic equations yet, but that's easy to
implement. We don't have a LaTeX output yet, but it's easy to add,
simlar to the StrPrinter:

https://github.com/symengine/symengine/blob/6f9ab96903c3f911d31f4e7f605def986a48996b/symengine/printer.h#L180

We have differentiation, matrices and vectors. We don't have integration yet.

>
> If the recommendation is to directly use SymPy 1.0, is there any C++ (or C)
> sample code that shows how to interface with SymPy by using a text-based
> interface? What I need is to be able to have a sort of command-line
> interface from C++, so that I have a function for sending a string to SymPy,
> and then get the SymPy result as either another string or a floating point
> number (if the result was a number). Of course I'd need that this interface
> keeps the SymPy session alive (so that variables/symbols created in previous
> commands are still alive).
>
> I know Python has a C API, but, I'm guessing somebody must have needed this
> kind of SymPy interface from C++/C in the past, so reusing a well-tested
> C-based command-line interface would seem to be wiser than writing it from
> scratch.

I would call SymPy just like any other Python code. You can use Cython
to do that. It's a bit pain, but doable.

What is your application? SymEngine can probably almost do what you
need, we are happy to implement the missing features.

Ondrej

>
> Thanks a lot in advance!
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "symengine" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to symengine+...@googlegroups.com.
> To post to this group, send email to syme...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/symengine/41555a54-0e5a-4e1c-b2b5-07c24d444c00%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

ardi

unread,
Jan 16, 2017, 9:18:41 PM1/16/17
to symengine
On Mon, Jan 16, 2017 at 20:09:04 (UTC+1), Ondřej Čertík wrote:
> Hi Ardi,
>
Thanks a lot for your reply, Ondrej.

My application is actually code fragments that generate the solutions of simple physics problems for teaching purposes (that's why I need LaTeX output).

BTW, I just thought that I might be able to use symengine in its current status if it has the following features:

1- Transforming an expression tree into a RPN (or similar) stack from which the client program can read the operations and the operands, in the proper order for evaluation.
2- Being able to store a custom pointer in each variable.

If these two features are supported, I could use symengine in this way:

- All values that have units will be a variable (even if they are constants with units, they'll be stored in a variable).
- All variables will be enriched with a pointer to a unit (I'm thinking in using the UDUNITS2 library because it's not copylefted and because it supports operations between units).
- symengine won't use the custom pointer to the unit, only my program knows the pointer meaning.
- All CAS tasks like equation solving, etc, will be performed by symengine because units won't be explicit (symengine will just see a variable called "Area" which doesn't seem to have units).
- When my program needs to numerically evaluate an expression, it will ask symengine to convert the expression to a RPN stack (or a similar representation), and my program will perform the evaluation on its own. When an operand is a variable, my program will understand the unit pointer, and will use the UDUNITS2 library for applying the operation to the operands units, so that the result is both a number and a UDUNITS2 unit.
- Maybe the stack might allow me to generate LaTeX output with units, by generating LaTeX output instead of computing the numerical evaluation.

So, can symengine transform to a RPN stack, and store custom client pointers in variables?

Thanks!



Isuru Fernando

unread,
Jan 16, 2017, 10:58:44 PM1/16/17
to symengine
Hi,

Units - One possible way to do this would be to create a custom numeric class inheriting from NumberWrapper. It would store a Number and a unit. 

class NumberWithUnit : public NumberWrapper
{
     RCP<const Number> num;
     UnitType unit;               // This can be a RCP<const Basic> if you want to use symengine or a pointer to a unittype in UDUNITS2
}

And then you can define the addition, subtraction, multiplication and division operators as follows.

For addition, subtraction,
1. If both operands are NumberWithUnit check that the units match. Add/subtract the numeric quantities using SymEngine. Resuting NumberWithUnit object would have the same unit
2. If only one of the operands is a NumberWithUnit, error

For multiplication, division
Consider the 2 cases separately and do the operation on the numeric quantity and the unit separately.

As the UnitType, you can use SymEngine or UDUNITS2 if you prefer it more. (Btw, if you use SymEngine as the UnitType, we would be happy to include the code in SymEngine itself.)


RPN stack

I'm not sure what your requirement is. SymEngine uses visitor pattern to implement most of the algorithms, so you can do anything yourself. 
SymEngine can create a C++ lambda function for you, see the lambda_double.h header. This would convert a symengine expression to a C++ lambda function and you can use it to evaluate the expression at different values of input variables.
I'd have to know more to answer your question.

Regards,

Isuru Fernando

--
You received this message because you are subscribed to the Google Groups "symengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to symengine+unsubscribe@googlegroups.com.

To post to this group, send email to syme...@googlegroups.com.

Isuru Fernando

unread,
Jan 16, 2017, 11:13:30 PM1/16/17
to symengine
On second thought, implementing units by having a class that keeps track of the unit and the SymEngine expression would be easier than keeping a pointer in SymEngine classes.

Regards,

Isuru Fernando

ardi

unread,
Jan 17, 2017, 6:00:22 AM1/17/17
to symengine
Thanks a lot for your comments, Isuru!

Regarding your "second thought", I just realized I was thinking with a C mindset rather than a C++ one :-) when I thought in "adding a pointer". IMHO, the easiest way is to write a derived class that holds the units information. Symengine will work with it flawlessly because it will understand the base class that it's derived from. And my "custom evaluator" can try to do a dynamic cast to my "NumberWithUnits". If the dynamic cast succeeds, then, voila, it's a number with units. Otherwise, it's a standard symengine object. The derived class can store the unit in the most convenient way, as an ID, a pointer, an object... whatever it's more convenient.

Regarding operations with units, I was thinking in the features offered by UDUNITS2, which has functions for operating with units, so my idea was to first check if the units of both operands can be converted to the units of one of them. If affirmative, convert both operands to the same unit, and then operate the numbers. If they cannot converted, try to operate the units anyway and, if it fails, then trigger an evaluation error. For example, the expression "2m + 5cm" would evaluate as "205cm" (or "2.05m", depending on what unit is given preference", the expression "6 km / 2 s" would evaluate as "3 km/s" (first we have tried to convert "km" to "s" or viceversa, it failed, so we operate them and it succeeded, getting "km/s", so we now operate the numbers and get "3 km/s").

BTW, what do you mean when you say to use symengine to implement the units? Are you thinking in defining the units as variables and operate symbolically with them? Or what exactly? Anyway, generic symbolic operation doesn't seem possible, because units could appear in any order in the result, for example, I'm guessing that symengine could evaluate "6*km/2*s" as "km*3/s", for example :-D

Also, I'm not sure because I didn't try, but from the SymPy units documentation, it seems that SymPy always favors non-prefixed units. I mean, in Sympy, what would "2cm + 25cm" return. From the docs I guess it would return "0.27m", but I would prefer to keep the operands units when possible (if the user is working with cm, the expected result would be "27cm" rather than "0.27m").

I keep thinking, thanks for your comments!!


To unsubscribe from this group and stop receiving emails from it, send an email to symengine+...@googlegroups.com.

To post to this group, send email to syme...@googlegroups.com.

ardi

unread,
Jan 17, 2017, 6:14:16 AM1/17/17
to symengine
Add-on: I might have some days for trying to implement units in symengine, using symengine objects. However, it's my first contact with the project. I've no idea about the class hierarchy, nor about how to perform symbolic operations with the engine. I come from Mathematica, I'm used to its syntax and workflow, but never used SymPy nor symengine.
Reply all
Reply to author
Forward
0 new messages