EDITEDIT[update]: Recently, I wrote for myself some sage lines implementing the algorithm I described you. This is my second version, now working for rational numbers too : I was originally interested only in irrational rotation numbers, so these lines do not work properly for rational numbers, but I think you can adapt it very easily (comments are welcome to improve it!).
L=9L=8 #length for cf-expansion, depending on your computer, 8 or 9 suggested for a try run
A=100000 #maximum size of single element of the sequence
def partfrac(x):
return x-floor(x)
##### computing rational approximations given continued fraction expansion
# input b=a continued fraction expansion
# input l=L length of computed expansion
def rational_approximation(b,l):
p=[0,1]
q=[1,b[1]]
for i in range(1,l+1):
p.append(b[i+1]*p[i]+p[i-1])
q.append(b[i+1]*q[i]+q[i-1])
return simplify(p[l+1]/q[l+1])
#computing rotation number of a given circle map f
def rotation(f):
a=[0]
orbit=[]
orbit.append(partfrac(f(0)))
if orbit[0]==0 :
print 'map with a fixed point'
return 0
def shift(x): #set f(0) as the origin + 1
if partfrac(x)>orbit[0]:
return partfrac(x)-1
return partfrac(x)
def first_return(p,pre_p,y):
x=shift(f(y))
while x<pre_p or x>p:
x=shift(f(x))
return x
a.append(1)
x=orbit[0]
if shift(f(orbit[0]))==0:
returnprint 'map with fixedperiodic point'point of order 2'
return 1/2
if shift(f(orbit[0]))<0:
while shift(f(x))<0:
a[1]=a[1]+1
x = shift(f(x))
if a[1]>10000a[1]>A:
returnprint 'approximatively 0'
return 0
if shift(f(x))==0:
print 'periodic point'
a[1]=a[1]+1
return 1/a[1]
orbit.append(shift(x))
z = shift(f(x))
a.append(0)
while z>0:
y = z
z = first_return(shift(orbit[0]),shift(orbit[1]),z)
a[2]=a[2]+1
if a[2]>10000a[2]>A:
returnprint 'approximatively 0'rational'
return 1/a[1]
if z==0:
print 'periodic point'
a[2]=a[2]+1
return rational_approximation(a,1)
orbit.append(y)
if shift(f(orbit[0]))>0:
def shift(y): #set f(0) as the origin
if partfrac(y)>=orbit[0]:
return partfrac(y)-1
return partfrac(y)
orbit.append(orbit[0]-1)
a.append(0)
while shift(f(x))>0:
a[2] = a[2] + 1
x = shift(f(x))
if a[2]>10000a[2]>A:
returnprint 'approximatively rational'
return 1/a[1]
if shift(f(x))==0:
print 'periodic point'
a[2]=a[2]+1
return rational_approximation(a,1)
orbit.append(shift(x))
z = shift(f(x))
for i in range(1,L):
a.append(0)
if shift(orbit[i+1])<shift(orbit[i]):
while z>0:
y = z
z = first_return(shift(orbit[i]),shift(orbit[i+1]),z)
a[i+2]=a[i+2]+1
if a[i+2]>10000a[i+2]>A:
returnprint 'approximatively rational'
return rational_approximation(a,i)
if z==0:
print 'periodic point'
a[i+2]=a[i+2]+1
return rational_approximation(a,i+1)
if shift(orbit[i+1])>shift(orbit[i]):
while z<0:
y = z
z = first_return(shift(orbit[i+1]),shift(orbit[i]),z)
a[i+2]=a[i+2]+1
if a[i+2]>10000a[i+2]>A:
return print 'approximatively rational'
orbit.append return rational_approximation(ya,i)
print a #shows the cf expansion
#computing rational approximationsif z==0:
p=[0,1] print 'periodic point'
q=[1,a[1]] a[i+2]=a[i+2]+1
for i in range return rational_approximation(1a,L+1i+1):
p orbit.append(a[i+1]*p[i]+p[i-1]y)
q.append(a[i+1]*q[i]+q[i-1])print a
return simplifyrational_approximation(p[L+1]/q[L+1]a,L) #returns the rational approximation