San Vu Ngoc - IRMAR
%matplotlib inline
# inline can be replaced by notebook to get interactive plots
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as img
import matplotlib.cm as cm
import matplotlib.colors as colors
plt.rcParams['figure.figsize'] = (20.0, 12.0) # set figures display bigger
def fibPaire (n):
if n == 0:
return (0,1)
else:
a,b = fibPaire (n-1)
return (b,a+b)
def fib (n):
a,b = fibPaire (n)
return a
[fib(n) for n in range(0,17)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
La complexité la "pire" est obtenue par des paires de nombres de Fibonacci consécutifs. Leur pgcd est toujours 1 (ils sont premiers entre eux). À démontrer par récurrence...
#voir feuille 03
def pgcdIter (a,b):
r = a % b
if r == 0:
return 1
else:
return 1 + pgcdIter(b,r)
pgcdIter(9227465, 14930352)
35
Pour tester des grands nombres, il faut une version non récursive de l'algorithme.
def fibI (n):
a,b = 0,1
while n > 0:
(a,b) = (b,a+b)
n = n-1
return a
[fibI(n) for n in range(0,18)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597]
On constate que les points où le nombre d'itération est le plus grand correspondent à des couples (i,j) où les i,j sont des éléments consécutifs dans la suite de Fibonacci !
fibI(974), fibI(974+1)
(160131437125022133570186981636530600256034719271619021063640417693436516163698377535248015679488033602845112321108929620534730439060000506398830226180857811739131287777823445209422467744194016647915972857, 259098107935652557104489133457117935287501385615468464797658075441635685688364082902818922538578546112563887878124152051556445086889386828976126497605113833423713583754975704308251673170580841059906839650)
float(fibI(974))
1.6013143712502212e+203
# voir feuille 03
def pgcdI (a,b): # version "itérative"
while b != 0:
(a, b) = (b, a % b)
return a
pgcdI(fibI(974), fibI(974+1))
1
pgcdIterI(fibI(974), fibI(974+1))
--------------------------------------------------------------------------- NameError Traceback (most recent call last) /tmp/ipykernel_55471/1978963195.py in <module> ----> 1 pgcdIterI(fibI(974), fibI(974+1)) NameError: name 'pgcdIterI' is not defined
fibI(972), fibI(972+1)
(61164766314391710035884829815943265224568052927769577329622759945237346639032672167677108820397521093126336764093707189513015791230614183821533954756601790054548991800671186110593262317807192235925106064, 98966670810630423534302151820587335031466666343849443734017657748199169524665705367570906859090512509718775557015222431021714647829386322577296271424256021684582295977152259098829205426386824411990866793)
pgcdIterI(fibI(972), fibI(972+1))
--------------------------------------------------------------------------- NameError Traceback (most recent call last) /tmp/ipykernel_55471/865368299.py in <module> ----> 1 pgcdIterI(fibI(972), fibI(972+1)) NameError: name 'pgcdIterI' is not defined
On trace les (i,j) qui sont les $(F_k,F_{k+1})$ et leurs multiples.
La couleur indique la complexité de l'algorithme d'Euclide pour pgcd(i,j)
. On commence à $k=k0$.
def BAD (n,k0):
T = np.zeros((n,n))
F1, F2 = fibPaire(k0) # on part les k0-ème et
m = 1 # (k0+1)-ème nombres de Fibonacci.
while F2 < n:
i, j = F1, F2
while j < n:
T[i,j] = m
T[j,i] = m
i, j = i+F1, j+F2
m = m+1
F1, F2 = F2, F1+F2 # on passe au couple de Fibonacci suivant
return T
ar=BAD(100,4)
plt.imshow(ar, interpolation='none', cmap=cm.gist_earth)
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x7efbce96b730>
Les pentes des droites de l'image ci-dessus sont données par le nombre d'or !
$\phi = \frac{1+\sqrt{5}}2$
pgcdI(fibI(3000), fibI(3000+1))
1
fibI(3001)
664390460366960072280217847866028384244163512452783259405579765542621214161219257396449810982999820391132226802809465132446349331994409434926019045342723749188530316994678473551320635101099619382973181622585687336939784373527897555489486841726131733814340129175622450421605101025897173235990662770203756438786517530547101123748849140252686120104032647025145598956675902135010566909783124959436469825558314289701354227151784602865710780624675107056569822820542846660321813838896275819753281371491809004412219124856375121694811728724213667814577326618521478357661859018967313354840178403197559969056510791709859144173304364898001
import math
(1+math.sqrt(5))/2
1.618033988749895
# une très bonne approximation !
fibI(3000+1) / fibI(3000)
1.618033988749895