Ok, here are my results of learning python and sage via implementing a proper powerseries module "hyperops.powerseries". I didnt dare to already incorporate it into our git repository before consilidating and synchronizing us about it. So I just attach the single file.
I also have a Sage question: How does one incorporate own packages into the sage hierarchy so that they are recognized from whatever path one starts sage?
Ok, now the module description:
The main difference to the existing powerseries package is that we deal with untruncated powerseries, which are evaluated as soon as we request it.
A powerseries is mainly given as a function that returns the coefficient for the index, i.e. what we write often as \( f_n \), the \( n \)-th coefficient of the powerseries \( f \).
Maple has such a package however its awfully slow if one want to compute for example hyperbolic iteration, because it lacks caching. This is a simple mechanism that just stores a once computed value for subsequent access. It is life-saving in the case of recursive computations as we need to do.
There are also other ugly matters with the Maple powerseries, for example that they always need a name. When created anonymously one get errors.
So thatswhy I was burning to create a proper powerseries package without all those drawbacks. And found that python is an absolute nice language to perform such tasks including functional programming style. And before long explanations I just give the example code, which is also included in the documentation section of the module.
Our beloved regular iteration is of course contained (hyperbolic and parabolic gathered in one routine deciding by the first coefficient which one to chose) and demonstrated here with the decremented exponential.
The pure command file (without the outputs) is appended. You can just paste into sage.
I also have a Sage question: How does one incorporate own packages into the sage hierarchy so that they are recognized from whatever path one starts sage?
Ok, now the module description:
The main difference to the existing powerseries package is that we deal with untruncated powerseries, which are evaluated as soon as we request it.
A powerseries is mainly given as a function that returns the coefficient for the index, i.e. what we write often as \( f_n \), the \( n \)-th coefficient of the powerseries \( f \).
Maple has such a package however its awfully slow if one want to compute for example hyperbolic iteration, because it lacks caching. This is a simple mechanism that just stores a once computed value for subsequent access. It is life-saving in the case of recursive computations as we need to do.
There are also other ugly matters with the Maple powerseries, for example that they always need a name. When created anonymously one get errors.
So thatswhy I was burning to create a proper powerseries package without all those drawbacks. And found that python is an absolute nice language to perform such tasks including functional programming style. And before long explanations I just give the example code, which is also included in the documentation section of the module.
Our beloved regular iteration is of course contained (hyperbolic and parabolic gathered in one routine deciding by the first coefficient which one to chose) and demonstrated here with the decremented exponential.
Code:
sage: from hyperops.powerseries import PowerSeriesI
sage: #Predefined PowerSeries
sage: expps = PowerSeriesI().Exp()
sage: expps.poly(10,x)
x^9/362880 + x^8/40320 + x^7/5040 + x^6/720 + x^5/120 + x^4/24 + x^3/6 + x^2/2 + x + 1
sage: expps
[1, 1, 1/2, 1/6, 1/24, 1/120, 1/720, 1/5040, 1/40320, 1/362880, 1/3628800, ...]
sage: PowerSeriesI().Zero()
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
sage: PowerSeriesI().One()
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
sage: PowerSeriesI().Identity()
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
sage: #finite powerseries
sage: p = PowerSeriesI([1,2,3,4])
sage: p.poly(10,x)
4*x^3 + 3*x^2 + 2*x + 1
sage: p
[1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
sage: one = PowerSeriesI([1])
sage: id = PowerSeriesI([0,1])
sage: #power series are just functions that map the index to the coefficient
sage: expps(30)
1/265252859812191058636308480000000
sage: #power series operations
sage: p+p
[2, 4, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
sage: p-p
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
sage: p*p
[1, 4, 10, 20, 25, 24, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
sage: #/ not yet implemented
sage: p**2
[1, 4, 10, 20, 25, 24, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
sage: #composition only works for coefficient 0 being 0 in the second operand
sage: dexp = expps - one
sage: expps.compose(dexp)
[1, 1, 1, 5/6, 5/8, 13/30, 203/720, 877/5040, 23/224, 1007/17280, ...]
sage: #we come into interesting regions ...
sage: dexp.compose(dexp)
[0, 1, 1, 5/6, 5/8, 13/30, 203/720, 877/5040, 23/224, 1007/17280, ...]
sage: dexp.iterate(2)
[0, 1, 1, 5/6, 5/8, 13/30, 203/720, 877/5040, 23/224, 1007/17280, ...]
sage: hdexp = dexp.iterate(1/2)
sage: hdexp
[0, 1, 1/4, 1/48, 0, 1/3840, -7/92160, 1/645120, 53/3440640, -281/30965760, ...]
sage: #verifying that shoudl be Zero
sage: hdexp.iterate(2) - dexp
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
sage: #symbolic (parabolic) iteration
sage: dexp.iterate(x)
[0, 1, x/2, 5*(x - 1)*x/12 - (x - 2)*x/6, ...]
sage: q = dexp.iterate(1/x).iterate(x)
sage: q(3)
(5*(1/x - 1)/(6*x) - (1/x - 2)/(3*x) + 1/(2*x^2))*(x - 1)*x/2 - (5*(1/x - 1)/(12*x) - (1/x - 2)/(6*x))*(x - 2)*x
sage: #simiplify and compare
sage: expand(q(3))
1/6
sage: dexp(3)
1/6
sage: #you can initialize power series with arbitrary functions on natural numbers
sage: #for example the power series of sqrt(2)^x can be given as
sage: bsrt = PowerSeriesI(lambda n: diff(sqrt(2)^x,x,n)(x=0)/factorial(n))
sage: #making the first coefficient 0 to get the decremented exponential
sage: def coeff(n):
sage: if n == 0:
sage: return 0
sage: else:
sage: return bsrt(n)
sage: dbsrt = PowerSeriesI(coeff)
sage: #and now starting hyperbolic iteration
sage: dbsrt2 = dbsrt.iterate(x).iterate(1/x)
sage: #Sage is not able to simplify
sage: simplify(dbsrt2(3))
...
sage: #but numerically we can verify equality
sage: RR(dbsrt2(3)(x=0.73)-dbsrt(3))
-8.67361737988404e-19The pure command file (without the outputs) is appended. You can just paste into sage.
