<jupyter_start><jupyter_text>Lecture 5This lecture covers linear difference equations (recurrence equations). Below are some examples solved using SymPy.We first import the necessary modules:<jupyter_code>from sympy import *
init_printing()
from IPython.display import display

from fractions import Fraction

# Support for interactive plots
from ipywidgets import interact

%matplotlib inline<jupyter_output><empty_output><jupyter_text>Student grant exampleThis example is covered in the lecture (solved by hand). Here it is solved using SymPy.The difference equation (non-homegeneous case) for the student grant example from the lecture notes has the form$$y_{n} - 2.95 y_{n-1} + 2 y_{n-2} = −(63.685)(1.07^{n})$$ We first define $n$ as an integer symbol and $y$ as a function:<jupyter_code>n = Symbol("n", integer=True)
y = Function("y")<jupyter_output><empty_output><jupyter_text>Now, we define the difference equation:<jupyter_code>f = y(n) - Fraction(295, 100)*y(n - 1) + 2*y(n - 2)
display(f)<jupyter_output><empty_output><jupyter_text>We'll solve the homogeneous version of the equation using `rsolve`. To compare to the solution in the lecture notes, we'll also evaluate the the solution in floating point:<jupyter_code>eqn = Eq(f, 0)
soln = rsolve(eqn, y(n))
display(soln)
soln.evalf()<jupyter_output><empty_output><jupyter_text>The solution is the same as in the lecture notes.We now consider the non-homogeneous case:<jupyter_code># Create non-homogeneous equation
eqn = Eq(f, -63.685*(1.07**n))
display(eqn)<jupyter_output><empty_output><jupyter_text>Solving the non-homogeneous equation, on this occasion providing the initial conditions $y(0) = 2000$ and $y(1) = 2200$,<jupyter_code>soln = rsolve(eqn, y(n), init={y(0) : 2000, y(1) : 2200})
display(soln)
soln.evalf()
# Plot
plot(soln, (n, 0, 12), xlabel="year (n)", ylabel="fee")

# Evaluate fee at 10 years
print("Fee after 10 years (n=10): {}".format(soln.subs(n, 10).evalf()))<jupyter_output><empty_output><jupyter_text>General caseBelow is the general case for a constant coefficient, second-order difference equation.<jupyter_code>n = Symbol("n", integer=True)
y = Function("y")

a, b, c = symbols("a b c")

f = a*y(n) - b*y(n - 1) + c*y(n - 2)
display(f)<jupyter_output><empty_output><jupyter_text>Solving for the homogeneous case,<jupyter_code>eqn = Eq(f, 0)
soln = rsolve(eqn, y(n))
display(soln)<jupyter_output><empty_output><jupyter_text>The above is a general solution. Solving for some initial conditions,<jupyter_code>soln = rsolve(eqn, y(n), init={y(0) : 2, y(1) : 1})
display(soln)<jupyter_output><empty_output><jupyter_text>If we now specify the values for the constants, the solution can be plotted:<jupyter_code>eqn1 = eqn.subs('a', 4).subs('b', 1).subs('c', 2)
soln = rsolve(eqn1, y(n), init={y(0) : 1, y(1) : 2})
display(soln)

plot(soln, (n, 0, 12), xlabel="$n$", ylabel="$y_{n}$");<jupyter_output><empty_output><jupyter_text>Interactive solutionWith an interactive plot, we can see how the form of the solution changes with changing constants in the difference equation.We first define the difference equation:<jupyter_code>f = a*y(n) - b*y(n - 1) + c*y(n - 2)
eqn = Eq(f, 0)
display(eqn)<jupyter_output><empty_output><jupyter_text>Solving and plotting:<jupyter_code>def plot_solution(a=6, b=1, c=8):
    # Substitute in parameters
    eqn1 = eqn.subs('a', a).subs('b', b).subs('c', c)
    
    # Check roots
    roots = ((-b - sqrt(b**2 - 4*a*c))/(2*a), (-b + sqrt(b**2 - 4*a*c))/(2*a))
    print("Roots of characteristic eqn:")
    display(roots)

    # Solve
    soln = rsolve(eqn1, y(n), init={y(0) : 1, y(1) : 2})
    print("Solution:")
    display(soln)
    
    # Plot
    plot(soln, (n, 0, 20), xlabel="$n$", ylabel="$y_n$", axis_center="auto", adaptive=False, nb_of_points=21)

    
interact(plot_solution, a=(-10, 11, 2), b=(-2, 20, 1), c=(1, 10, 1), continuous_update=False);<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15368852459016394, 'fraction_numerical': 0.03048155737704918, 'mean_word_length': 5.850877192982456, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '257974', 'license': 'MIT', 'n_tokens_mistral': 1554, 'n_tokens_neox': 1439, 'n_words': 387, 'path': 'Lecture05.ipynb', 'repo_name': 'garth-wells/IA-maths-Ipython', 'size': '3904'}