INF1100 AppA Printversion 8
INF1100 AppA Printversion 8
INF1100 AppA Printversion 8
Sequences
1, 3, 5, 7, . . . , 2n + 1, . . .
Simula Research Laboratory
University of Oslo, Dept. of Informatics For this sequence we have a formula for the n-th term:
xn = 2n + 1
(xn )∞
n=0 , xn = 2n + 1
Sequences and Difference Equations (Appendix A) – p.1/?? Sequences and Difference Equations (Appendix A) – p.2/??
x0 , x1 , . . . , x20
Sequences and Difference Equations (Appendix A) – p.3/?? Sequences and Difference Equations (Appendix A) – p.4/??
For sequences occuring in modeling of real-world phenomena, Put x0 money in a bank at year 0. What is the value after N years
there is seldom a formula for the n-th term if the interest rate is p percent per year?
However, we can often set up one or more equations governing The fundamental information relates the value at year n, xn , to the
the sequence value of the previous year, xn−1 :
Such equations are called difference equations p
xn = xn−1 + xn−1
With a computer it is then very easy to generate the sequence by 100
solving the difference equations
Solution by simulation:
Difference equations have lots of applications and are very easy
to solve on a computer, but often complicated or impossible to start with x0 (known)
solve for xn (as a formula) by pen and paper! compute x1 = x0 + 0.01px0 = (1 + 0.01p)x0
The programs require only loops and arrays compute x2 = x1 + 0.01px1 = (1 + 0.01p)2 x0
...continue this boring procedure...
find that xn = (1 + 0.01p)n x0
...which is what you learned in high school
That is: we can solve this difference equation by hand
Sequences and Difference Equations (Appendix A) – p.5/?? Sequences and Difference Equations (Appendix A) – p.6/??
Simulating the difference equation for interest rates Note about the use of arrays
Simulate = solve math equations by repeating a simple procedure We store the xn values in a NumPy array
(relation) many times (boring, but well suited for a computer) To compute xn , we only need one previous value, xn−1
Let us make a program for Thus, for the computations we do not need to store all the
p previous values, i.e., we do not need any array, just two numbers:
xn = xn−1 + xn−1 x_old = x0
100 for n in index_set[1:]:
x_new = x_old + (p/100.)*x_old
from scitools.std import * x_old = x_new # x_new becomes x_old at next step
x0 = 100 # initial amount
p = 5 # interest rate However, programming with an array x[n] is simpler, safer, and
N = 4 # number of years
index_set = range(N+1)
enables plotting the sequence, so we will continue to use arrays in
x = zeros(len(index_set)) the examples
# solution:
x[0] = x0
for n in index_set[1:]:
x[n] = x[n-1] + (p/100.0)*x[n-1]
print x
plot(index_set, x, ’ro’, xlabel=’years’, ylabel=’amount’)
Sequences and Difference Equations (Appendix A) – p.7/?? Sequences and Difference Equations (Appendix A) – p.8/??
Daily interest rate Program for daily interest rate
A more relevant model is to add the interest every day from scitools.std import *
x0 = 100 # initial amount
The interest rate per day is r = p/D if p is the annual interest rate p = 5 # annual interest rate
r = p/360.0 # daily interest rate
and D is the number of days in a year import datetime
date1 = datetime.date(2007, 8, 3)
A common model in business applies D = 360, but n counts exact date2 = datetime.date(2011, 8, 3)
(all) days diff = date2 - date1
N = diff.days
New model: index_set = range(N+1)
r x = zeros(len(index_set))
xn = xn−1 + xn−1
100 # solution:
x[0] = x0
How can we find the number of days between two dates? for n in index_set[1:]:
>>> import datetime x[n] = x[n-1] + (r/100.0)*x[n-1]
>>> date1 = datetime.date(2007, 8, 3) # Aug 3, 2007 print x
>>> date2 = datetime.date(2008, 8, 4) # Aug 4, 2008 plot(index_set, x, ’ro’, xlabel=’days’, ylabel=’amount’)
>>> diff = date2 - date1
>>> print diff.days
367
Sequences and Difference Equations (Appendix A) – p.9/?? Sequences and Difference Equations (Appendix A) – p.10/??
But the annual interest rate may change quite often... Payback of a loan
This is problematic when computing by hand A loan L is paid back with a fixed amount L/N every month over
In the program, a varying p is easy to deal with N months + the interest rate of the loan
Just fill an array p with correct annual interest rate for day no. n, Let p be the annual interest rate and p/12 the monthly rate
n=0,...,N (this can be a bit challenging) Let xn be the value of the loan at the end of month n
Modified program: The fundamental relation from one month to the other:
p = zeros(len(index_set))
# fill p[n] for n in index_set p p L
xn = xn−1 + xn−1 − ( xn−1 + )
r = p/360.0 # daily interest rate 12 · 100 12 · 100 N
x = zeros(len(index_set))
x[0] = x0
which simplifies to
for n in index_set[1:]: L
x[n] = x[n-1] + (r[n-1]/100.0)*x[n-1] xn = xn−1 −
N
(The constant term L/N makes the equation nonhomogeneous,
while the previous interest rate equation was homogeneous (all
terms contain xn or xn−1 ))
The program is left as an exercise
Sequences and Difference Equations (Appendix A) – p.11/?? Sequences and Difference Equations (Appendix A) – p.12/??
How to make a living from a fortune (part 1) How to make a living from a fortune (part 2)
We have a fortune F invested with an annual interest rate of p Assume I percent inflation per year and that c0 is q percent of the
percent interest the first year
Every year we plan to consume an amount cn (n counts years) cn then develops as money with interest rate I, and xn develops
Let xn be the development of our fortune with rate p but with a loss cn every year:
Sequences and Difference Equations (Appendix A) – p.13/?? Sequences and Difference Equations (Appendix A) – p.14/??
xn = xn−1 + xn−2 , x0 = 1, x1 = 1
Sequences and Difference Equations (Appendix A) – p.15/?? Sequences and Difference Equations (Appendix A) – p.16/??
Fibonacci numbers and overflow (part 1) Fibonacci numbers and overflow (part 2)
Run the program with N = 50: Best: use Python scalars of type int – these automatically
2 2 changes to long when overflow in int
3 3
4 5 The long type in Python has arbitrarily many digits (as many as
5 8
6 13 required in a computation)
...
45 1836311903 Note: long for arrays is 64 bit integer (int64), while scalar
Warning: overflow encountered in long_scalars long in Python is an integer with as "infinitely" many digits
46 -1323752223
Sequences and Difference Equations (Appendix A) – p.17/?? Sequences and Difference Equations (Appendix A) – p.18/??
Program with Python’s long type for integers Exponential growth with limited resources
The program now avoids arrays and makes use of three int The model for growth of money in a bank has a solution of the type
objects (which automatically changes to long when needed):
import sys xn = x0 C n (= x0 en ln C )
N = int(sys.argv[1])
xnm1 = 1 # "x_n minus 1"
xnm2 = 1 # "x_n minus 2" This is exponential growth in time (n)
n = 2
while n <= N: Populations of humans, animals, and cells also exhibit the same
xn = xnm1 + xnm2
print ’x_%d = %d’ % (n, xn) type of growth as long as there are unlimited resources (space
xnm2 = xnm1 and food)
xnm1 = xn
n += 1 The environment can only support a maximum number M of
Run with N = 200: individuals
x_2 = 2 How can we model this?
x_3 = 3
... We shall introduce a logistic model
x_198 = 173402521172797813159685037284371942044301
x_199 = 280571172992510140037611932413038677189525
x_200 = 453973694165307953197296969697410619233826
Initially, when there are enough resources, the growth is In a program it is easy to introduce logistic instead of exponential
exponential: growth, just replace
r x[n] = x[n-1] + p/100.0)*x[n-1]
xn = xn−1 + xn−1
100 by
x[n] = x[n-1] + (rho/100.0)*x[n-1]*(1 - x[n-1]/float(M))
The growth rate r must decay to zero as xn approaches M
A very simple r(n) function with this behavior is 500
450
xn
r(n) = ̺ 1 − 400
M 350
no of individuals
Observe that r(n) ≈ ̺ for small n when xn << M , and r(n) → 0 300
200
The model for limited growth, called logistic growth, is then
150
̺ xn−1 100
xn = xn−1 + xn−1 1 − 0 50 100 150 200
Sequences and Difference Equations (Appendix A) – p.21/?? Sequences and Difference Equations (Appendix A) – p.22/??
The factorial n! is defined as n(n − 1)(n − 2) · · · 1 (0! = 1) The Taylor series for ex reads
The following difference equation has xn = n! as solution and can ∞
be used to compute the factorial:
X xn
ex =
n=0
n!
xn = nxn−1 , x0 = 1
We can formulate this series as two coupled difference equations
(and solving these difference equations is (probably) the most
efficient way to compute the Taylor series!):
x
an = an−1 , a0 = 1
n
en = en−1 + an , e0 = 1
See the book for how to solve the difference equations by hand
and show that the solution is the Taylor series for ex
Sequences and Difference Equations (Appendix A) – p.23/?? Sequences and Difference Equations (Appendix A) – p.24/??
Newton’s method for finding zeros A program for Newton’s method
Sequences and Difference Equations (Appendix A) – p.25/?? Sequences and Difference Equations (Appendix A) – p.26/??
2
Only one f (x) call in each iteration, optional storage of (x, f (x)) Example: solve e−0.1x sin( π2 x) = 0
values during the iterations, and float division: from math import sin, cos, exp, pi
import sys
def Newton(f, x, dfdx, epsilon=1.0E-7, N=100,
store=False): def g(x):
f_value = f(x) return exp(-0.1*x**2)*sin(pi/2*x)
n = 0
if store: info = [(x, f_value)] def dg(x):
while abs(f_value) > epsilon and n <= N: return -2*0.1*x*exp(-0.1*x**2)*sin(pi/2*x) + \
x = x - float(f_value)/dfdx(x) pi/2*exp(-0.1*x**2)*cos(pi/2*x)
n += 1
f_value = f(x) x0 = float(sys.argv[1])
if store: info.append((x, f_value)) x, info = Newton(g, x0, dg, store=True)
if store: print ’zero:’, x
return x, info for i in range(len(info)):
else: print ’Iteration %3d: f(%g)=%g’ % \
return x, n, f_value (i, info[i][0], info[i][1])
Sequences and Difference Equations (Appendix A) – p.27/?? Sequences and Difference Equations (Appendix A) – p.28/??
Sequences and Difference Equations (Appendix A) – p.29/?? Sequences and Difference Equations (Appendix A) – p.30/??
Making a sound file with single tone (part 1) Making a sound file with single tone (part 2)
r: sampling rate (samples per second, default 44100) We have data as an array with float and unit amplitude
f : frequency of the tone Sound data in a file should have 2-byte integers (int16) as data
m: duration of the tone (seconds) elements and amplitudes up to 215 − 1 (max value for int16
data)
Sampled sine function for this tone: data = note(440, 2)
data = data.astype(numpy.int16)
n max_amplitude = 2**15 - 1
sn = A sin 2πf , n = 0, 1, . . . , m · r data = max_amplitude*data
r import scitools.sound
scitools.sound.write(data, ’Atone.wav’)
Code (we use descriptive names: frequency=f , length=m, scitools.sound.play(’Atone.wav’)
amplitude=A, sample_rate=r):
import numpy
def note(frequency, length, amplitude=1,
sample_rate=44100):
time_points = numpy.linspace(0, length,
length*sample_rate)
data = numpy.sin(2*numpy.pi*frequency*time_points)
data = amplitude*data
return data
Sequences and Difference Equations (Appendix A) – p.31/?? Sequences and Difference Equations (Appendix A) – p.32/??
Reading sound from file Playing many notes
Let us read a sound file and add echo Each note is an array of samples from a sine with a frequency
Sound = array s[n] corresponding to the note
Echo means to add a delay of the sound Assume we have several note arrays data1, data2, ...:
# put data1, data2, ... after each other in a new array:
# echo: e[n] = beta*s[n] + (1-beta)*s[n-b]
data = numpy.concatenate((data1, data2, data3, ...))
def add_echo(data, beta=0.8, delay=0.002, The start of "Nothing Else Matters" (Metallica):
sample_rate=44100):
newdata = data.copy() E1 = note(164.81, .5)
shift = int(delay*sample_rate) # b (math symbol) G = note(392, .5)
for i in xrange(shift, len(data)): B = note(493.88, .5)
newdata[i] = beta*data[i] + (1-beta)*data[i-shift] E2 = note(659.26, .5)
return newdata intro = numpy.concatenate((E1, G, B, E2, B, G))
...
Load data, add echo and play: song = numpy.concatenate((intro, intro, ...))
scitools.sound.play(song)
data = scitools.sound.read(filename)
scitools.sound.write(song, ’tmp.wav’)
data = data.astype(float)
data = add_echo(data, beta=0.6)
data = data.astype(int16)
scitools.sound.play(data)
Sequences and Difference Equations (Appendix A) – p.33/?? Sequences and Difference Equations (Appendix A) – p.34/??
Sequence: x0 , x1 , x2 , . . ., xn , . . ., xN Given a x0 , x1 , x2 , . . ., xn , . . ., xN
Difference equation: relation between xn , xn−1 and maybe xn−2 Can we listen to this sequence as "music"?
(or more terms in the "past") + known start value x0 (and more Yes, we just transform the xn values to suitable frequencies and
values x1 , ... if more levels enter the equation) use the functions in scitools.sound to generate tones
Solution of difference equations by simulation: We will study two sequences:
index_set = <array of n-values: 0, 1, ..., N>
x = zeros(N+1)
x[0] = x0 xn = e−4n/N sin(8πn/N )
for n in index_set[1:]:
x[n] = <formula involving x[n-1]>
and
Can have (simple) systems of difference equations:
for n in index_set[1:]:
xn = xn−1 + qxn−1 (1 − xn−1 ) , x = x0
x[n] = <formula involving x[n-1]>
y[n] = <formula involving y[n-1] and x[n]> The first has values in [−1, 1], the other from x0 = 0.01 up to
around 1
Taylor series and numerical methods such as Newton’s method
can be formulated as difference equations, often resulting in a Transformation from "unit" xn to frequencies:
good way of programming the formulas
yn = 440 + 200xn
Three functions: two for generating sequences, one for the sound