These are chat archives for symengine/symengine
@certik: As to series in Sage there are two implementations used: GiNaC and one based on polynomials (flint). The first supports expansion of most symbolic function expressions but is buggy; the second is fast but does not support symbolic functions. I proposed some fixes to the first but met with disinterest. However, the situation with SymPy is ridiculous as well:
In : %time _ = (1/(1-X)).series(n=100) CPU times: user 3.06 s, sys: 8 ms, total: 3.06 s Wall time: 3.06 s
So, this is what motivates me with symengine series expansion.
As to your design decisions I can't put my finger on any flaw. With series you want both lazy and indexed generation. I'm not sure how sparse the usual series really is, certainly not sparse if in one variable? The speed of series expansion of expressions would be independent from the kind of polynomial used, but the speed of manipulation would be affected. Note the above example is about expansion.
In : from sympy.polys.ring_series import * In : %time _ = rs_series(1/(1-x), x, 100) CPU times: user 4 ms, sys: 0 ns, total: 4 ms Wall time: 4.13 ms
rs_series? I only have
_from_listin SymPy git master.
In : from symengine import var In : var('f w x y z') Out: (f, w, x, y, z) In : %time _ = rs_series(1/(1-x), x, 100) ... GeneratorsError: expected a string, Symbol or expression or a non-empty sequence of strings, Symbols or expressions
sympifybefore using the expression and symbols
rs_seriesexpanded? The example you gave does not the same as mine:
In : rs_series(1/(1-x), x, 100) Out: (1/(-x + 1)) In : series(1/(1-x), x, n=100) Out: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 1 + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x ...
rs_series. @certik and @shivamvats might be able to
The whole function stuff is missing too?
In : from symengine import * %time _ = rs_series(cos(x)*sin(x), x, 100) ... AttributeError: 'symengine.lib.symengine_wrapper.Sin' object has no attribute 'has'
symengine.Functionis not an
symengine.Expression, and even if so,
Exprtranslation versus numeric or other ring improvements in symengine? While manipulation of series probably is possible without
Expr, series expansion from symbolic expressions is not. You might also need
Exprfor other things like simplification of expressions involving functions.
Thank you @rswt for your interest in ring_series.
rs_series is not in public API is that the function is buggy (as you yourself figured out :) ) and not implemented fully.
rs_series is basically a wrapper that calls the required functions (implemented in polys/ring_series.py) to expand a given expression. Currently it works with expressions involving
exponly (though making it work with other functions isn't difficult).
However, most of the elementary functions are fully implemented including series reversion, nth root and others. To use them, you need to create rings (a little extra work). For example, let's take your expression:
In : from sympy.polys.ring_series import rs_series_inversion In : R, x = ring('x', QQ) In : %timeit rs_series_inversion(1-x, x, 100) 100 loops, best of 3: 1.7 ms per loop In : %timeit rs_series_inversion(1-x, x, 10000) 10 loops, best of 3: 115 ms per loop In : %timeit (1/(1-a)).series(a,0,100) 1 loops, best of 3: 2.38 s per loop
You might also want to read https://github.com/sympy/sympy/blob/master/doc/src/modules/polys/ringseries.rst
@certik Sympy's online doc repo isn't automatically updated. Do I need to clone sympy_doc and update it?
sympy.Basic are two different things. When we pass a
symengine.Basic object to a
sympy first converts it into a
sympy.Basic and then carries on the computation. We'd like to have functionality that doesn't need conversions.
(One way would be to have
symengine objects behave as
sympy objects by manipulating
__instancecheck__ , but that'll be a lot of work to go through
sympy codebase and changing little things that are incompatible. http://stackoverflow.com/questions/6803597/how-to-fake-type-with-python )
rs_seriesfunction not to be buggy?
logof their own elements. GiNaC series have expansion of generic symbolic expressions (through differentiation I guess).
sage: R.<t> = PowerSeriesRing(QQ) sage: %time _ = (t^2+1).sqrt(prec=100) CPU times: user 2 ms, sys: 0 ns, total: 2 ms Wall time: 1.68 ms Wall time: 1.35 ms Wall time: 1.37 ms Wall time: 1.48 ms
sage: var('x') x sage: %time _ = sqrt(x^2+1).series(x,100) CPU times: user 38 ms, sys: 0 ns, total: 38 ms Wall time: 38.5 ms Wall time: 37.6 ms Wall time: 40.8 ms Wall time: 40.6 ms
Exprwhile I don't think e.g. Ruby has one. Also you don't want to convert SymPy
Exprs to symengine and vice versa. So you need to either use SymPy
Exprs from symengine (which is only useful temporarily) or you use symengine
Expressions from SymPy (so you need a translation). Wrong?
Expressionto have the full
@rwst here is how to do this using sympy:
In : from sympy.polys import ring, QQ In : from sympy.polys.ring_series import rs_nth_root In : R, x = ring('x', QQ) In : %time _ = rs_nth_root(x**2+1, 2, x, 100) CPU times: user 17 ms, sys: 4 ms, total: 21 ms Wall time: 17.3 ms Wall time: 15.1 ms Wall time: 12.3 ms Wall time: 15.7 ms Wall time: 12.3 ms Wall time: 13.3 ms Wall time: 13.4 ms Wall time: 13.3 ms Wall time: 14.2 ms Wall time: 14.9 ms
On my computer, Sage gives:
sage: R.<t> = PowerSeriesRing(QQ) sage: %time _ = (t^2+1).sqrt(prec=100) CPU times: user 9 ms, sys: 0 ns, total: 9 ms Wall time: 8.49 ms Wall time: 4.31 ms Wall time: 4.25 ms Wall time: 4.07 ms Wall time: 1.98 ms Wall time: 3.57 ms
You can check that both sympy and sage answers in
_ are exactly the same. My experience with Piranha is that it can easily be 10x faster than the sympy polynomials. So from the timings above, you can see that there is a huge potential for speedup. What is stopping Sage from extending the PowerSeriesRing to work for all symbolic functions?
Exprthing --- I am still a bit confused about what exactly the problem is. My view is that the C++ SymEngine library doesn't care about this at all. We are just trying to implement things in some maintainable way, currently we settled on using Basic, Mul, Pow, ... hierarchy and implement most functionality using the visitor pattern or single dispatch, so Basic doesn't need many methods. We are keeping an option to perhaps do things differently if they turn out to be faster. Either way though, this shouldn't matter at all for how it is actually used from Python, Ruby or Julia. Let's talk about just Python: there the wrappers are in implemented using Cython, and they are free to introduce any kind of classes (including
Expressionif needed), and the point of the wrappers is to make sure that things work out of the box from SymPy and Sage. The only job of the C++ SymEngine library is to ensure that the library's C++ API is implemented in such a way so that the wrappers can be written to do what they need. And so I think your question is how to improve the wrappers to operate better with Sage and SymPy, am I right?
symengine/symenginerepository, we only have to worry about speed, correctness, maintainability and a usable API and we can concentrate on these things without worrying or even testing any kind of wrappers. In the wrappers (
.rb), we simply just use the C++ (or C) API and the only thing we care is so that the (Python) wrapper can be used from sympy/Sage (and we test that in the test suite), and that it doesn't introduce unnecessary overhead in terms of speed. Ruby or Julia wrappers then care about interoperability with other libraries in those languages.
rs_serieswork with rest of the ring_series functions.
@certik , as to why Sage series are not being improved, maybe the fact that people would then have to integrate symbolic expressions into the
PowerSeriesRingwhich means working on symbolics (most shy away from that also because reviewers are lacking).
My problem with
Expr is just that it doesn't exist in symengine, to use for a translation of
rs_series, and I worry about how much of SymPy I need to translate to be able to translate
PowerSeriesRing. As to
Expr, we can easily introduce it into the wrappers, by simply introducing the
Exprclass and make all the other classes subclass it.
rs_series, are you talking about translation into SymEngine?
rs_*functions from SymPy into C++, they will call Piranha underneath. That will give us an immediate benchmark that we can run and see what the speed is compared to Sage or other libraries, and if this approach is worth pursuing.
rs_seriesthat calls the primitive functions underneath, and hook it all up with the rest of SymEngine, and also expose it in Python wrappers.
rs_*functions form sympy into symengine.
rs_muland then run the sin(x)*cos(x) benchmark against other software and see how we are doing.