Search code examples
pythonnumerical-methodsrecurrence

Recurrence Relations in Python


I am working with the recurrence "xn+1 = (13/3)xn - (4/3)xn-1". I am trying to write a Python script to print the first 50 values of xn with the given values of x0 = 1 and x1 = 1/3. This is what my code currently looks like:

import math
def printRecurrence():
    x = [0]*51 #initialize list of x values
    x[0] = 1
    x[1] = 1/3
    for i in range(1, 51):
        x[i+1] = (13/3)*x[i] - (4/3)*x[i-1]
        print(x[i])

and the output I receive is:

0.3333333333333333
0.11111111111111094
0.03703703703703626
0.012345679012342514
0.004115226337435884
0.0013717421124321456
0.00045724737062478524
0.00015241578946454185
5.0805260179967644e-05
1.6935074827137338e-05
5.644977344304949e-06
1.8814687224716613e-06
6.263946716372672e-07
2.0575194713260943e-07
5.63988753916179e-08
-2.994080281313502e-08
-2.049419793790756e-07
-8.481608402251475e-07
-3.402107668470205e-06
-1.361158544307069e-05
-5.444739336201271e-05
-0.00021778992397796082
-0.0008711598127551465
-0.0034846392899683535
-0.013938557172856001
-0.05575422869575153
-0.22301691478444863
-0.8920676591382753
-3.5682706365532617
-14.2730825462131
-57.092330184852415
-228.36932073940963
-913.4772829576384
-3653.909131830553
-14615.63652732221
-58462.546109288836
-233850.18443715532
-935400.7377486213
-3741602.950994485
-14966411.80397794
-59865647.21591176
-239462588.86364704
-957850355.4545882
-3831401421.8183527
-15325605687.27341
-61302422749.09364
-245209690996.37457
-980838763985.4983
-3923355055941.993

which is only correct for the first 13 printed values. The proof I was provided was that xn = 3-n, which for the most part does not match the values of my script. Did I do something wrong in my calculations? I've been unable to see it.


Solution

  • This recurrence relation can be answered exactly through the use of the fractions module or with a variable level of precision using the decimal module, which demonstrates the very high level of precision required to find compute 50 iterations accurately.

    Jean-François' point about floating point accumulation errors is correct. However the fraction module does not seem to be able to multiply multiple Fraction objects together, so all of the numeric values must be stated within the fraction object. Credit to him for the use of the correct module for this problem.

    Exact answer

    import math
    import fractions
    
    def printRecurrence():
        x = [0]*51 #initialize list of x values
        x[0] = fractions.Fraction(1,1)
        x[1] = fractions.Fraction(1,3)
        for i in range(1, 50):
            x[i+1] = fractions.Fraction(13*x[i]/3) - fractions.Fraction(4*x[i-1]/3)
            print(float(x[i+1]), 3**(-(i+1)), x[i+1]-(3)**(-(i+1)))
    
    printRecurrence()
    

    The print-out shows that the computation exactly matches the proof answer.

    Inexact but instructive answer

    The decimal module allows for a custom level of precision; to get to 50 iterations one needs a precision of 60 points or more.

    import math
    from decimal import *
    getcontext().prec = 60
    
    def printRecurrence():
        x = [0]*51 #initialize list of x values
        x[0] = Decimal(1)
        x[1] = Decimal(1)/Decimal(3)
        for i in range(1, 50):
            x[i+1] = (Decimal(13)/Decimal(3))*x[i] - (Decimal(4)/Decimal(3))*x[i-1]
            print(float(x[i+1]), 3**(-(i+1)), float(x[i+1]-Decimal(3)**(-(i+1))))
    
    printRecurrence()
    

    As with Jean-François' answer, I've printed the result, the computed value of 3**-n and the difference. One can play with the precision level getcontext().prec to see the effect on the result.

    0.111111111111 0.111111111111 -1e-60
    0.037037037037 0.037037037037 -4e-60
    0.0123456790123 0.0123456790123 -1.57e-59
    0.00411522633745 0.00411522633745 -6.243e-59
    0.00137174211248 0.00137174211248 -2.4961e-58
    0.000457247370828 0.000457247370828 -9.984e-58
    0.000152415790276 0.000152415790276 -3.993577e-57
    5.08052634253e-05 5.08052634253e-05 -1.59742978e-56
    1.69350878084e-05 1.69350878084e-05 -6.38971879e-56
    5.64502926948e-06 5.64502926948e-06 -2.5558875048e-55
    1.88167642316e-06 1.88167642316e-06 -1.02235500146e-54
    6.27225474386e-07 6.27225474386e-07 -4.08942000567e-54
    2.09075158129e-07 2.09075158129e-07 -1.63576800226e-53
    6.96917193763e-08 6.96917193763e-08 -6.54307200905e-53
    2.32305731254e-08 2.32305731254e-08 -2.61722880362e-52
    7.74352437514e-09 7.74352437514e-09 -1.04689152145e-51
    2.58117479171e-09 2.58117479171e-09 -4.18756608579e-51
    8.60391597238e-10 8.60391597238e-10 -1.67502643432e-50
    2.86797199079e-10 2.86797199079e-10 -6.70010573727e-50
    9.55990663597e-11 9.55990663597e-11 -2.68004229491e-49
    3.18663554532e-11 3.18663554532e-11 -1.07201691796e-48
    1.06221184844e-11 1.06221184844e-11 -4.28806767185e-48
    3.54070616147e-12 3.54070616147e-12 -1.71522706874e-47
    1.18023538716e-12 1.18023538716e-12 -6.86090827496e-47
    3.93411795719e-13 3.93411795719e-13 -2.74436330998e-46
    1.3113726524e-13 1.3113726524e-13 -1.09774532399e-45
    4.37124217466e-14 4.37124217466e-14 -4.39098129597e-45
    1.45708072489e-14 1.45708072489e-14 -1.75639251839e-44
    4.85693574962e-15 4.85693574962e-15 -7.02557007356e-44
    1.61897858321e-15 1.61897858321e-15 -2.81022802942e-43
    5.39659527735e-16 5.39659527735e-16 -1.12409121177e-42
    1.79886509245e-16 1.79886509245e-16 -4.49636484708e-42
    5.99621697484e-17 5.99621697484e-17 -1.79854593883e-41
    1.99873899161e-17 1.99873899161e-17 -7.19418375532e-41
    6.66246330538e-18 6.66246330538e-18 -2.87767350213e-40
    2.22082110179e-18 2.22082110179e-18 -1.15106940085e-39
    7.40273700597e-19 7.40273700597e-19 -4.60427760341e-39
    2.46757900199e-19 2.46757900199e-19 -1.84171104136e-38
    8.22526333997e-20 8.22526333997e-20 -7.36684416545e-38
    2.74175444666e-20 2.74175444666e-20 -2.94673766618e-37
    9.13918148886e-21 9.13918148886e-21 -1.17869506647e-36
    3.04639382962e-21 3.04639382962e-21 -4.71478026589e-36
    1.01546460987e-21 1.01546460987e-21 -1.88591210636e-35
    3.38488203291e-22 3.38488203291e-22 -7.54364842542e-35
    1.12829401097e-22 1.12829401097e-22 -3.01745937017e-34
    3.76098003645e-23 3.76098003657e-23 -1.20698374807e-33
    1.25366001171e-23 1.25366001219e-23 -4.82793499227e-33
    4.17886668798e-24 4.1788667073e-24 -1.93117399691e-32
    1.39295549185e-24 1.3929555691e-24 -7.72469598763e-32