Hello,
> Mike, could you point me to your code?
I've attached the _very_ rough version I started awhile back. It just
does FormalPowerSeries and DataStream.
> I actually wonder why you would
> reprogram it in Sage and not interfacing the aldor-combinat library?
> Is there a problem with the license of the aldor compiler
> (aldor-combinat itself is GPL2).
Well, tree-like structures ( and hence species ) should be a standard
part of Sage. If we were to use aldor-combinat to do those
computations, then aldor would need to become a standard part of Sage.
This presents a number of issues:
* Aldor must build cleanly on all the platforms Sage builds on. This
is something that someone much more familiar with Aldor. The first
step would be to create an experimental spkg.
* I have no idea how (if possible) to interface an Aldor program from
C. pexpect interfaces are slow.
* licensing issues need to be sorted out since the APL2 is not
GPL-compatible. I don't know if it'd even be possible to distribute
Aldor as part of Sage.
Also, part of it was just a chance for me to learn more about species.
I definitely cannot program in Aldor, and one of the reasons why
Python has been so nice to work with is that is just sort of stays out
of the way. I'd much think about programming math instead of
programming languages.
--Mike
from stream import Stream
from series_order import InfiniteSeriesOrder, UnknownSeriesOrder, bounded_decrement, increment
from sage.rings.all import Integer
import pdb
inf = InfiniteSeriesOrder()
unk = UnknownSeriesOrder()
"""
#Test Plus 1
sage: from sage.combinat.species.series import *
sage: from sage.combinat.species.stream import Stream
sage: gs0 = FormalPowerSeries(Stream(const=0))
sage: gs1 = FormalPowerSeries(Stream(const=1))
sage: sum1 = gs0 + gs1
sage: sum2 = gs1 + gs1
sage: sum3 = gs1 + gs0
sage: [gs0.coefficient(i) for i in range(11)]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
sage: [gs1.coefficient(i) for i in range(11)]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
sage: [sum1.coefficient(i) for i in range(11)]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
sage: [sum2.coefficient(i) for i in range(11)]
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
sage: [sum3.coefficient(i) for i in range(11)]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
#Test Plus 2
sage: l1 = [1,2,4,8,0]
sage: l2 = [-1, 0,-1,-9,22,0]
sage: gs1 = FormalPowerSeries(Stream(l1))
sage: gs2 = FormalPowerSeries(Stream(l2))
sage: sum = gs1 + gs2
sage: sum2 = gs2 + gs1
sage: [ sum.coefficient(i) for i in range(5) ]
[0, 2, 3, -1, 22]
sage: [ sum.coefficient(i) for i in range(5, 11) ]
[0, 0, 0, 0, 0, 0]
sage: [ sum2.coefficient(i) for i in range(5) ]
[0, 2, 3, -1, 22]
sage: [ sum2.coefficient(i) for i in range(5, 11) ]
[0, 0, 0, 0, 0, 0]
#Test Zero
sage: s = FormalPowerSeries(Stream([0,2,3,0]))
sage: s.zero()
False
sage: s = FormalPowerSeries(0)
sage: s.zero()
True
sage: s = FormalPowerSeries(Stream([0]))
sage: s.zero()
False
sage: s.coefficient(0)
0
sage: s.coefficient(1)
0
sage: s.zero()
True
#Test Times 1
sage: gs0 = FormalPowerSeries(Stream(const=0))
sage: gs1 = FormalPowerSeries(Stream(const=1))
sage: prod0 = gs0 * gs1
sage: prod1 = gs1 * gs0
sage: prod2 = gs1 * gs1
sage: [prod0.coefficient(i) for i in range(11)]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
sage: [prod1.coefficient(i) for i in range(11)]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
sage: [prod2.coefficient(i) for i in range(11)]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
#Test Times 2
sage: l1 = [1,2,4,8,0]
sage: l2 = [-1, 0,-1,-9,22,0]
sage: gs1 = FormalPowerSeries(Stream(l1))
sage: gs2 = FormalPowerSeries(Stream(l2))
sage: prod1 = gs1 * gs2
sage: prod2 = gs2 * gs1
sage: [prod1.coefficient(i) for i in range(11)]
[-1, -2, -5, -19, 0, 0, 16, 176, 0, 0, 0]
sage: [prod2.coefficient(i) for i in range(11)]
[-1, -2, -5, -19, 0, 0, 16, 176, 0, 0, 0]
#Test Recursive 0
sage: s = FormalPowerSeries()
sage: s._name = 's'
sage: s.set(one+monom*s)
sage: s.aorder
0
sage: s.order
Unknown series order
sage: [s.coefficient(i) for i in range(6)]
[1, 1, 1, 1, 1, 1]
#Test Recursive 1
sage: s = FormalPowerSeries()
sage: s._name = 's'
sage: s.set(one+monom*s*s)
sage: s.aorder
0
sage: s.order
Unknown series order
sage: [s.coefficient(i) for i in range(6)]
[1, 1, 2, 5, 14, 42]
#Test Recursive 1b
sage: s = FormalPowerSeries()
sage: s._name = 's'
sage: s.set(monom + s*s)
sage: s.aorder
1
sage: s.order
Unknown series order
sage: [s.coefficient(i) for i in range(7)]
[0, 1, 1, 2, 5, 14, 42]
#Test Recursive 2
sage: s = FormalPowerSeries()
sage: s._name = 's'
sage: t = FormalPowerSeries()
sage: t._name = 't'
sage: s.set(one+monom*t*t*t)
sage: t.set(one+monom*s*s)
sage: [s.coefficient(i) for i in range(9)]
[1, 1, 3, 9, 34, 132, 546, 2327, 10191]
sage: [t.coefficient(i) for i in range(9)]
[1, 1, 2, 7, 24, 95, 386, 1641, 7150]
#Test Recursive 2b
sage: s = FormalPowerSeries()
sage: s._name = 's'
sage: t = FormalPowerSeries()
sage: t._name = 't'
sage: s.set(monom + t*t*t)
sage: t.set(monom + s*s)
sage: [s.coefficient(i) for i in range(9)]
[0, 1, 0, 1, 3, 3, 7, 30, 63]
sage: [t.coefficient(i) for i in range(9)]
[0, 1, 1, 0, 2, 6, 7, 20, 75]
#Test Recursive 3
sage: s = FormalPowerSeries()
sage: s._name = 's'
sage: s.set(one+monom*s*s*s)
sage: [s.coefficient(i) for i in range(10)]
[1, 1, 3, 12, 55, 273, 1428, 7752, 43263, 246675]
#Test PlusTimes 1
sage: s = (one + monom) * (one + monom)
sage: [s.coefficient(i) for i in range(6)]
[1, 2, 1, 0, 0, 0]
#Test Compose 1
sage: s = FormalPowerSeries(Stream(const=1))
sage: t = FormalPowerSeries(Stream([0,0,1]))
sage: u = s(t)
sage: u.coefficients(11)
[1, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
#Test Compose 2
sage: s = FormalPowerSeries(Stream(const=1))
sage: t = FormalPowerSeries(Stream([0,0,1,0]))
sage: u = s(t)
sage: u.aorder
0
sage: u.order
Unknown series order
sage: u.coefficients(10)
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
sage: u.aorder
0
sage: u.order
0
#Test Compose 3
# s = 1/(1-x), t = x/(1-x)
# s(t) = (1-x)/(1-2x)
sage: s = FormalPowerSeries(Stream(const=1))
sage: t = FormalPowerSeries(Stream([0,1]))
sage: u = s(t)
sage: u.coefficients(14)
[1, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096]
#Test Differentiate 1
sage: s = FormalPowerSeries(Stream(const=1))
sage: u = s.differentiate()
sage: u.coefficients(10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
#Test Differentiate 2
sage: s = FormalPowerSeries()
sage: s._name = 's'
sage: s.set(one+monom*s*s)
sage: u = s.differentiate()
sage: u.coefficients(5) #[1*1, 2*2, 3*5, 4*14, 5*42]
[1, 4, 15, 56, 210]
#Test Differentiate 3
sage: s = FormalPowerSeries(Stream(const=1))
sage: t = FormalPowerSeries(Stream([0,1]))
sage: u = s(t).differentiate()
sage: v = (s.differentiate().compose(t))*t.differentiate()
sage: u.coefficients(11)
[1, 4, 12, 32, 80, 192, 448, 1024, 2304, 5120, 11264]
sage: v.coefficients(11)
[1, 4, 12, 32, 80, 192, 448, 1024, 2304, 5120, 11264]
#Test Differentiate 4
sage: s = FormalPowerSeries(); s._name='s'
sage: t = FormalPowerSeries(); t._name='t'
sage: s.set(monom+t*t*t)
sage: t.set(monom+s*s)
sage: u = (s*t).differentiate()
sage: v = s.differentiate()*t + s*t.differentiate()
sage: u.coefficients(10)
[0, 2, 3, 4, 30, 72, 133, 552, 1791, 4260]
sage: v.coefficients(10)
[0, 2, 3, 4, 30, 72, 133, 552, 1791, 4260]
sage: u.coefficients(10) == v.coefficients(10)
True
#Test Integrate 1a
sage: s = zero
sage: t = s.integrate()
sage: t.zero()
True
#Test Integrate 1b
sage: s = zero
sage: t = s.integrate(1)
sage: t.coefficients(6)
[1, 0, 0, 0, 0, 0]
sage: t.stream.is_constant()
True
#Test Integrate 2a
sage: s = term(1, 0)
sage: t = s.integrate()
sage: t.coefficients(6)
[0, 1, 0, 0, 0, 0]
sage: t.stream.is_constant()
True
#Test Integrate 2b
sage: s = term(1,0)
sage: t = s.integrate(1)
sage: t.coefficients(6)
[1, 1, 0, 0, 0, 0]
sage: t.stream.is_constant()
True
#Test Integrate 3a
sage: s = term(1, 4)
sage: t = s.integrate()
sage: t.coefficients(10)
[0, 0, 0, 0, 0, 1/5, 0, 0, 0, 0]
#Test Integrate 3b
sage: s = term(1,4)
sage: t = s.integrate(1)
sage: t.coefficients(10)
[1, 0, 0, 0, 0, 1/5, 0, 0, 0, 0]
#Test Sum 1
sage: s = FormalPowerSeries(Stream(const=1))
sage: g = [s]*6 + [zero]
sage: t = fps_sum_generator(g)
sage: t.coefficients(10)
[1, 2, 3, 4, 5, 6, 6, 6, 6, 6]
#Test Sum 2
sage: s = FormalPowerSeries(Stream(const=1))
sage: def g():
... while True:
... yield s
sage: t = fps_sum_generator(g())
sage: t.coefficients(9)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
#Test Product 1
sage: s1 = FormalPowerSeries(Stream([1,1,0]))
sage: s2 = FormalPowerSeries(Stream([1,0,1,0]))
sage: s3 = FormalPowerSeries(Stream([1,0,0,1,0]))
sage: s4 = FormalPowerSeries(Stream([1,0,0,0,1,0]))
sage: s5 = FormalPowerSeries(Stream([1,0,0,0,0,1,0]))
sage: s6 = FormalPowerSeries(Stream([1,0,0,0,0,0,1,0]))
sage: s = [s1, s2, s3, s4, s5, s6]
sage: def g():
... for a in s:
... yield a
sage: p = fps_product_generator(g())
sage: p.coefficients(26)
[1, 1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0]
#Test Product 2
sage: def m(n):
... n -= 1
... yield 1
... while True:
... for i in range(n):
... yield 0
... yield 1
...
sage: def s(n):
... q = 1/n
... n -= 1
... yield 0
... while True:
... for i in range(n):
... yield 0
... yield q
...
sage: def lhs_gen():
... n = 1
... while True:
... yield FormalPowerSeries(Stream(m(n)))
... n += 1
...
sage: def rhs_gen():
... n = 1
... while True:
... yield FormalPowerSeries(Stream(s(n)))
... n += 1
...
sage: lhs = fps_product_generator(lhs_gen())
sage: rhs = fps_sum_generator(rhs_gen()).exponentiate()
sage: lhs.coefficients(10)
[1, 1, 2, 3, 5, 7, 11, 15, 22, 30]
sage: rhs.coefficients(10)
[1, 1, 2, 3, 5, 7, 11, 15, 22, 30]
#Test exponentiate
sage: def inv_factorial():
... q = 1
... yield 0
... yield q
... n = 2
... while True:
... q = q / n
... yield q
... n += 1
sage: f = FormalPowerSeries(Stream(inv_factorial())) #e^(x)-1
sage: u = f.exponentiate()
sage: g = inv_factorial()
sage: z1 = [1,1,2,5,15,52,203,877,4140,21147,115975]
sage: l1 = [z*g.next() for z in z1]
sage: l1 = [1] + l1[1:]
sage: u.coefficients(11)
[1, 1, 1, 5/6, 5/8, 13/30, 203/720, 877/5040, 23/224, 1007/17280, 4639/145152]
sage: l1 == u.coefficients(11)
True
"""
def uninitialized():
raise RuntimeError, "we should never be here"
def FormalPowerSeries(x=None):
if x is None:
return FormalPowerSeries_class(stream=None, order=unk, aorder=unk,
aorder_changed=True, compute_aorder=uninitialized,
is_initialized=False)
if hasattr(x, 'next'):
return FormalPowerSeries(Stream(x))
if isinstance(x, Stream):
return FormalPowerSeries_class(stream=x, order=unk, aorder=0,
aorder_changed=False, compute_aorder=do_nothing,
is_initialized=True)
if x == 0:
return zero
if x == 1:
return one
if x == 'monom':
return monom
raise TypeError, "unable to create a formal power series from x (= %s)"%x
class FormalPowerSeries_class:
def __init__(self, stream=None, order=None, aorder=None, aorder_changed=True, is_initialized=False, compute_aorder=None, name=None):
self.stream = stream
if order is None:
self.order = unk
else:
self.order = order
if aorder is None:
self.aorder = unk
else:
self.aorder = aorder
if self.aorder == inf:
self.order = inf
self.aorder_changed = aorder_changed
self.is_initialized = is_initialized
self.compute_aorder = compute_aorder
self._name = name
def __repr__(self):
if self._name:
return self._name
if self.is_initialized:
l = str(self.stream.list)
else:
l = 'uninitialized'
return "Formal power series: %s"%l
def initialize(self):
if self.order != unk:
return
if self.aorder == inf:
raise ValueError, "aorder can never be infinity since order would have to be infinity"
elif self.aorder != unk and self.is_initialized:
#Try to improve the approximate order
i = self.aorder
c = self.stream
n = len(c)
if i == 0 and n > 0:
if self.stream[i] == 0:
i += 1
self.aorder += 1
#Try to recognize the zero series
if i >= n:
#For non-constant series, we cannot do anythin
if not self.stream.is_constant():
return
if self.stream[ len(self.stream) - 1] == 0:
self.aorder = inf
self.order = inf
return
while i < n and c[i] == 0:
i += 1
self.aorder = i
if i < n:
self.order = i
else:
#if self.is_initialized != False:
# raise ValueError, "the series must be uninitialized at this point"
self.compute_aorder()
#if self.is_initialized != True:
#raise ValueError, "the series must be initialized at this point"
if hasattr(self, '_references_me'):
self._references_me._copy(self)
def initialize_coefficient_stream(self,compute_coefficients):
ao = self.aorder
assert ao != unk
if ao == inf:
self.order = inf
self.stream = Stream(0)
else:
self.stream = Stream(gen=compute_coefficients(ao))
self.is_initialized = True
def coefficients(self, n):
return [self.coefficient(i) for i in range(n)]
def zero(self):
self.initialize()
return self.order == inf
def set_approximate_order(self, new_order):
self.aorder_changed = ( self.aorder != new_order )
self.aorder = new_order
return self.aorder_changed
def _copy(self, x):
self.order = x.order
self.aorder = x.aorder
self.aorder_changed = x.aorder_changed
self.compute_aorder = x.compute_aorder
self.is_initialized = x.is_initialized
self.stream = x.stream
def set(self, x):
self._copy(x)
x._references_me = self
reprx = repr(x)
if "=" in reprx:
self._name += " = (" + reprx +")"
else:
self._name += " = " + reprx
def coefficient(self, n):
#pdb.set_trace()
if self.zero():
return 0
if n < self.aorder:
return 0
assert self.is_initialized
return self.stream[n]
def get_aorder(self):
self.initialize()
return self.aorder
def get_order(self):
self.initialize()
return self.order
def get_stream(self):
self.initialize()
return self.stream
def approximate_order_two(self, x, y, new_order, compute_coefficients):
"""approximate_order_two(\n%s, \n%s, \n%s, \n%s)"""%(x,y,new_order,compute_coefficients)
if self.is_initialized:
return
ochanged = self.aorder_changed
must_initialize_coefficient_stream = ( self.aorder == unk or self.is_initialized == False)
def a_order(x,y):
#print "(%s,%s) -> %s"%(x.aorder, y.aorder, new_order(x.aorder, y.aorder))
return new_order(x.aorder, y.aorder)
ao = a_order(x,y)
#start at maximum
if ao == unk:
ao = inf
tchanged = self.set_approximate_order(ao)
if ochanged or tchanged:
x.compute_aorder()
y.compute_aorder()
ao = a_order(x,y)
tchanged = self.set_approximate_order(ao)
#assert self.is_initialized == False
if must_initialize_coefficient_stream:
self.initialize_coefficient_stream(compute_coefficients)
if hasattr(self, '_references_me'):
self._references_me._copy(self)
def approximate_order_one(self, x, new_order, compute_coefficients):
"""approximate_order_two(\n%s, \n%s, \n%s)"""%(x,new_order,compute_coefficients)
if self.is_initialized:
return
ochanged = self.aorder_changed
must_initialize_coefficient_stream = ( self.aorder == unk or self.is_initialized == False)
def a_order(z):
#print "%s -> %s"%(z.aorder, new_order(z.aorder))
return new_order(z.aorder)
ao = a_order(x)
#start at maximum
if ao == unk:
ao = inf
tchanged = self.set_approximate_order(ao)
if ochanged or tchanged:
x.compute_aorder()
ao = a_order(x)
tchanged = self.set_approximate_order(ao)
assert self.is_initialized == False
if must_initialize_coefficient_stream:
self.initialize_coefficient_stream(compute_coefficients)
if hasattr(self, '_references_me'):
self._references_me._copy(self)
def approximate_order_zero(self, new_order, compute_coefficients):
"""approximate_order_zero(\n%s, \n%s)"""%(new_order,compute_coefficients)
if self.is_initialized:
return
assert self.aorder == unk
ao = new_order()
self.set_approximate_order(ao)
self.initialize_coefficient_stream(compute_coefficients)
if hasattr(self, '_references_me'):
self._references_me._copy(self)
def new0(self,compute_coefficients, order_op, name=None):
new_fps = self.new_from_ao(name=name)
def f0():
"""new0 - f0: %s, %s"""%(order_op, compute_coefficients)
new_fps.approximate_order_zero(order_op, compute_coefficients)
new_fps.compute_aorder = f0
return new_fps
def new1(self, compute_coefficients, order_op, x, name=None):
new_fps = self.new_from_ao( name=name )
def f1():
"""new1 - f1: %s, %s, %s"""%(x, order_op, compute_coefficients)
new_fps.approximate_order_one(x, order_op, compute_coefficients)
new_fps.compute_aorder = f1
return new_fps
def new2(self,compute_coefficients, order_op, x, y, name=None):
new_fps = self.new_from_ao(name=name )
def f2():
new_fps.approximate_order_two(x, y, order_op, compute_coefficients)
f2.__doc__ = """new2 - f2: %s, %s, %s, %s"""%(x, y, order_op, compute_coefficients)
new_fps.compute_aorder = f2
return new_fps
def new_from_ao(self, name=None):
return FormalPowerSeries_class(stream=None, order=unk, aorder=self.aorder,
aorder_changed=True, compute_aorder=None,
is_initialized=False, name=name)
def __add__(self, y):
def plus(ao):
for n in range(ao):
yield 0
n = ao
while True:
yield self.coefficient(n) + y.coefficient(n)
n += 1
return self.new2(plus, min, self, y, name=repr(self)+" + " +repr(y))
def __mul__(self, y):
def times(ao):
for n in range(ao):
yield 0
n = ao
while True:
low = self.aorder
high = n - y.aorder
nth_coefficient = 0
#Handle the zero series
if low == inf or high == inf: #
yield 0 #
n += 1 #
continue #
for k in range(low, high+1):
cx = self.coefficient(k)
if cx == 0:
continue
nth_coefficient += cx * y.coefficient(n-k)
yield nth_coefficient
n += 1
reprself = repr(self)
repry = repr(y)
if "+" in reprself:
reprself = "(" + reprself + ")"
if "+" in repry:
repry = "(" + repry + ")"
return self.new2(times, lambda a,b:a+b, self, y, name=reprself+"*"+repry)
def __call__(self, y):
def compose(ao):
assert y.coefficient(0) == 0
yield self.coefficient(0)
def g():
n = 1
while True:
yield self.coefficient(n)
n += 1
rest_x = FormalPowerSeries(g())
z = rest_x.compose(y)*y
is_zero = z.zero()
n = 1
while True:
yield z.coefficient(n)
n += 1
return self.new2(compose, lambda a,b:a*b, self, y, name="(%s)o(%s)"%(repr(self), repr(y)))
def add(self, y):
return self + y
def times(self, y):
return self * y
def compose(self, y):
return self(y)
def differentiate(self):
def diff(ao):
#Fixme! (take care of approximate order stuff)
#for n in range(ao-1):
# yield 0
n = 1
while True:
yield n*self.coefficient(n)
n += 1
return self.new1(diff, bounded_decrement, self, name="D(%s)"%repr(self))
def integrate(self, integration_constant = 0):
def integrate(ao):
for n in range(ao):
yield 0
n = ao
while True:
yield (Integer(1)/Integer(n))*self.coefficient(n-1)
n += 1
if integration_constant == 0:
return self.new1(integrate, increment, self, name="I(%s)"%repr(self))
else:
return _new(0, Stream(self._integrate_nonzero(integration_constant)), name="I(%s,%s)"%(repr(self), integration_constant))
def _integrate_nonzero(self, integration_constant):
yield integration_constant
aox = self.aorder
assert aox != unk
if aox == inf:
while True:
yield 0
else:
for n in range(aox):
yield 0
n = aox + 1
while True:
yield (Integer(1)/Integer(n))*self.coefficient(n-1)
n += 1
def exponentiate(self):
s = FormalPowerSeries(); s._name = "s"
s.set( (self.differentiate()*s).integrate(1) )
s._name = "EXP(%s)"%repr(self)
return s
def do_nothing(*args, **kwargs):
## assert t.aorder != unk
## assert t.is_initialized == True
return
def new_from_ao(approximate_order):
return FormalPowerSeries_class(stream=None, order=unk, aorder=unk,
aorder_changed=True, compute_aorder=approximate_order,
is_initialized=False)
#Finite Sum
def sum_coefficients(a):
last = len(a) - 1
assert last >= 0
n = 0
while True:
r = sum( [a[i].coefficient(n) for i in range(len(a))] )
yield r
n += 1
def fps_sum(a):
return FormalPowerSeries( sum_coefficients(a) )
#Potentially infinite sum
def fps_sum_generator(g):
s = Stream(g)
def h():
n = 0
while True:
r = s[n].coefficient(n) #compute [x^n] s(n)
for i in range(len(s)-1):
r += s[i].coefficient(n)
yield r
n += 1
return FormalPowerSeries(h())
#Potentially infinite product
def fps_product_generator(g):
def h():
z = g.next()
yield z.coefficient(0)
yield z.coefficient(1)
n = 2
for x in g:
z = z * x
yield z.coefficient(n)
n += 1
while True:
yield z.coefficient(n)
n += 1
return FormalPowerSeries(h())
#################################
def _new(o, g, name=None):
return FormalPowerSeries_class(stream=g, order=o, aorder=o,
aorder_changed=False, compute_aorder=do_nothing,
is_initialized=True, name=name)
zero = _new(inf, Stream([0]), name="0")
one = _new(0, Stream([1,0]), name="1")
monom = _new(1, Stream([0,1,0]), name="monom")
def term(r, n):
if r == 0:
return zero
else:
s = [0]*n+[r,0]
return _new(int(n), Stream(s), name="term(%s,%s)"%(r,n))
from sage.rings.all import Integer
class SeriesOrderElement:
pass
class InfiniteSeriesOrder(SeriesOrderElement):
def __init__(self):
pass
def __repr__(self):
return "Infinite series order"
def __add__(self, x):
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return self
if isinstance(x, InfiniteSeriesOrder):
return self
if isinstance(x, UnknownSeriesOrder):
return x
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
__radd__ = __add__
def __mul__(self, x):
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return self
if isinstance(x, InfiniteSeriesOrder):
return self
if isinstance(x, UnknownSeriesOrder):
return x
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
def __rmul__(self, x):
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
if x == 0:
return 0
else:
return self
if isinstance(x, InfiniteSeriesOrder):
return self
if isinstance(x, UnknownSeriesOrder):
return x
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
def __lt__(self, x):
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return False
if isinstance(x, InfiniteSeriesOrder):
return False
if isinstance(x, UnknownSeriesOrder):
return False
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
def __gt__(self, x):
return True
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return False
if isinstance(x, InfiniteSeriesOrder):
return False
if isinstance(x, UnknownSeriesOrder):
return False
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
class UnknownSeriesOrder(SeriesOrderElement):
def __init__(self):
pass
def __repr__(self):
return "Unknown series order"
def __add__(self, x):
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return self
if isinstance(x, SeriesOrderElement):
return self
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
__radd__ = __add__
def __mul__(self, x):
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return self
if isinstance(x, SeriesOrderElement):
return self
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
def __rmul__(self, x):
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return self
if isinstance(x, SeriesOrderElement):
return self
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
def __lt__(self, x):
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return True
if isinstance(x, SeriesOrderElement):
return True
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
def __gt__(self, x):
return False
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return False
if isinstance(x, InfiniteSeriesOrder):
return False
if isinstance(x, UnknownSeriesOrder):
return False
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
def bounded_decrement(x):
if isinstance(x, SeriesOrderElement):
return x
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return max(0, x - 1)
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
def increment(x):
if isinstance(x, SeriesOrderElement):
return x + 1
if isinstance(x, (int, Integer)):
if x < 0:
raise ValueError, "x must be a positive integer"
return x+1
raise TypeError, "x must be a positive integer or a SeriesOrderElement"
import itertools
def _integers_from(n):
while True:
yield n
n += 1
class Stream:
"""
EXAMPLES:
sage: from itertools import izip
sage: s = Stream(0)
sage: len(s)
1
sage: [x for x in s.elements()]
[0]
sage: [x for (x,i) in izip(s, range(4))]
[0, 0, 0, 0]
sage: len(s)
1
sage: l = [4,3,5,7,4,1,9,7]
sage: s = Stream(l)
sage: s[3]
8
sage: len(s)
4
sage: s[3]
8
sage: len(s)
4
sage: s[1]
3
sage: len(s)
4
sage: s[4]
4
sage: len(s)
5
sage: [i for i in s.elements()]
[4, 3, 5, 7, 4, 1, 9, 7]
sage: len(s)
8
sage: l = [4,3,5,2,6,1]
sage: s = Stream(l)
sage: s[3]
2
sage: len(s)
4
sage: g = iter(l)
sage: s.set_gen(g)
sage: s[5]
3
sage: len(s)
6
sage: [x for x in s.elements()]
[4, 3, 5, 2, 6, 1, 4, 3, 5, 2]
sage: len(s)
10
sage: s = Stream(const=4)
sage: g = iter(s)
sage: n = s.elements()
sage: l1 = [x for (x,i) in izip(g, range(10))]
sage: l2 = [x for (x,i) in izip(n, range(10))]
sage: l = [4 for k in range(10)]
sage: l == l1
True
sage: l2
[4]
sage: t = Stream([2,3,5,7,11])
sage: g3 = t.elements(2)
sage: l3 = [x for (x,i) in izip(g3, range(10))]
sage: l3
[5, 7, 11]
sage: g4 = t.elements(10)
sage: l4 = [x for (x,i) in izip(g4, range(10))]
sage: l4
[11]
sage: l = ['Hello', ' ', 'World', '!']
sage: s = Stream(l)
sage: len(s)
0
sage: s[2]
"World"
sage: len(s)
3
sage: u = ""
sage: for i in range(len(s)): u += s[i]
sage: u
"Hello World"
sage: v = ""
sage: for i in range(10): v += s[i]
sage: v
"Hello World!!!!!!!"
sage: len(s)
4
sage: l = [2,3,5,7,11,0]
sage: s = Stream(l)
sage: s.is_constant()
False
sage: s[3]
7
sage: s.is_constant()
False
sage: s[5]
0
sage: s.is_constant()
False
sage: s[6]
0
sage: s.is_constant()
True
sage: s = Stream(const='I am constant.')
sage: s.is_constant()
True
sage: s = Stream([1,2,3,4,5,6])
sage: a = []
sage: b = []
sage: for (i,x) in enumerate(s.elements()):
a = [x] + a
b = [ s[2*i] ] + b
sage: a
[6, 5, 4, 3, 2, 1]
sage: b
[6, 6, 6, 5, 3, 1]
sage: fib = Stream()
sage: def g():
yeild 1
yield 1
n = 0
while True:
yield fib[n] + fib[n+1]
n += 1
sage: fib.set_gen(g())
sage: [x for (x,i) in izip(fib, range(11))]
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 69]
sage: def h(l):
if len(l) < 2:
return 1
return l[-1] + l[-2]
sage: fib = Stream(func = h)
sage: [x for (x,i) in izip(fib, range(11))]
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 69]
sage: s = Stream()
sage: l = Stream([1, 0])
sage: y = Stream([0,1,0])
sage: s.set_gen(iter(l + y * s * s))
sage: [x for (x,i) in izip(s, range(6))]
[1, 1, 2, 5, 14, 42]
sage: def f(l):
if len(l) == 0:
return 0
return l[-1] + 1
sage: o = Stream(func=f)
sage: [x for (x,i) in izip(o, range(10))]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
sage: double = lambda z: 2*z
sage: t = o.map(double)
sage: [x for (x,i) in izip(t, range(10))]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
sage: double = lambda z: 2*z
sage: o = Stream([0,1,2,3])
sage: [x for (x,i) in izip(o, range(6))]
[0, 1, 2, 3, 3, 3]
sage: t = o.map(double)
sage: [x for (x,i) in izip(t, range(6))]
[0, 2, 4, 6, 6, 6]
sage: r = [4, 3, 5, 2, 6, 1, 1, 1, 1, 1]
sage: l = [4, 3, 5, 2, 6, 1]
sage: s = Stream(l)
sage: s[3] = -1
sage: [x for (x,i) in izip(s, r)]
[4, 3, 5, -1, 6, 1, 1, 1, 1, 1]
sage: s[5] = -2
sage: [x for (x,i) in izip(s, r)]
[4, 3, 5, -1, 6, -2, 1, 1, 1, 1]
sage: s[6] = -3
sage: [x for (x,i) in izip(s, r)]
[4, 3, 5, -1, 6, -2, -3, 1, 1, 1]
sage: s[8] = -4
sage: [x for (x,i) in izip(s, r)]
[4, 3, 5, -1, 6, -2, -3, 1, -4, 1]
sage: a = Stream(const=0)
sage: a[2] = 3
sage: [x for (x,i) in izip(a, range(4))]
[0, 0, 3, 0]
"""
def __init__(self, gen=None, const=None, list=None, constant=True, func=None):
if func != None:
if gen != None:
raise ValueError, "you cannot specify both a function and a generator"
def g():
while True:
try:
yield func(self.list)
except:
break
gen = g()
if hasattr(gen, '__iter__'):
gen = iter(gen)
#Constant stream
if const != None:
self.list = [ const ]
self.last_index = 0
self.gen = None
self.constant = const
self.end_reached = True
else:
self.list = [ ]
self.last_index = -1
self.gen = gen
self.constant = constant
self.end_reached = False
def __setitem__(self, i, t):
self[i]
if i < len(self.list):
self.list[i] = t
else:
self.list += [ self.constant ] * (i+1 - len(self.list))
self.last_index = i
self.list[i] = t
def set_gen(self, gen):
self.gen = gen
self.end_reached = False
def map(self, f):
return Stream(gen=(f(x) for x in self))
def __getitem__(self, i):
if i <= self.last_index:
return self.list[i]
elif self.end_reached:
if self.constant != "False":
return self.constant
else:
raise IndexError, "out of position"
else:
while self.last_index < i:
try:
self.list.append(self.gen.next())
self.last_index += 1
except StopIteration:
self.end_reached = True
self.constant = self.list[-1]
return self[i]
return self.list[i]
def __add__(self, ds):
if not isinstance(ds, Stream):
raise TypeError, "ds must be a Stream"
return Stream(gen=(a+b for (a,b) in itertools.izip(self,ds)))
def __mul__(self, ds):
if not isinstance(ds, Stream):
raise TypeError, "ds must be a Stream"
def times(n):
t = 0
for k in range(n+1):
sk = self[k]
if sk == 0:
continue
t += sk *ds[n-k]
return t
return Stream(gen=(times(n) for n in _integers_from(0)))
def __iter__(self):
i = 0
while True:
try:
yield self[i]
except IndexError:
break
i += 1
def __len__(self):
return len(self.list)
def number_computed(self):
return self.__len__()
def data(self):
return self.list
def is_constant(self):
return self.end_reached
def elements(self, start_index=0):
i = start_index
while not self.end_reached:
try:
self[i]
except IndexError:
break
i += 1
if start_index >= len(self.list):
return iter(self.list[-1:])
else:
return iter(self.list[start_index:])
## if start_index < 0:
## raise ValueError, "start_index must be >= 0"
## i = start_index
## while True:
## print i, self.last_index, len(self.list), self.end_reached
## z = self[i]
## print i, self.last_index, len(self.list), self.end_reached
## print "-"*20
## if self.end_reached and i >= len(self.list):
## if start_index >= len(self.list):
## yield z
## break
## yield z
## i += 1
one = Stream(const=1)
zero = Stream(const=0)
x = Stream([0,1,0])
ints = Stream(_integers_from(0))
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Aldor-combinat-devel mailing list
Aldor-combinat-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/aldor-combinat-devel