Professional Documents
Culture Documents
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
7
7
8
9
10
10
10
11
12
13
13
14
14
15
16
16
20
21
22
23
23
24
25
25
26
26
26
32
35
36
38
38
42
45
46
46
47
4
4.3
4.4
5
6
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
47
48
48
49
50
51
53
57
61
63
63
64
68
70
73
73
73
74
75
76
76
77
78
79
81
83
83
84
84
84
85
85
86
88
88
91
93
93
96
98
99
2
3
1.3
Chanes de caractres . . . . . . . . . . . . . . . . . . . . . . . .
Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Algorithmique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1
Algorithmique des tableaux/listes et des chanes de caractres
3.2
Mthode dEuler . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3
Algorithme de Gauss-Jordan . . . . . . . . . . . . . . . . . . . .
Lire et crire dans un fichier . . . . . . . . . . . . . . . . . . . . . . . . .
4.1
Requtes SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
102
103
103
103
104
106
107
107
.
.
.
.
.
.
.
113
113
115
119
120
120
124
128
Chapitre 1
Cours de premire anne
1 Structures de donnes en Python
1.1 Nombres
1.1.1 Nombres en base 10 et base 2
En informatique, linformation est rprsente par des squences de 0 et de 1. Les symboles
0 et 1 sont appels boolens, chiffre binaires, ou encore bit (acronyme de binary digits).
Les nombres que nous manipulons sont habituellement reprsents en base 10 : intuivement, pour dnombrer des objets, on les regroupe en paquets de 10, 100, 1000 etc. . .Par
exemple, 2015 signifie 2 1000 + 0 100 + 1 10 + 5, donc 2 paquets de 1000, aucun paquet
de 100, un paquet de 10 et un reste de 5 units.
En informatique, les nombres sont reprsents en base 2. Il est relativement ais de passer
de la base 10 la base 2, et rciproquement.
Pour passer de la base 10 la base 2. On effectue des divisions euclidienne par 2 du nombre
n reprsent en base 10, tant que le quotient nest pas gal 0. Si les restes successifs sont
nots r 0 , r 1 , . . . , r q alors :
n = r q r q1 . . . r 1 r 0 2
Donc n = 11111011110 .
Pour passer de la base 2 la base 10. Si en base 2, n = r q r q1 . . . r 1 r 0 2 , alors en base 10 :
n = r q 2q + r q1 2q1 + + r 1 21 + r 0 20
7
Exemple. Sur 8 bits, x = 23 est reprsent par sa reprsentation binaire 00010111 , puisque
2
0 23 28 1 = 127.
Exemple. Sur 8 bits, x = 128 est reprsent par 10000000 puisque 2 = 128 x 1,
2
Pour les raisons donnes ci-dessus, le premier bit est appel bit de signe.
Les nombres entiers forment le type int. Lorsquon manipule des nombres trop grand (ie
plus grand que 2n pour une reprsentation sur n bits), on parle de dpassement de capacit.
En Python 2.x, un nouveau type a t cr, appel long (pour long int). En Python 3.x, les
types int et long sont fusionns, on ne peroit donc pas de dpassement de capacit.
Pour les nombres rels, le choix de la reprsentation est beaucoup plus dlicat. On montre
simplement que tout rel x a une unique criture de la forme m 2n avec = 1, m [1, 2[
et n Z .
Ainsi pour stocker x en mmoire il suffire de stocker ,m et n. et n sont des entiers , respectivement appels signe et exposant de x, donc on procde comme ci-dessus (en tant limit
par les dpassements de capacits).
m, appel mantisse, est un nombre rel de lintervalle [1, 2[. On va stocker sa reprsentation
ap
1 a1 a2 a3
2
en binaire qui scrit 1, a1 a2 a3 . . . a p = 0 + 1 + 2 + 3 + + p cest--dire un nombre
2
2
2
2
2
virgule avec le chiffre 1 gauche de la virgule. Comme certains nombres rels ont un nombre
infini de chiffres aprs la virgule, ils ne seront donc pas reprsentables en machine. En pratique, le chiffre gauche de la virgule tant toujours 1, on ne stocke que les chiffres aprs la
virgule.
Plus prcisment on utilise souvent la norme IEEE 754.
Simple prcision. On utilise 32 bits : 1 bit de signe, 8 bits pour lexposant (126 127) et 23
bits de mantisse (avec 1 bit implicite).
Double prcision. On utilise 64 bits : 1 bit de signe, 11 bits pour lexposant (1022 1023)
et 52 bits de mantisse (avec 1 bit implicite).
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
9
Les nombres ainsi reprsents sont appels flottants et forment en Python le type float. Un
nombre entier peut tre du type int ou du type float : 7 est du type int et 7. est du type
float.
B Il faudra prendre garde deux aspects du type float :
1) Certains nombres peuvent avoir une criture dcimale finie mais une criture binaire infinie, cest--dire que ce sont des nombres simples dun point de vue mathmatique et pourtant non reprsentable en machine ! (Ce sont les nombres non dyadiques : tous les irrationnels et certains rationnels)
+
X
1
1
2
+ 4n+3 = 0, 01100110011001100 . . . a une reprsentation biExemple. 0.4 =
4n+2
2
n=0 2
naire infinie, et nest donc pas reprsentable en machine.
x
x
x
x
+
*
/
y
y
y
y
10
x.real
x.imag
# partie relle
# partie imaginaire
x &
x |
x ^
not
y
y
y
x
ou
x and y
# et
ou
x or y
# ou
# ou ex
lusif
# ngation de x
Toute opration valable sur des entiers lest aussi sur les boolens : le calcul se fait en prenant
la valeur 0 pour False, et la valeur 1 pour True.
La plupart du temps, les boolens sont obtenus au moyen de tests. Tests :
x == y
x
x
x
x
x
x
x
< y
> y
<= y
>= y
!= y
in y
is y
#
#
#
#
#
#
#
#
#
1.3 Listes
Une liste permet de manipuler une squence dobjets.
[1, 10, 2, 3, 2, 2
Une liste peut contenir des objets de nimporte-quel type. Par exemple, des chanes de caractres :
11
On peut mme avoir une liste qui contient une liste :
[
Les lments dune liste peuvent contenir des expressions complexes, faisant appel des
variables ou des fonctions :
a = 2
[(2 + 3) * a, a * 2
12
1.3.3 Indices, longueur et intervalles
On accde aux lments individuels dune liste en indiquant leur indice entre crochets. La
numrotation des lments commence zro. Par exemple :
>>> a = [1, 7, 5
>>> a[0
1
>>> a[2
5
On peut utiliser des indices ngatifs pour compter partir de la fin de la liste :
>>> a = [1, 7, 5
>>> a[-1
5
>>> a[-3
1
La fonction len donne la longueur dune liste :
>>> liste[:-1
[1, 4, 1, 5
On peut aussi prciser un pas avec linstruction liste[min:max:pas. Par exemple pour
avoir les lments dindices pairs :
>>> liste[::2
[1, 1, 9
13
1.3.4 Oprateurs sur les listes
De la mme manire que les chanes, les listes peuvent tre concatnes avec loprateur +,
et multiplies par un entier :
>>> [1, 2 + [2
[1, 2, 2
>>> [1, 2 * 3
[1, 2, 1, 2, 1, 2
On peut comparer deux listes avec loprateur == :
>>> a = [1, 7, 5
>>> a[1 = 0
>>> a
[1, 0, 5
On peut aussi affecter une liste un intervalle :
>>> a = [1, 7, 5
>>> a[0:2 = [2, 3
>>> a
[2, 3, 5
Lors dune affectation un intervalle, il nest pas ncessaire que les listes soient de longueur
identique :
>>> a = [1, 7, 5
>>> a[0:2 = [2, 3, 4
>>> a
[2, 3, 4, 5
>>> a[0:2 = [
>>> a
[4, 5
La mthode append permet dajouter un lment la fin de la liste :
>>> a = [1, 4, 5
>>> a.append(0)
>>> a
[1, 4, 5, 0
14
1.3.6 Smantique de pointeur
Laffectation dune liste une variable ne cre pas une copie de la liste. Voici un exemple de
programme qui illustre ce phnomne :
>>>
>>>
>>>
>>>
a = [1, 7, 5
b = a
a[1 = 0
b
[1, 0, 5
On voit que la modification de la liste a affecte aussi la liste b. Cela peut se reprsenter de la
faon suivante dans un tableau dexcution :
a
L1
b
L1
L1
[1, 7, 5
[1, 0, 5
Pour faire une nouvelle copie de la liste, il est ncessaire dutiliser une expression comme
ci-dessous :
>>>
>>>
>>>
>>>
a = [1, 7, 5
b = a[: # b = a + [, ou b = list(a) ou b = [ x for x in a fon
tionnent aussi
a[1 = 0
b
[1, 7, 5
Ce qui donne :
a
L1
b
L2
L1
[1, 7, 5
L2
[1, 7, 5
[1, 0, 5
>>> a = [1, 5, 3, 2
>>> a.sort()
>>> print(a)
[1, 2, 3, 5
Si on souhaite conserver la liste a intacte, et crer une nouvelle liste, on peut utiliser la fonction sorted :
>>> a = [1, 5, 3, 2
>>> b = sorted(a)
>>> print(b)
[1, 2, 3, 5
>>> print(a)
[1, 5, 3, 2
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
15
Lappartenance une liste peut se tester avec loprateur in :
>>> 1 in [3, 4, 5
False
>>> 4 in [3, 4, 5
True
Le minimum et le maximum peuvent se trouver avec les fonctions min et max :
>>> min([3, 1, 4, 1, 5, 9, 2)
1
>>> max([3, 1, 4, 1, 5, 9, 2)
9
del permet de supprimer un lment dune liste :
>>> a = [0, 1, 2, 3, 4
>>> del a[2
>>> a
[0, 1, 3, 4
Notez quon peut faire la mme opration en affectant une liste vide :
>>> a = [0, 1, 2, 3, 4
>>> a[2:3 = [
>>> a
[0, 1, 3, 4
>>>
= "bonjour"
>>>
[0
b
>>>
[0:3
bon
>>> len(
)
7
On peut aussi dlimiter une chane de caractres par des apostrophes ' ' ou pas des triples
guillements """ """.
Si on cherche modifier la chane, il se produit des erreurs :
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
16
>>>
[0 = "B"
Tra
eba
k (most re
ent
all last):
File "<stdin>", line 1, in <module>
TypeError: 'str' obje
t does not support item assignment
>>>
.append("!")
Tra
eba
k (most re
ent
all last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' obje
t has no attribute 'append'
Mais on peut obtenir un effet similaire en construisant une nouvelle chane :
>>> "x" in
False
>>> "Bon" in
True
Attention : in ne fonctionne pas de cette faon pour les listes.
2 Programmation
2.1 Variables et affectations
En Python , les variables bnficient dun typage dynamique : le type est dtect automatiquement lors de la cration de la variable par affectation. Il nest donc pas ncessaire de
dclarer la variable avant de lutiliser (comme dans la plupart des autres langages).
Laffectation est laction consistant donner une valeur une variable.
a = 2
# affe tation
Laffectation dune valeur une variable se fait avec lgalit. La ligne ci-dessus donne la
valeur 2 la variable a, ceci jusqu la prochaine modification.
Une affectation peut prendre en argument le rsultat dune opration :
a = 2 + 4
Ce calcul peut mme utiliser la variable a elle-mme :
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
17
a = a + 4*a*a
Dans ce cas, le calcul du membre de droite est effectu dabord, et ensuite seulement laffectation. Ainsi, le calcul est effectu avec lancienne valeur de a. Il faut en particulier quune
valeur ait dj t attribue a. Par exemple, si a a initialement la valeur 2, la ligne ci-dessus
attribue la valeur 18 a.
Il existe des raccourcis pour certaines oprations de ce type :
a += 2
a -= 1
a *= 3
a /= 2
a %= 3
a **= 4
et
.
#
#
#
#
#
#
quivaut
quivaut
quivaut
quivaut
quivaut
quivaut
a
a
a
a
a
a
=
=
=
=
=
=
a
a
a
a
a
a
+ 2
- 1
* 3
/ 2 (en Python 2.7 division entire si possible)
% 3 (reste modulo 3)
** 4 (puissan
e)
Pour afficher la valeur dune variable en ligne de commande, il suffit de taper le nom de la
variable aprs linvite de commande :
>>> a = 2
>>> a
2
Faire un affichage du contenu dune variable lors de lexcution dun programme ncessite
la fonction print(), qui affiche une chane de caractres. On peut aussi lutiliser en ligne de
commande :
>>> print(a)
2
Cette fonction ralise une conversion automatique pralable du contenu de la variable en
chane de caractres, car la fonction print() prend toujours en argument une chane de
caractres.
Il est possible deffectuer simultanment plusieurs affectations de variables (de mme type
ou non) :
18
Laffectation simultane est un bon moyen dchanger le contenu de deux variables :
>>> x, y = 3, 7
>>> x, y = y, x
>>> [x, y
[7, 3
>>> a, b,
, d, e = 1, 2, 3, 4, 5
>>> a, b,
, d, e = b,
, d, e, a
>>> a, b,
, d, e
(2, 3, 4, 5, 1)
Comme dans toute valuation, lexpression qui suit le signe = est value en premier (donc
avant que la premire des affectations ne soit ralise).
>>> u, v = 2, 3
# i
i u reoit 2, et v reoit 3
>>> u, v = v*v, u*u
# gau
he de =, lire la squen
e 9, 4
>>> u, v
# don
ne pas
roire qu'on a effe
tu u=v=9 puis v=u=81
(9, 4)
Dans un langage qui ne gre pas laffectation simultane, lchange des valeurs de deux variables x et y ncessite une troisime variable temporaire z :
>>> z=x
>>> x=y
>>> y=z
Chaque variable possde un identifiant (ladresse mmoire associe), et un type (la nature
de lobjet stock dans la variable). Lidentifiant change chaque raffectation, le type peut
changer lui-aussi. Les mthodes associes un objet peuvent le modifier sans changement
didentifiant.
type(a)
id(a)
int
float
omplex
bool
list
tuple
str
fun
tion
#
#
#
#
#
#
#
#
Par exemple :
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
19
>>> type(87877654)
<
lass 'int'>
>>> type(1.22)
<
lass 'float'>
>>> type(True)
<
lass 'bool'>
>>> type([1,2)
<
lass 'list'>
>>> type('ab
')
<
lass 'str'>
>>> type(lambda x:x*x)
<
lass 'fun
tion'>
Il existe dautres types dans des modules spcifiques, en particulier le type array du module
numpy, pour les tableaux et les matrices.
Certains objets dun type donn peuvent tre convertis en un autre type compatible. Conversions de type :
int(x)
# Convertit un objet x en nombre entier.
float(a)
# Convertit l'entier a en rel flottant
omplex(a)
# Convertit l'entier ou le flottant a en
omplexe
str(x)
# Convertit l'objet x de type quel
onque en
# une
hane de
ara
tres.
list(x)
# Convertit un l'objet x en liste.
tuple(x)
# Convertit un l'objet x en liste.
Par exemple :
>>> int('24')
24
>>> float(2)
2.0
>>>
omplex(2)
(2+0j)
>>> str([2,3,1)
'[2, 3, 1'
>>> str(77+2)
'79'
>>> list((1,2,3))
[1, 2, 3
>>> list('ens')
['e', 'n', 's'
>>> tuple('ab
')
('a', 'b', '
')
20
if test1:
instru
tions1
elif test2:
instru
tions2
elif test3:
instru
tions3
...
else:
instru
tions4
Les clauses elif (il peut y en avoir autant quon veut), ainsi que else sont facultatives.
La structure est comprendre comme suit :
Les intru
tions1 sont effectues uniquement si le test1 est True
Les instructions instru
tions2 sont effectues uniquement si le test1 est False et
le test2 est True
Les instructions instru
tions3 sont effectues uniquement si le test1 et le test2
sont False et le test3 est True
...
Les instructions instru
tions4 sont effectues dans tous les autres cas restants.
Le mot elif est comprendre comme une abrviation de else if. Ainsi, la structure prcdente est en fait quivalente une imbrication de structures conditionnelles simples :
if test1:
instru
tions1
else:
if test2:
instru
tions2
else:
if test3:
instru
tions3
else:
instru
tions4
21
for i in objet_iterable:
instru
tions
# qui peuvent dpendre de i
Par exemple :
for i in [1,2,5:
print(i)
va afficher les 3 valeurs 1, 2 et 5.
Le classique for i = 1 to n (ou similaire) quon trouve dans la plupart des langages se
traduit alors par :
for i in range(1,n+1):
instru
tions
Les itrateurs sont des objets grnant des valeurs les unes aprs les autres en les retournant
successivement. On peut utiliser ces valeurs successives grace linstruction for.
Litrateur le plus utile pour nous sera range, numrant des entiers dans un intervalle donn.
range(a,b,p)
range(a,b)
range(b)
for i in range(n):
instr
for i in liste:
instr
for i in
haine:
instr
La boucle while permet dobtenir un arrt de litration par un test. Il sagit en fait plutt
dune condition de continuation, puisquon itre la boucle tant quune certaine condition
est vrifie.
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
22
while
ond:
# Bou
le while, pour l'arrt des itrations par un test
instru
tions
Tant que la condition
ond est satisfaite, litration se poursuit.
Remarquez quune boucle for traditionnelle (de 1 n) peut se traduire aussi par une boucle
while :
i = 1
while i <= n:
instru
tions
i +=1
B Remarquer que lincrmentation i+=1 nest pas gr automatiquement (contrairement
la boucle for).
En revanche, ce nest pas le cas de la boucle for sur dautres objets itrables : on ne peut pas
systmatiquement avoir recours une boucle while.
2.4 Fonctions
Une fonction est un morceau de programme que lon isole, et quon peut faire dpendre de
paramtres. Cela permet de :
Dgager le coeur mme du programme de toute technique en isolant cette technique
dans des fonctions (clart et lisibilit du code)
Pouvoir rpter une certaine action plusieurs endroits dun mme programme, ou
mme dans des programmes diffrents (en dfinissant des fonctions dans des fichiers
spars quon importe ensuite)
Rendre certains actions plus modulables en les faisant dpendre de paramtres.
Une fonction prend en paramtres un certain nombre de variables ou valeurs et retourne un
objet (ventuellement None), calcul suivant lalgorithme donn dans sa dfinition. Il peut
aussi agir sur les variables ou les priphriques.
La syntaxe gnrale de la dfinition dune fonction est la suivante :
23
Cela permet par exemple de donner une fonction en paramtre, sans avoir la dfinir globalement par def.
Pour quune fonction donne plusieurs rsultats en sortie, il suffit des les donner dans une
liste :
return [x0 , x1 , ..., xn ]
24
1. Si, pour une boucle donne, on peut exhiber un variant de boucle, alors le nombre de
passages dans la boucle est finie.
2. Si, pour un algorithme donn, on peut exhiber, pour toute boucle de lalgorithme, un
variant de boucle, alors lalgorithme sarrte en temps fini.
B Il faut bien justifier la validit du variant de boucle pour toute valeur possible dentre.
La terminaison assure un arrt thorique de lalgorithme. En pratique, un deuxime paramtre entre en jeu : le temps de rponse. Ce temps de rponse sans tre infini, peut tre trs
grand (certains algorithmes exponentiels peuvent avoir un temps de rponse de lordre de
milliards dannes pour des donnes raisonnablement grandes !). videmment dans ce cas,
mme si lalgorithme sarrte en thorie, cest dassez peu dintrt.
Prenons comme exemple lalgorithme dEuclide qui calcule le PGCD deux entiers relatifs :
1
2
3
4
def eu
lide (a ,b ):
while b >0:
a ,b = b ,a %b
return a
La variable |b| est un variant de boucle, ce qui prouve la terminaison de cet algorithme.
2.5.2 Correction
La terminaison dun algorithme nassure pas que le rsultat obtenu est bien le rsultat attendu, cest- -dire que lalgorithme rpond bien la question pose initialement. Ltude
de la validit du rsultat quon obtient fait lobjet de ce paragraphe. On parle de ltude de la
correction de lalgorithme.
Reprenons lexemple de lalgorithme dEuclide. Cet algorithme a pour objet le calcul du pgcd
de a et b. La preuve mathmatique classique de la correction de lalgorithme repose sur la
constatation suivante : si r est le reste de la division euclidienne de a par b, alors a b = b r .
La preuve mathmatique de ce point ne pose pas de problme.
On constate alors que la quantit w = a b prend toujours la mme valeur lentre dune
boucle (correspondant aussi la valeur la sortie de la boucle prcdente). Cest le fait
davoir une valeur constante qui nous assure que la valeur initiale recherche a b, est gale
a b pour les valeurs finales obtenues pour a et b. Or, en sortie de boucle b = 0, donc
a b = a. Ainsi, le pgcd des valeurs initiales de a et b est gal la valeur finale de a.
De faon gnrale, ltude de la correction dun algorithme se fera par la recherche dune
quantit invariante dun passage lautre dans la boucle. On appellera donc invariant de
boucle une quantit w dpendant des variables x1 , . . . , xk en jeu ainsi ventuellement que du
compteur de boucle n, telle que :
la valeur prise par w en entre ditration, ainsi que la valeur quaurait pris w en cas
dentre dans litration suivant la dernire itration effectue, soit constante.
Si le passage initial dans la boucle est index 0 et que la dernire itration effectue
est indexe n 1, lgalit w 0 = w n permet de prouver que lalgorithme retourne bien
la quantit souhaite.
Dans le cas de lalgorithme dEuclide, la quantit w = a b est un invariant de boucle : il
est constant, et la sortie, puisque b = 0, il prend la valeur a. Ainsi, la valeur retourne par
lalgorithme est bien gal a b, pour les valeurs initiales de a et b, passes en paramtres.
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
25
3 Modules
3.1 Gnralits
De nombreuses fonctions sont dfinies dans des modules spcialises ; cela permet de ne
pas encombrer la mmoire de la dfinition de plein de fonctions dont on ne se servira pas.
On peut se contenter de charger (importer) les modules contenant les fonctions utilises (ou
mme selectionner les fonctions quon importe dans chaque module). De cette manire, on
peut dfinir un trs grand nombre de fonctions, sans pour autant alourdir lensemble.
Pour utiliser une fonction fon
t dun module mod, il faut importer cette fonction, ou le module entier avant lutilisation de cette fonction. Cela peut se faire de 3 manires.
Import simple du module :
import mod
#Cette instru
tion permet de faire savoir l'ordinateur qu'on
#utilise le module mod. On peut alors utilier les fon
tions
#de
e module en les faisant pr
der du prfixe mod (nom du
#module):
mod.fon
t()
Lutilisation de prfixes permet dutiliser des fonctions ayant ventuellement mme nom et
se situant dans des modules diffrents. Certains noms de module sont longs, ou seront utiliss trs souvent. On peut, au moment de limport du module, crer un alias, qui permettra
dappeler les fonctions de ce module en donnant comme prfixe lalias au lieu du nom complet :
import mod as al
al.fon
t()
Import dune fonction dun module :
26
3.2 Math
Le module math offre les fonctions et les constantes mathmatiques usuelles, rsumes dans
ce tableau :
Python
math.fa
torial(n)
math.fabs(x)
math.exp(x)
math.log(x)
math.log10(x)
math.pow(x, y)
math.sqrt(x)
math.sin(x)
math.
os(x)
math.tan(x)
math.asin(x)
math.a
os(x)
math.atan(x)
math.pi
math.e
mathmatiques
n!
|x|
r me x
ln(x)
log10 (x)
xy
p
x
sin(x)
cos(x)
tan(x)
arcsin(x)
arccos(x)
arctan(x)
3.3 Numpy
Dans toute la suite on supposera quon a effectu :
import numpy as np
3.3.1 Manipuler des listes et des matrices
numpy propose un type numpy.ndarray qui offre les fonctionnalits des listes de Python,
mais aussi des routines de calcul efficaces. Dans la suite nous appellerons tableau numpy
toute instance du type numpy.ndarray (ou plus simplement tableau ). Attention : contrairement aux listes, les lments dun tableau numpy doivent tous tre de mme type.
Cration de tableaux monodimensionnels
La fonction np.array transforme une liste Python en tableau numpy :
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
27
>>> u = [1, 4, 6, 2
>>> type (u)
<type 'list'>
>>> t = np.array (u)
>>> t
array([1, 4, 6, 2)
>>> type (t)
<type 'numpy.ndarray'>
La fonction np.zeros cre un tableau compos uniquement de zros, le nombre dlments
tant pass en paramtre. Par dfaut les lments sont de type float mais on peut le modifier avec le paramtre facultatif dtype.
>>> np.zeros(5)
array([ 0., 0., 0., 0., 0.)
>>> np.zeros(5, dtype = int)
array([0, 0, 0, 0, 0)
La fonction np.ones fonctionne de la mme manire que np.zeros sauf que les lments
sont tous gaux 1.
>>> x=np.arange(0,1,0.3)
>>> x
array([ 0., 0.3,
0.6,
0.9)
28
La fonction np.eye prend en paramtre un seul entier, et renvoie la matrice identit : les
coefficients de la diagoanle principale sont gaux 1, les autres 0.
>>> np.eye(3)
array([[ 1., 0., 0.,
[ 0., 1., 0.,
[ 0., 0., 1.)
La fonction np.diag prend en paramtre une liste [t0 , . . . , tn1 ] (ou un tableau numpy) et renvoie la matrice diagonale ayant les lments ti sur la diagonale et des zros ailleurs :
>>> np.diag([5, 7,
array([[5,
[0,
[0,
2)
0, 0,
7, 0,
0, 2)
Accs un lment
Accs un lment dun tableau monodimensionnel :
>>> t=np.array([3,7,1)
>>> t[2
1
>>> t[-1=20
>>> t
array([ 3, 7, 20)
Accs un lment dun tableau bidimensionnel :
>>> x=np.array([3,4)
>>> np.exp(x)
array([ 20.08553692, 54.59815003)
>>> import math
>>> math.exp(x)
TypeError: only length-1 arrays
an be
onverted to Python s
alars
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
29
Lorsque la fonction f ne dispose pas dquivalent numpy (par exemple si elle a t cre par
lutilisateur), on peut la vectorialiser grce linstruction np.ve
torize(f). Exemple :
>>> x=np.array([3,4)
>>> np.ve
torize(bin)(x)
array(['0b11', '0b100',
dtype='|S5')
Quand les paramtres sont des tableaux numpy, les oprations usuelles (+, , , /, ) effectuent les oprations coefficient par coefficient.
>>> 3+a
>>> 3*a
array([[4, 5,
[6, 7)
array([[ 3, 6,
[ 9, 12)
30
Les oprateurs , /, de numpy ne correspondent pas du tout aux oprations matricielles mathmatiques. Ils effectuent simplement un produit (ou une division ou une
mise la puissance) coefficient par coefficient. Pour les oprations matricielles mathmatiques, se rfrer cidessous la section quelques outils dalgbre linaire .
Slicing, vues, copies
Il est possible de slectionner une sous-matrice en ne gardant que certaines lignes conscutives et/ou certaines colonnes conscutives.
Un intervalle dindices est dune des formes suivantes :
debut:fin:pas (les indices entre debut inclus et fin exclu, spars par la valeur
pas) ;
debut:fin (tous les indices entre debut inclus et fin exclu) ;
debut: (tous les indices depuis debut inclus) ;
:fin (tous les indices jusqu fin exclu) ;
: (tous les indices) ;
i (seulement lindice i).
La syntaxe matri
e[intervalle d'indi
es de lignes, intervalle d'indi
es de
olonnes permet de crer une sous-matrice correspondant aux lignes et aux colonnes
slectionnes.
>>> a = m[1:, 1:
>>> a
array([[7, 2, 4,
[1, 2, 6)
>>> a[0,0 = 20
>>> m
array([[ 1, 2, 5, 3,
[ 4, 20, 2, 4,
[ 3, 1, 2, 6)
>>> a[:,:2 = np.eye(2)
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
31
>>> a
>>> m
array([[1, 0, 4,
[0, 1, 6)
array([[1, 2, 5, 3,
[4, 1, 0, 4,
[3, 0, 1, 6)
On constate dans lexemple prcdent quune vue peut servir de membre de gauche dune
affectation. Si on veut une duplication des lments dune matrice numpy, on utilise la fonction np.
opy :
1:)
5, 3,
0, 4,
1, 6)
32
3.3.2 Quelques outils dalgbre linaire
Produit matriciel
Syntaxe de lappel : numpy.dot(matri
e A, matri
e B)
Valeur de retour : le produit matriciel A.B
B Loprateur * effectue une multiplication terme terme des lments des deux matrices,
et na donc rien voir avec un produit matriciel.
Exemple :
33
-1.80143985e+15,
1.80143985e+15,
1.80143985e+15,
-1.80143985e+15,
Les valeurs trs grandes laissent tout de mme planer un certain soupon.
Rsolution dun systme de Cramer
Syntaxe de lappel : numpy.linalg.solve(matri
e A, ve
teur B)
Valeur de retour : le vecteur X solution de AX = B
Exemple, rsolution de
x + 2y = 2
3x + 4y = 8
34
Dterminant
Syntaxe de lappel : numpy.linalg.det(matri
e A)
Valeur de retour : le dterminant de A, de type float
Exemple :
>>> np.transpose([[1,2,[3,4)
array([[1, 3,
[2, 4)
Autre possibilit :
>>> A = np.array([[1,2,[3,4)
>>> A.T
array([[1, 3,
[2, 4)
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
35
Outils de deuxime anne
npr.randint(a)
36
La fonction binomial permet de simuler une variable alatoire suivant une loi binomiale
de paramtres n et p. Elle permet donc galement de simuler une variable alatoire suivant
une loi de Bernoulli de paramtres p en prenant simplement n = 1. Cette fonction prend un
troisime paramtre optionnel qui correspond, comme pour les fonctions prcdentes, au
nombre de valeurs obtenir.
3.3.4 Polynmes
Le sous-module numpy.polynomial.polynomial permet de travailler avec des polynmes :
>>> p = Polynomial([-3, 2, 0, 1)
On peut alors utiliser cette variable comme une fonction pour calculer, en un point quelconque, la valeur de la fonction polynme associe. Cette fonction peut agir galement sur
un tableau de valeurs, elle calcule alors la valeur de la fonction polynme en chacun des
points indiqus.
>>> p(0)
-3.0
>>> p([1, 2, 3)
array([ 0., 9., 30.)
Lattribut
oef donne accs aux coefficients ordonns par degr croissant ; ainsi p.
oef[i
correspond au coefficient du terme de degr i . La mthode degree renvoie le degr du polynme alors que roots calcule ses racines.
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
37
>>> p.
oef
array([-3., 2., 0., 1.)
>>> p.
oef[1
2.0
>>> p.degree()
3
>>> p.roots()
array([-0.5-1.6583124j, -0.5+1.6583124j,
1.0+0.j)
La mthode deriv renvoie un nouveau polynme, driv du polynme initial. Cette mthode prend en argument facultatif un entier positif indiquant le nombre de drivations
effectuer. De la mme manire la mthode integ intgre le polynme, elle prend un paramtre optionnel supplmentaire donnant la constante dintgration utiliser, ce paramtres
peut tre une liste en cas dintgration multiple ; les constantes dintgration non prcises
sont prises gales zro.
>>>
>>>
>>>
>>>
a = Polynomial([1, 2, 1)
b = Polynomial([5, 3)
p = 2*a * b + Polynomial([-7, 2)
p.
oef
array([ 3., 28., 22., 6.)
>>> (p**2).
oef
array([9., 168., 916., 1268., 820., 264., 36.)
Loprateur / permet de diviser un polynme par un scalaire. Pour diviser deux polynmes
il faut utiliser loprateur // qui renvoie le quotient ; loprateur % calcule le reste.
38
>>> q.
oef
array([ 10., 6.)
>>> r.
oef
array([-7., 2.)
>>> (q * a + r).
oef
array([ 3., 28., 22., 6.)
3.4 Random
Pour crer un nombre alatoire, on peut aussi utiliser le module random. Exemple :
plt.plot(L1,L2, label='nom')
39
1
2
3
4
5
6
7
x = [1. , 2.5 , 4.
y = [3. , 1. , 5.
plt . axis ( ' equal ')
plt . plot (x , y)
plt . axis ([ -1. , 5. , -1. , 6.)
plt . grid ()
plt . show ()
La fonction plot admet de nombreuses options de prsentation. Le paramtre
olor permet de choisir la couleur ('g' : vert, 'r' : rouge, 'b' : bleu). Pour dfinir le style de la ligne,
on utilise linestyle ('-' : ligne continue, '--' : ligne discontinue, ':' : ligne pointille).
Si on veut marquer les points des listes, on utilise le paramtre marker ('+', '.', 'o', 'v'
donnent diffrents symboles).
6
5
x = [1. , 2.5 , 4.
y = [3. , 1. , 5.
plt . axis ([ -1. , 5. , -1. , 6.)
plt . plot (x , y ,
olor = 'r ',
linestyle = ': ', marker = 'o ')
5 plt . show ()
1
2
3
4
4
3
2
1
0
1
1
Tracs de fonction
Pour tracer la courbe reprsentative dune fonction, on dfinit une liste dabscisses puis on
construit la liste des ordonnes correspondantes. Lexemple ci-dessous trace la courbe de
x 7 sin x sur [0, 3].
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
40
1
2
3
4
5
6
7
import math
import numpy as np
def f(x ):
return math . sin ( x)
1.0
0.5
0.0
X = np . arange (0 , 3* np .pi ,
0.01)
8 Y = [ f (x ) for x in X
9 plt . plot (X , Y)
10 plt . show ()
0.5
1.0
0
10
Une autre solution consiste utiliser la fonction ve
torize du module numpy qui permet de
transformer une fonction scalaire en une fonction capable de travailler avec des tableaux. Il
est cependant beaucoup plus efficace dutiliser directement des fonctions universelles.
1
2
3
4
def f(x ):
return math . sin ( x)
f = np . ve
torize ( f)
Il est noter que les oprateurs python (+, -, *, etc.) peuvent sappliquer des tableaux, ils
agissent alors terme terme. Ainsi la fonction f dfinie ci-dessous est une fonction universelle, elle peut travailler aussi bien avec deux scalaires quavec deux tableaux et mme avec
un scalaire et un tableau.
1
2
def f(x , y) :
return np . sqrt (x **2 + y **2)
>>> f(3, 4)
5.0
>>> f(np.array([1, 2, 3), np.array([4, 5, 6))
array([ 4.12310563, 5.38516481, 6.70820393)
>>> f(np.array([1, 2, 3), 4)
array([ 4.12310563, 4.47213595, 5.)
41
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
def x(t ) :
return np . sin (2* t)
def y(t ) :
return np . sin (3* t)
1.0
0.5
0.0
T = np . arange (0 , 2* np .pi ,
0.01)
X = x(T )
Y = y(T )
plt . axis ( ' equal ')
plt . plot (X , Y)
plt . show ()
0.5
1.0
1.0
0.5
0.0
0.5
1.0
5
4
3
2
1
0
1.0
0.5
1.0
0.0
0.5
0.0
0.5
0.5
1.0
1.0
Trac de surfaces
Pour tracer une surface dquation z = f (x, y), on ralise dabord une grille en (x, y) puis on
calcule les valeurs de z correspondant aux points de cette grille. On fait ensuite le trac avec
la fonction plot_surfa
e.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
from mpl_toolkits . mplot3d
import Axes3D
1.0
0.5
def f(x ,y ) :
return x **2 - y **2
0.0
0.5
X = np . arange ( -1 , 1, 0.02)
Y = np . arange ( -1 , 1, 0.02)
X , Y = np . meshgrid (X , Y )
Z = f(X , Y)
ax . plot_surfa
e (X , Y , Z )
plt . show ()
1.0
1.0
0.5
1.0
0.0
0.5
0.0
0.5
0.5
1.0
1.0
42
Trac de lignes de niveau
Pour tracer des courbes dquation f (x, y) = k, on fait une grille en x et en y sur laquelle on
calcule les valeurs de f . On emploie ensuite la fonction
ontour en mettant dans une liste
les valeurs de k pour lesquelles on veut tracer la courbe dquation f (x, y) = k.
1
2
3
4
5
6
7
8
9
10
11
import numpy as np
def f(x ,y ):
return x **2 + y **2 + x*y
X = np . arange ( -1 , 1, 0.01)
Y = np . arange ( -1 , 1, 0.01)
X , Y = np . meshgrid (X , Y )
Z = f(X , Y)
plt . axis ( ' equal ')
plt .
ontour (X , Y , Z ,
[0.1 ,0.4 ,0.5)
12 plt . show ()
0.5
0.0
0.5
1.0
1.0
0.5
0.0
0.5
1.0
s
ipy.integrate.quad(f,a,b)
s
ipy.optimize.newton(f,a,g)
# intgrale de f de a b
# rsolution d'quation par la mthode de Newton
# initialise au point a
# g doit tre gal f'
s
ipy.integrate.odeint(f,y0,T)
# Rsolution de l'ED y'=f(y,t)
# y0 est la valeur initial (t minimal)
# T est un tableau des temps auquels
#
al
uler les valeurs de y
Rsolution approche dquations
Pour rsoudre une quation du type f (x) = 0 o f est une fonction dune variable relle,
on peut utiliser la fonction fsolve du module s
ipy.optimize. Il faut prciser la valeur
initiale x0 de lalgorithme employ par la fonction fsolve. Le rsultat peut dpendre de cette
condition initiale.
1
2
3
4
43
def f(v ):
return v [0**2 - v [1**2 - 1, v [0 + 2* v [1 - 3
1
2
3
4
5
import as np
import s
ipy . integrate as integr
def f(x ) :
return np . exp (-x )
>>> integr.quad(f, 0, 1)
(0.6321205588285578, 7.017947987503856e-15)
>>> integr.quad(f, 0, np.inf)
(1.0000000000000002, 5.842607038578007e-11)
Rsolution approches dquations diffrentielles
Pour rsoudre une quation diffrentielle x = f (x, t ), on peut utiliser la fonction odeint du
module s
ipy.integrate. Cette fonction ncessite une liste de valeurs de t, commenant
en t0 , et une condition initiale x0 . La fonction renvoie des valeurs approches (aux points
contenus dans la liste des valeurs de t) de la solution x de lquation diffrentielle qui vrifie x(t0 ) = x0 . Pour trouver des valeurs approches sur [0, 1] de la solution x (t ) = t x(t ) qui
vrifie x(0) = 1, on peut employer le code suivant.
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
44
1
2
3
4
5
6
import numpy as np
import s
ipy . integrate as integr
import matplotlib. pyplot as plt
def f(x , t) :
return t *x
1.7
1.6
1.5
1.4
1.3
1.2
1.1
1.0
0.0
0.2
0.4
0.6
0.8
1.0
x (t ) = x(t ) y(t )
avec la condition
y (t ) = x(t ) y(t )
45
1.2
1.0
0.8
0.6
0.4
0.2
0.0
0.2
0.5
0.0
0.5
1.0
1.5
2.0
time.time()
46
Le rsultat de la requte est contenu dans la variable res qui est un tuple de tuples : chaque
ligne de rponse de la requte est donne par un tuple ; un tuple contient toutes les rponses.
On peut parcourir les rponses avec une boucle for :
def re
her
he (t ,x ):
n= len (t)
i =0
while i < n and t[ i != x : # valuation paresseuse de and
i +=1
if i < n:
return i
else :
print False
Si on sautorise les sorties de boucle avec linstruction return, on peut utiliser une boucle
for :
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
47
1
2
3
4
5
6
def re
her
he (t ,x ):
n= len (t)
for i in range (n ):
if t [i == x:
return i # on arr te l ' algorithme
return False #
ette ligne n ' est atteinte que si x n '
appartient pas t
Pour valuer les performances de cet algorithme, notons cn le nombre de tests effectus pour
une liste t de taille n. Il est clair que cn = 1 dans le meilleur des cas (t[0=x), et que cn = n
dans le pire des cas (x est le dernier lment).
48
Pour valuer les performances de cet algorithme, notons cn le nombre de tests effectus pour
une liste t de taille n. Il est clair que cn = n dans tous les cas.
X
1 n1
tk
n k=0
et sa variance par :
v=
On en dduit les programmes :
1
2
3
4
5
6
X
2
1 n1
tk m
n k=0
et :
1
2
3
4
5
6
7
49
3
4
5
6
7
8
9
10
11
12
13
14
15
a =0
b=n -1
if t[ a> x or t[b <x : #
as triviaux o x n ' est pas dans t
return False
else :
while b -a >0:
# on
her
he dans t[ a:b
=( a+ b) /2 # Python 2.7
if t[
== x: # x est au milieu
return
# on a trouv x !!
elif t[
>x : # x est dans la partie gau
he
b =
-1
else :
# x est dans la partie droite
a =
+1
p
2 la prcision 103 :
50
xn+1 = xn
f (xn )
f (xn )
On arrte lalgorithme ds que la diffrence entre deux termes conscutifs est assez petite.
1
2
3
4
5
6
Par exemple :
51
4.8 Calcul de valeur approches dintgrales sur un segment par la mthode des rectangles ou des trapzes
Le but est de calculer une valeur approche de lintgrale
nue sur un segment [a, b].
Zb
a
On peut utiliser la mthode des rectangles : on calcule une valeur approche de lintgrale
en ralisant une somme de surfaces de rectangles. Le domaine dintgration est dcoup en
intervalles [xk , xk+1 ] et on fait comme si la fonction restait constante sur chaque intervalle.
Sur chaque intervalle, on ralise ainsi lapproximation suivante :
Zxk+1
xk
f (t ) dt (xk+1 xk ) f (xk )
Zb
a
k=0
ba
et lapproximation devient :
n
X
ba
b a n1
f a +k
n k=0
n
La mthode des trapzes, comme son nom lindique, consiste remplacer les rectangles par
des trapzes.
52
f (x) dx
n1
X
k=0
(xk+1 xk )
f (xk ) + f (xk+1 )
2
X
ba
ba
b a n1
f a +k
+ f a + (k + 1)
2n k=0
n
n
Pour viter de nombreux appels f on peut arranger la formule sous cette forme :
"
#
X
b a f (a) + f (b) n1
ba
f a +k
+
n
2
n
k=1
On en dduit les programmes Python :
1
2
3
4
5
6
et :
1
2
3
4
5
6
def trapezes (f ,a ,b ,n ):
""" approximation de l ' int grale de f entre a et b ave
n
trap zes """
I =(b - a) *( f (a ) + f( b) ) /(2.* n )
# Python 2.7
for k in range (1 , n) :
I += (b -a ) * f( a +k *(b - a) / float (n) ) / float (n)
#
Python 2.7
return I
53
Intuitivement la prcision sera meilleure pour de grandes valeurs de n. De plus cest la mthode des trapzes qui devrait converger le plus rapidement. On peut le vrifier sur un exemple :
54
Rechercher un algorithme donnant une erreur acceptable, en un temps raisonnable
Contrler prcisment lerreur
Trouver un compris entre temps de calcul et prcision.
et
ba
le pas constant de la subdivision, on peut rcrire la relation de rcurn
k 0, n 1,
u k+1 = h. f (xk , u k ) + u k
55
Le code Python est le suivant :
1
2
3
4
5
6
7
8
En sortie on rcupre le vecteur des piquets de temps, et le vecteur des valeurs approches
de y.
Par exemple appliquons cette mthode pour le problme de Cauchy
valle [0, 5], et comparons la solution approche et la solution exacte.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
y = y
sur lintery(0) = 1
On voit sur la figure suivante que la solution approche diverge au cours du temps.
Dans certains cas, on peut avoir besoin dutiliser cette mthode pour des fonctions valeurs
vectorielle (cest--dire valeurs dans R2 , R3 . . .). La mthode dEuler est la mme, la fonction
Python est donc la mme mais il faut prendre garde une chose : loprateur + neffectue pas
laddition de deux liste mais leur concatnation !
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
56
Pour utiliser des fonctions vectorielles, il faut donc ne pas utiliser des variables de type list
mais des variables du type array fourni par le module numpy (dans le cas loprateur + correspond bien laddition de deux tableaux).
x1 (t ) = x1 (t ) x2 (t )
x2 (t ) = x1 (t ) x2 (t )
avec la condition initiale x1 (0) = 2, x2 (0) = 1, on considre que la fonction y = (x1 , x2 ) est
solution de y = f (t , y) o f (t , , ) = ( , ). Le code devient le suivant :
1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np
def f(t ,y ):
return np . array ([ - y [0 - y [1 , y [0 - y [1)
def Euler_ve
t(f ,a ,b ,y0 ,n ):
y= np . zeros (( n ,2) )
#
ette ligne a
hang
t =[ a +k* float (b - a) /( n -1) for k in range (n)
y [0= y0
for k in range (1 , n) :
y [k = y[k -1+( b - a) / float (n -1) *f( t[k -1 , y [k -1)
return t ,y
>>>
>>>
>>>
>>>
>>>
57
Le cas des fonctions vectorielles englobe aussi le cas des quations diffrentielles dordre
deux, quon peut ramener lordre un par vectorialisation. Par exemple, considrons lquation x + x = 0 avec les conditions initiales x(0) = 0 et x (0) = 1. La fonction vectorielle
y = (x, x ) vrifie lquation diffrentielle dordre un y = f (t , y) avec f (t , , ) = (, ). On
dfinit en Python la fonction f :
1
2
def f(t ,y ):
return np . array ([ y [1 , -y [0)
np.array([0.,1.), 400)
>>>
>>>
>>>
>>>
58
Ds maintenant, il faut bien comprendre le rle de lquivalence, qui assure que le systme
initial et le systme final ont les mmes solutions.
La rsolution dun systme linaire quelconque passera systmatiquement par une premire
tape pour le mettre sous forme triangulaire en gardant lquivalence avec le systme initial.
Si une quation disparat ou bien fournit une contradiction, alors on peut en conclure
que :
Si lquation 0 = 0 apparat, on peut lliminer du systme en gardant lquivalence.
Si lquation 0 = apparat (avec 6= 0), le systme initial nadmet pas de solution
Pour un systme de Cramer, ces situations ne se prsenteront pas.
La rsolution dun systme triangulaire sera la dernire tape (la plus simple et rapide) de
la rsolution dun systme linaire. On lappelle souvent phase de remonte : on rsout les
quations de bas en haut, en substituant aux inconnues les valeurs trouves dans les lignes
infrieures.
Pour mettre un systme sous forme triangulaire, on va raliser des transvections, cest--dire
des oprations lmentaires de la forme suivante : ajouter tant de fois telle quation telle
autre , afin dliminer une inconnue dans des quations... mais pas dans le dsordre !
On va dcrire ces oprations pour un systme 3 3 dinconnues (x, y, z) dans une situation
favorable, en notant L 1 , L 2 et L 3 les trois quations en jeu. On suppose que le coefficient
en x de la premire quation, appel a, est non nul. On va sen servir comme pivot pour
liminer les autres occurrences de x. Si on note b et c les coefficients en x des deuxime
b
c
et troisime lignes, le systme constitu des quations L 1 , L 2 = L 2 L 1 et L 3 = L 3 L 1
a
a
est alors quivalent au premier et ne fait apparatre x que dans la premire quation. En
supposant que le coefficient en y de la nouvelle deuxime ligne L 2 , appel d , est non nul
(cest alors le nouveau pivot) et en notant e celui de y dans la nouvelle troisime ligne L 3 ,
e
le systme constitu des lignes L 1 , L 2 et L 3 = L 3 L 2 est quivalent au premier systme et
d
triangulaire : on est ramen un cas quon sait traiter.
Lors de la premire tape, on ne touche pas la premire ligne. De mme, la deuxime
tape, on ne touche ni la premire ni la deuxime ligne, et ainsi de suite.
Dans lexemple qui suit, on adopte une notation classique : pour dire quon change la seconde ligne L 2 en L 2 = L 2 + L 1 , on prfrera noter L 2 L 2 + .L 1 . Cela signifie quon appelle dsormais L 2 ce que dsignait auparavant L 2 + L 1 . Aprs cinq oprations de ce type,
on parlera donc toujours de L 8 plutt que de L
8 .
59
Dans les cas moins favorables, on peut rencontrer en cours de rsolution dun systme 3 3
ces trois problmes :
Le pivot nest pas l o on veut : si, la premire tape, le coefficient en x de la premire ligne est nul, on peut changer la premire quation avec la deuxime ou la
troisime. De mme, si la seconde tape, le coefficient en y (futur pivot) est nul, on
peut changer la deuxime quation avec la troisime, mais pas la premire (se souvenir quon veut arriver un systme triangulaire : il ne faut pas faire rapparatre x
dans les deux dernires quations).
Il ny a plus de pivot en une variable : si tous les coefficients en x sont nuls (cest rare :
cela revient dire que x napparat pas dans le systme...), on peut prendre y ou z
comme premire variable. De mme, si aprs la premire tape, y napparat ni dans
la deuxime ni dans la troisime quation, on peut prendre z comme deuxime inconnue.
Il ny a plus de pivot : cela signifie que les membres de gauche des quations restantes
sont nuls. Selon que les membres de droite correspondants sont nuls ou pas, ces quations vont disparatre ou bien rendre le systme incompatible.
Les deux dernires situations ne se produiront pas sur un systme de Cramer.
Pour la recherche dun pivot, il faudrait tester la nullit des coefficients sur une colonne. . .mais
tester la nullit dun flottant na pas de sens en informatique ! On prfre donc chercher sur
la colonne en cours le coefficient le plus lev en valeur absolue (ou module). Cela sappelle
la mthode du pivot partiel.
On fait ici lhypothse que le systme initial est de Cramer. Il est important de noter que les
oprations ralises vont introduire des systmes quivalents au premier, qui demeureront
donc des systmes de Cramer.
Comme signal plus haut, on veut liminer des variables dans les quations successives. On
va donc faire en sorte quaprs k tapes, pour tout i entre 1 et k, la i -ime variable ait disparu
de toutes les quations du systme partir de la (i + 1)-ime. Ce sera linvariant de boucle.
Ainsi, aprs la (n 1)-ime tape, le systme sera bien sous forme triangulaire.
Dans le pseudo-code qui suit, on rsout le systme Ax = y. La ligne L i dsigne la fois
les coefficients de A (qui sont dans une matrice, un tableau bidimensionnel) et les seconds
membres, qui sont dans une matrice colonne y. Les indexations de tableaux vont de 0 n 1
comme en Python :
Pour i de 0 n 2 faire
Trouver j entre i et n 1 tel que |a j ,i | soit maximale.
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
60
changer L i et L j (coefficients de la matrice et membres de droite).
Pour k de i + 1 n 1 faire
a
L k L k ak,i L i
i ,i
Fin Pour
Fin Pour
Rechercher j entre i et n tel que |a j ,i | soit maximale (puis changer deux lignes) a deux
objectifs : dune part sassurer que le coefficient en position (i , i ) sera diffrent de 0 (cest
essentiel pour pouvoir pivoter) et, dautre part, minimiser les erreurs numriques dans la
suite du calcul.
Arriv ici, le systme est sous forme triangulaire et il ny a plus qu remonter , via des
substitutions. Le rsultat est mis dans un tableau x et il sagit donc de calculer :
!
n1
X
1
ai ,k xk
yi
xi =
ai ,i
k=i +1
Pour i de n 1 0 faire
Pour k de i + 1 n 1 faire
y i y i ai ,k xk
Fin Pour
y
xi a i
i ,i
Fin Pour
Dans les programmes Python, les matrices seront reprsents par des listes de listes. Par
exemple la matrice 2 3 suivante :
0 1 2
M=
3 4 5
peut tre dfinie en Python par le tableau m ci-aprs :
m = [[0, 1, 2, [3, 4, 5
On accde llment Mi ,j avec lexpression m[i[j.
Comme les listes sont modifies en place, les fonctions ne renverront rien.
Le premier programme Python prend en entre une matrice A et un indice i. Il doit renvoyer
un indice j i tel que |aj,i | soit maximale :
1
2
3
4
5
6
7
61
Enfin viennent les transvections. Comme pour la fonction prcdente, la matrice fournie en
entre est modifie en place, la fonction ne renvoyant rien. En particulier, lappel se fera via
transve
tion_ligne(A,i,j,mu), et non via A = transve
tion_ligne(A,i,j,mu) :
1
2
3
4
5
def resolution(A , Y) :
""" R solution de A. X=Y ; A doit etre inversible """
n = len (A)
# Mise sous forme triangulaire
for i in range (n ):
j =
her
her_pivot (A , i )
if j > i:
e
hange_lignes (A , i , j)
e
hange_lignes (Y , i , j)
for k in range (i +1 , n):
x = A [k [ i / float (A [i [ i )
transve
tion_ligne (A , k , i , -x )
transve
tion_ligne (Y , k , i , -x )
# Phase de remont e
X = [0. * n
for i in range (n -1 , -1, -1) :
somme =0.
for j in range (i +1 , n ):
somme += A [i [ j * X [j
X [i = (Y [i [0 - somme ) / A[i [ i
return X
B Les variables A et Y sont modifies en place par la fonction prcdente. Si on souhaite les
garder intactes, il faut en faire une copie ds le dbut du programme. . .
Testons sur un exemple :
>>> resolution([[2,2,-3,[-2,-1,-3,[6,4,4,[[2,[-5,[16)
[-14.000000000000036, 21.000000000000046, 4.000000000000007
Il est clair que la complexit de lalgorithme, en prenant en compte les comparaisons, affectations et oprations arithmtiques, vrifie cn = (n 3 ).
62
>>> import os
>>> os.get
wd()
'/home/arno/Dropbox/PSI/Python/Cours_Arnaud'
Changer de rpertoire :
63
6 Bases de donnes
6.1 Gnralits
Il sagit de stocker des donnes de faon adapte, de sorte :
pouvoir facilement faire des recherches
prendre le moins de place possible en mmoire.
Un attribut dune base de donne est une des caractristiques dont on souhaite enregistrer
la valeur, lors dune entre. Ainsi, il sagit du nom des diffrentes colonnes.
On reprsente souvent une relation sous forme dune table, comme nous lavons fait prcdemment. Ainsi, le schma relationnel dfinit les noms des colonnes dune table, et le type
des entres de chaque colonne, alors que la relation est lensemble des donnes entres dans
la table. Un enregistrement (ou une valeur) correspond une ligne de la table. Le cardinal de
la relation est le nombre de lignes dans la table.
Une cl primaire est un attibut tel que les valeurs prises par cet attribut dterminent toutes
les autres valeurs de lenregistrement (donc dterminent toute les lignes).
64
65
'luth'
'violon
elle'
'violon'
'viole de gambe'
'
lave
in'
'piano'
'orgue'
'flte'
'hautbois'
'baryton'
'soprano'
'
larinette'
'
or'
'basson'
'haute-
ontre'
Linstruction suivante :
66
'BAC 1',
'HAE 1',
'SCA 1',
'Ba
h',
'Haendel',
'S
arlatti',
'Johann Sebastian',
'Georg Friedri
h',
'Domeni
o',
1685,
1685,
1685,
1750
1759
1757
Par ailleurs, on peut utiliser des oprations sur les attributs, soit pour exprimer des tests, soit
pour former de nouvelles colonnes. Former de nouvelles colonnes se fait en indiquant dans
la clause SELECT les oprations faire partir des autres attributs pour crer cette colonne.
+ * - /
Voici quelques exemples. Retourner Nom Prnom pour les compositeurs morts entre 1820
et 1830 :
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
67
SELECT nom, prenom FROM
ompositeur WHERE mort >= 1820 AND mort <= 1830 ;
On obtient :
'Beethoven',
'S
hubert',
'Ludwig (Van)'
'Franz'
'Couperin',
'Ba
h',
'Haendel',
'Franois'
'Johann Sebastian'
'Georg Friedri
h'
Certaines oprations mathmatiques portant sur lensemble des valeurs dun attribut sont
possibles. Ce sont les fonctions agrgatives :
COUNT(*)
COUNT(ATTR)
AVG(ATTR)
SUM(ATTR)
MIN(ATTR)
MAX(ATTR)
# nombre de lignes
# nombre de lignes remplies pour
et attribut
# moyenne
# somme
# minimum
# maximum
Les fonctions agrgatives servent dfinir de nouvelles colonnes, mais ne peuvent pas tre
utilises dans une condition. Par exemple, nom et ge du composteur mort le plus vieux :
'Ysae', 93
Les fonctions agrgatives peuvent sutiliser avec linstruction GROUP BY Att HAVING Cond
permettant de calculer les fonctions agrgatives sur des paquets de donnes prenant la mme
valeur pour lattribut Att, en ne gardant que les lignes vrifiant la condition Cond.
Par exemple, date de la premire sonate pour des compositeurs avant N dans lordre alphabtique :
68
SELECT id
omp FROM
ompositeur WHERE naissan
e>=1700 AND naissan
e<=1800
INTERSECT
SELECT DISTINCT
ompositeur FROM oeuvre WHERE type = 'sonate' ;
Une intersection peut souvent se reexprimer plus simplement avec une sous-requte et une
opration boolenne AND. Cela peut tre efficace lorsquon veut croiser deux tables compltes (par exemple deux tables de clients de deux filiales) :
69
SELECT nom, prenom, oeuvre FROM
ompositeur, oeuvre WHERE id
omp =
ompositeur
Rsultat partiel :
SELECT nom, prenom, oeuvre FROM
ompositeur JOIN oeuvre ON id
omp =
ompositeur ;
On peut combiner cette jointure avec une slection conditionnelle WHERE. Par exemple, oeuvres
crites par un compositeur moins de 18 ans :
SELECT nom, prenom, oeuvre FROM
ompositeur JOIN oeuvre ON id
omp =
ompositeur
WHERE date - naissan
e <= 18 ORDER BY nom ;
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
70
On peut faire des jointures successives si on veut des attributs de tableaux plus loigns, ou
si on veut extraire des donnes de plus de deux tables :
On a dja vu HAVING, qui effectue une slection en aval dune agrgation. Par exemple, donner les moyennes par filire :
SELECT filiere,AVG(noteba
) FROM eleve GROUP BY filiere HAVING AVG(noteba
) > 14.4 ;
Voyons un exemple quivalent celui plus haut, mais sans HAVING :
SELECT filiere,moy
FROM (SELECT filiere,AVG(noteba
) FROM eleve GROUP BY filiere)
WHERE AVG(noteba
)>14.4 ;
Ici, on effectue une premire requte ( lintrieur des parenthses) produisant des lignes
de la forme filiere, moyenne, puis on rutilise immdiatement la table produite dans une
nouvelle requte. Celle-ci est quivalente la premire et produit le mme rsultat.
Il faut bien comprendre quappliquer des requtes une table produit une nouvelle table !
Un autre exemple est le suivant : quels sont les lves ayant eu la plus haute note au bac ? Ici,
il faut rcuprer dabord la plus haute note au bac, puis refaire une requte pour slectionner
les lves ayant eu cette note. En SQL, on obtient :
71
72
Chapitre 2
Cours de deuxime anne
1 Piles
1.1 Gnralits
En informatique, une pile (en anglais stack) est une structure de donnes fonde sur le principe dernier arriv, premier sorti (ou LIFO pour Last In, First Out ), ce qui veut dire que
les derniers lments ajouts la pile seront les premiers tre rcuprs.
Le fonctionnement est celui dune pile dassiettes : on ajoute des assiettes sur la pile, et on
les rcupre dans lordre inverse, en commenant par la dernire ajoute.
Sur la figure suivante on empile A puis B et ensuite on dpile dans lordre B, puis A.
73
74
Les Piles ont beaucoup dapplications :
Dans un navigateur web, une pile sert mmoriser les pages Web visites. Ladresse
de chaque nouvelle page visite est empile et lutilisateur dsempile ladresse de la
page prcdente en cliquant le bouton Afficher la page prcdente .
Lvaluation des expressions mathmatiques en notation post-fixe (ou polonaise inverse) utilise une pile.
La fonction Annuler la frappe (en anglais Undo) dun traitement de texte mmorise
les modifications apportes au texte dans une pile.
Un algorithme de recherche en profondeur dans un graphe utilise une pile pour mmoriser les nuds visits.
Par exemple, on peut trs simplement inverser les lments contenus dans un tableau
ou dans une chane de caractres (pour tester un palindrome) en utilisant une pile. Il
suffit dempiler les lments sur une pile puis de reconstituer le tableau (ou la chane)
inverse en dsempilant les lments.
Un des gros avantages des piles est quil nest pas ncessaire de connatre lavance la taille
de la pile, cest--dire le nombre dlments quon va empiler.
1.2 Primitives
Pour manipuler les Piles, on dispose des fonctions suivantes, appeles primitives.
Trois primitives indispensables :
Empiler. Ajoute un lment sur la pile. Terme anglais correspondant : Push .
La pile est-elle vide ? Renvoie vrai si la pile est vide, faux sinon. Terme anglais isempty .
Dautres primitives peuvent tre obtenues partir des 3 premires :
Nombre dlments de la pile. Renvoie le nombre dlments dans la pile.
Quel est llment de tte ? Renvoie llment de tte sans le dpiler. Terme anglais correspondant : Peek .
Vider la pile. Dsempiler tous les lments. Terme anglais correspondant : Clear .
Dupliquer llment de tte et changer les deux premiers lments. Existe sur les calculatrices fonctionnant en notation polonaise inverse (style marque HP). Termes anglais
correspondants : Dup et Swap respectivement.
En Python, on utilise des listes. On ne sautorise aucune fonction excepte les trois suivantes
qui correspondent aux primitives indispensables : les mthodes append() et pop() et le test
dgalit la liste vide.
1
2
3
4
5
6
7
pile =[5 ,3 ,4 ,5
pile . append (1)
print pile
[5 ,2 ,4 ,5 ,1
pile . pop ()
1
print pile
75
8
9
10
[5 ,2 ,4 ,5
pile ==[
False
Remarquer que la mthode append() renvoie None alors que la mthode pop() renvoie llment dsempil (ou une erreur si la pile est vide).
On peut ensuite programmer les autres primitives. On modlise ainsi des piles non bornes.
Dans certains cas, on peut nutiliser que des piles bornes (limitation impose par le logiciel,
ou taille mmoire rduite). Dans ce cas, si N N est la taille limite dune pile borne, on
utilise en Python une liste de taille N , qui peut sinitialiser par les instructions pile=[0*N
ou pile=[ 0 for k in range(N) .
Par convention le premier lment de la liste va donner la longueur de la pile, et les autres
lments seront les lments de la pile.
1.3 Files
En informatique, une file (queue en anglais) est une structure de donnes base sur le principe du premier entr, premier sorti , en anglais FIFO (First In, First Out), ce qui veut dire
que les premiers lments ajouts la file seront les premiers tre rcuprs.
Le fonctionnement ressemble une file dattente la poste : les premires personnes arriver sont les premires personnes sortir de la file.
76
Les applications sont diffrentes de celles des piles :
Mmoriser temporairement des transactions qui doivent attendre pour tre traites
dans lordre darrive.
Les serveurs dimpression, qui doivent traiter les requtes dans lordre dans lequel
elles arrivent, et les insrent dans une file dattente (ou une queue).
Certains moteurs multitches, dans un systme dexploitation, qui doivent accorder
du temps-machine chaque tche, sans en privilgier aucune.
Pour crer toutes sortes de mmoires tampons (en anglais buffers ).
2 Rcursivit
2.1 Gnralits
En informatique pratique les fonctions rcursives sont simplement des fonctions dont le
calcul ncessite dinvoquer la fonction elle-mme. Cest lanalogue des formules de rcurrences en mathmatiques.
Les fonctions non rcursives seront appeles fonctions itratives.
def fa
torielle(n ):
fa
t =1
for k in range (2 , n +1) :
fa
t = fa
t *k
return fa
t
B Cette exemple montre les trois grands principes dune fonction rcursive :
Une fonction rcursive doit comporter une close darrt qui consiste en la donne dun
ou plusieurs cas de base : cest le type de la sortie de cette close qui va dterminer le
type de la sortie de la fonction.
Une fonction rcursive doit appeler la close darrt au bout dun nombre fini dtapes
(ce qui assure la terminaison de lalgorithme).
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
77
Une fonction rcursive sappelle elle-mme, mais avec diffrentes valeurs de (ou des)
largument(s).
La structure gnrale est donc la suivante :
On remarque que linstruction return doit tre prsente au moins deux fois : une fois pour
la close darrt, une fois pour lappel rcursif.
def puissan
e (x ,n ):
puiss =1
for k in range (n )
puiss *= x
return puiss
78
1
2
3
4
5
6
7
8
9
On voir sur cet exemple quune instruction du type speed_puissan
e_re
(x,n/2)*speed_
puissan
e_re
(x,n/2) est trompeuse, puisque les deux appels ne vont pas se faire en
mme temps et beaucoup de calculs identiques vont tre effectues deux fois ; do lintrt
de la variable auxiliaire r.
Il est aussi possible de dfinir des fonctions mutuellement rcursives. Il suffit de les crire
lune la suite de lautre :
1
2
3
4
5
6
7
8
9
10
11
import sys
sys . setre
ursionlimit (2000)
La figure suivante montre les phases de descente et de remonte pour le calcul de 6!.
79
http://www.pythontutor. om/visualize.html#mode=edit.
On peut remarquer que lappel de fa
torielle_re
(-1) ne va sarrter quune fois dpasse la capacit de la pile dexcution. On dit que la fonction ne termine pas dans tous les
cas.
On peut corriger ce problme en levant une exception avec linstruction assert :
1
2
3
4
5
6
Dans ce cas la fonction termine dans tous les cas : en effet, soit on lui donne un entier n < 0
et on tombe sur lexception, soit on lui donne un entier n 0, et dans ce cas les diffrents
appels rcursifs vont amener un appel avec largument 1 (ou 0 si n = 0 au dpart) qui fait
partie de la close darrt, et donc le programme termine aussi dans ce cas l.
On peut donc retenir la mthode gnrale suivante : pour montrer quun algorithme rcursif
termine, il faut montrer que, pour toutes valeurs de largument, on arrivera en un nombre
fini dtapes un appel de la close darrt.
B Il existe des fonctions rcursives pour lesquelles on ne sait pas dmontrer la terminaison.
Par exemple la fonction de Syracuse :
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
80
1
2
3
4
5
6
7
8
Pour viter les valeurs de largument pour lesquelles lalgorithme de ne termine pas, on peut
aussi utiliser les instructions while et input pour redemander une valeur lutilisateur (et
on suppose quil le fera au bout dun nombre fini dessais. . .) :
1
2
3
4
5
6
7
8
81
Si n est son argument, on note C (n) le nombre doprations lmentaires effectues, et A(n)
loccupation mmoire. On cherche ensuite, en tudiant lalgorithme une relation de rcurrence vrifie par la suite C (n), ou encore la suite A(n). On essaye ensuite den dduire une
expression explicite mais cela est rarement possible cause de la difficult des calculs. On
cherche souvent dominer C (n) et A(n) par une des suites de rfrences (n , ln(n), n! . . .).
Par exemple, pour la fonction fa
torielle_re
, on trouve C (n) = 1 + C (n 1) : en effet, on
effectue une multiplication et lappel rcursif au rang n 1. On a donc C (n) = n. On obtient
la mme complexit que pour la version rcursive.
Donnons un exemple plus complexe : la suite de Fibonacci. Elle est dfinie par u 0 = u 1 = 1
et, pour tout n N : u n+2 = u n+1 + u n . La version itrative est la suivante :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Si note A(n) loccupation mmoire de fibo_re
(n), on trouve que A(n) = A(n 1)+ A(n 2).
On montre alors quil existe un constante C > 0 telle que :
p !n
5
A(n) C . 1 +
n+
2
ce qui est trs mauvais (pour la version itrative A(n) = 2 et C (n) = n 1). En effet, certains
termes de la suite sont calculs un trs grand nombre de fois (alors quune fois suffirait). On
peut le visualiser sur la figure suivante, ou le calcul de u 6 a demand de calculer 8 fois u 2 .
82
Pour rsoudre ce problme, il faudrait enregistrer dans un tableau les termes dj calculs :
cette technique sappelle la mmosation.
Grce linstruction time() du module time, on peut comparer les vitesse dexcution des
versions itratives et rcursives :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
83
On obtient :
0.00005
Version rcursive
Version itrative
0.00004
0.00003
0.00002
0.00001
0.00000
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def re
her
he (l ,x ):
if len (l ) ==0: #
lose d ' arr t
return -1
else :
k = len (l ) /2 # Python 2.7
if l [k == x: # x est au milieu de la liste
return k
elif l[ k> x: # on
her
he gau
he
return re
her
he (l [: k ,x )
else :
test = re
her
he (l [k +1: , x ) # droite
if test == -1: # non trouv
return -1
else : # trouv
return test + k +1 #
orre
tion de la position
Dans ce cas, on sait lavance si la recherche doit se faire dans la partie gauche ou dans la
partie droite, contrairement au cas prcdent.
Si on note C (n) le nombre de tests boolens,
dans
84
2.6.2 Algorithme de dichotomie
Le but est de trouver une solution approche de lquation f (x) = 0 sur un segment [a, b].
Pour cela on se base sur le thorme des valeurs intermdaires : si f est continue sur [a, b],
et si f (a) et f (b) sont de signes contraires (au sens large), alors f sannule au moins une fois
sur [a, b].
a +b
. Si f (a) et f (c) sont de
2
signes contraires, on cherche la solution dans [a, c], sinon on la cherche dans [c, b]. On ritre
ensuite ce processus. Comme on divise chaque fois lintervalle en 2, on arrive au bout de
ba
n tapes un intervalle [a , b ] de longueur n : a et b sont alors des valeurs approches
2
ba
de la solution cherche, avec une prcision de
. Si on souhaite une prcision de > 0
2n
ba
donne, il suffit de choisir le nombre n ditrations tel que n < .
2
Lalgorithme consiste couper le segment en son milieu c =
def di
ho (f ,a ,b , eps ) :
assert f (a) *f (b) <=0 , 'on ne sait pas si f s '' annule '
if b -a < eps : #
lose d ' arr t
return a
else :
=( a +b) /2. # Python 2.7
if f (a) *f (
) <0:
return di
ho (f ,a ,
, eps ) # re
her
he dans [a ,
else :
return di
ho (f ,
,b , eps ) # re
her
he dans [
,b
Le nombre ditrations est le mme que pour la version itrative : cest le plus petit entier n
ba
tel que n < .
2
3 Algorithmes de tri
Dans cette section, nous allons prsenter plusieurs algorithmes permettant de trier une liste
(ou un tableau) de nombres.
Pour cette raison, un algorithme de tri sera dit optimal lorsque cn = O log2 (n) .
B Lorsquon ajoute des hypothses sur les objets trier, il existe des algorithmes plus rapides !
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
85
Donnons ensuite une notion qui va permettre de comparer les performances des diffrents
algorithmes de tri : on dit quun tri est fait en place si il ne ncessite pas lutilisation dune
liste (ou tableau) auxiliaire. Dans ce cas, la complexit spatiale (= occupation en mmoire)
de lalgorithme est constante.
86
1
2
3
4
5
6
7
8
9
10
11
Par exemple :
1
2
3
4
>>>
>>>
>>>
[1 ,
t =[5 ,2 ,4 ,6 ,1 ,3
tri_insertion (t)
t
2, 3, 4, 5, 6
la place de t est un paramtre pass par rfrence, on dit parfois que t est une variable
modifie en place.
On remarque que le tri par insertion est tri fait en place, sa complexit spatiale est donc faible.
En utilisant la fonction enumerate on peut crire une version peut-tre plus lisible du programme prcdent. Linstruction for k,x in enumerate(t) parcours la liste t de telle sorte
que k prenne successivement les valeurs 0, 1, . . ., len(t), et simultanment x prend les valeurs t[0, t[1, . . ., t[len(t).
1
2
3
4
5
6
7
def tri_insertion2 (t ):
for k ,x in enumerate ( t): # x= t[ k
j =k -1
while j >=0 and t[ j> x:
t[j +1= t [j
j=j -1
t [j +1= x
3.2.2 Complexit
Avec le module time, on peut valuer empiriquement la complexit en regardant le temps
de calcul pour trier des listes de nombres de taille variant de 1 300. Pour crer des liste
alatoires on utilise la fonction randint du sous-module random du module numpy.
1
2
3
4
5
6
7
8
87
9
10
11
12
13
14
15
temps = time ()
tri_insertion ( liste )
temps = time () - temps
ordonnees . append ( temps )
abs
isses = range (n +1)
plt . plot ( abs
isses , ordonnees , linestyle = ': ' , marker = 'o ')
plt . show ()
Nous allons donc valuer la complexit de lalgorithme en fonction de la taille n dune liste
donne en argument dentre.
Dans le pire des cas, la boucle while seffectue jusqu ce que la variable j prenne la valeur
1, et le nombre de comparaisons est gal k. Avec la boucle for on obtient que le nombre
total de comparaison est :
1 +2 + +k + +n 1 =
n(n 1)
2
88
Dans le meilleur des cas, la boucle while ne seffectue pas, et le nombre de comparaisons est
gal 1. Avec la boucle for on obtient que le nombre total de comparaison est :
1 +1 + +k + +1 = n 1
Si on note cn la complexit temporelle (en ne prenant en compte que les comparaisons) dans
le meilleur des cas, on a donc :
cn
n+
Remarquer que cette situation correspond au cas dun tableau dj tri au dpart dans lordre
croissant.
Ce tri nest donc pas optimal mais il est tout de mme beaucoup utilis. Empiriquement, il
est tabli quil est le plus rapide sur des donnes presque tries, ou sur des listes (ou tableaux)
de petite taille.
Cet algorithme est un exemple dune mthode gnrale utilise en rcursivit, appele diviser pour rgner : on divise le problme initial en deux sous-problmes quon sait rsoudre,
et on revient ensuite au problme initial. Dans le cas du tri rapide, les appels rcursifs sont
lancs jusqu tomber sur des listes de taille 1 ou 0, qui sont dj tries, et il ne reste plus
qu les concatner dans le bon ordre.
89
def tri_rapide( t) :
if len (t ) <=1: #
lose d ' arr t : tableau vide
return t # ou ave
un seul l ment
else :
pivot =t [0 #
hoix arbitraire du pivot
plus_petits =[ x for x in t if x < pivot
plus_grands =[ x for x in t [1: if x >= pivot
return tri_rapide( plus_petits) +[ pivot + tri_rapide(
plus_grands)
9
#
on
at nation et renvoi du r sultat
1
2
3
4
5
6
7
8
def tri_rapide2(t ):
if len (t ) <=1: #
lose d ' arr t : tableau vide
return t # ou ave
un seul l ment
else :
pivot =t [0 #
hoix arbitraire du pivot
plus_petits =[
plus_grands =[
for x in l [1::
if x < pivot :
plus_petits. append (x )
else :
plus_grands. append (x )
return tri_rapide( plus_petits) +[ pivot + tri_rapide(
plus_grands)
14
#
on
at nation et renvoi du r sultat
1
2
3
4
5
6
7
8
9
10
11
12
13
Ce premier algorithme naf illustre trs bien la mthode utilise, grce aux liste plus_petits
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
90
et plus_grands. Mais il a un gros dfaut : le tri ne se fait pas en place. Au cours de lexcution
il se cre beaucoup de tableaux auxiliaires et la complexit spatiale est alors trs importante.
Nous allons donner une version plus complique, mais pour laquelle le tri se fera en place : il
faut russir partitionner selon le pivot, mais sans crer de nouvelle liste auxiliaire, la seule
possibilit tant de permuter les lments de la liste deux deux.
Nous allons commencer par crer une fonction partition(t) qui va partitionner une liste
t en prenant le premier lment t[0 comme pivot.
Pour cela, on parcourt la liste de gauche droite ( partir de t[1]), de telle sorte que lorsquon
arrive llment t[i, les i premiers lments soient partitionns, cest--dire que :
leur partie gauche jusqu un indice appel position est forme des lments plus petits
(au sens strict) que le pivot,
leur partie droite (aprs lindice position) est forme des lments plus grands (au sens
large).
0
pivot
...
<pivot
position
<pivot
...
pivot
i
t[i]
...
?
len(t)-1
def partition (t ):
assert t !=[ , 'on ne peut pas partitionner la liste vide '
pivot =t [0
position =0
for i in range (1 , len ( t)) :
if t [i< pivot :
t[i , t[ position +1= t[ position +1 , t[ i
position +=1
if position !=0:
t [0 , t[ position = t[ position , t [0
return position
Pour lancer le tri rcursif, nous allons devoir appliquer cette fonction sur une portion de la
liste, et non la liste entire. On adapte donc notre fonction pour quelle ne partitionne que
la portion t[a:b (forme des t[i pour t allant de a b 1). Le reste de la liste nest pas
modifi.
1
2
3
91
4
5
6
7
8
9
10
11
position =a
for i in range (a +1 , b) :
if t [i< pivot :
t[i , t[ position +1= t[ position +1 , t[ i
position +=1
if position != a:
t [a, t[ position = t[ position , t[ a
return position
On peut crire le programme principal du tri rapide en place. Lui aussi doit pouvoir se lancer
sur des portions de liste, il aura donc trois arguments comme la fonction partition prcdente. En sortie, il ne renvoie rien mais la liste a t modifie.
1
2
3
4
5
Pour trier toute la liste t, il faut lancer tri_rapide2(t,0,len(t)). Comme ce nest pas trs
naturel, on peut crer une nouvelle fonction avec un seul argument dentre.
1
2
3.3.2 Complexit
Comme pour le tri par insertion, on peut valuer empiriquement la complexit en regardant
le temps de calcul pour trier des listes de nombres de taille variant de 1 300.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
On obtient la courbe suivante qui suggre une complexit un peu plus que linaire, o n est
la taille de la liste :
92
Nous allons donc valuer la complexit de lalgorithme en fonction de la taille n dune liste
donne en argument dentre, et nous allons voir quelle nest pas linaire mais en O (n log2 (n)).
Dans le pire des cas, le rsultat de la fonction partition place systmatiquement le pivot en
dbut ou en fin de tableau. Les appels rcursifs se font donc sur un tableau vide et un tableau
de taille n 1. Avant de lancers les appels rcursifs, lappel la fonction partition effectue
n 1 comparaisons entre les lments du tableau.
Si on note C n la complexit temporelle (en ne prenant en compte que les comparaisons)
dans le pire des cas, on a donc :
C n = n 1 +C n1
On en dduit facilement que :
C n = (n 1) + (n 2) + + 1 + 0 +C 0 =
donc :
Cn
n+
n(n 1)
+C 0
2
O n2
Remarquer que cette situation correspond au cas dun tableau dj tri au dpart (dans nimporte quel ordre).
Dans le meilleur des cas, le rsultat de la fonction partition place systmatiquement le
j npik
vot en milieu de de tableau. Les appels rcursifs se font donc sur deux tableaux taille
.
2
Avant de lancers les appels rcursifs, lappel la fonction partition effectue n 1 comparaisons entre les lments du tableau.
Si on note cn la complexit temporelle (en ne prenant en compte que les comparaisons) dans
le meilleur des cas, on a donc :
cn = n 1 + 2.c n
2
93
Les calculs suivant prouvent que :
cn
n+
O n. log2 (n)
Cas 2. On revient au cas gnral. Pour cela, on fait lhypothse raisonnable que la suite
(cn )nN est croissante (plus la taille des donnes trier est important, plus le nombre de
comparaisonest important).
On en dduit que :
log (n)+1
log2 (n)+1
log2 (n)+1
2
cn log2 (n) + 1 .2
+12
+2
.c0 = 2n log2 (n) + 1 1 + c0 1
et finalement :
cn
n+
O log2 (n)
Ce tri est donc optimal dans le meilleur des cas mais il ne lest pas dans le pire des cas.
Mais il se trouve quen pratique cest lalgorithme le plus rapide, il est donc empiriquement
le plus performant. Cette diffrence vient du fait que nous avons seulement dnombr les
comparaisons entre lments du tableau trier, alors quil se passe beaucoup dautre choses
lors de lexcution de lalgorithme (affectations etc. . .).
94
coupe le tableau en deux morceaux toujours gaux, quon trie, puis reste ltape dlicate appele fusion. Elle consiste fusionner ces deux tableaux de telle sorte quon obtienne un
tableau tri.
La figure suivante illustre ce tri sur un exemple :
La fonction principale est la fonction fusion qui permet de fusionner deux tableaux tris
en un tableau tri. Pour cela on procde manire rcursive : le plus petit lment des deux
tableaux est plac en premire position du nouveau tableau, il reste ensuite fusionner les
deux tableaux privs de cet lment.
1
2
3
4
5
6
7
8
9
10
11
def trifus (t ):
if len (t ) <=1: #
lose d ' arr t
return t
else :
return fusion ( trifus (t [: len (t) /2) , trifus ( t[ len (t) /2:) )
# en Python 2.7 / est la division eu
lidienne
95
On voir tout de suite lavantage de cet algorithme : la lecture est trs simple, et le fait de
toujours couper le tableau en deux parties gales va limiter le nombre de comparaisons.
Par contre la complexit spatiale est trs mauvaise, on utilise une fonction rcursive qui appelle elle-mme une fonction rcursive, et les oprations ne sont faites pas en place.
On peut donc esprer amliorer lalgorithme en le programmant en place. Pour cela, si on
dispose dun tableau dont les deux moitis sont tries, il faut tre capable de les fusionner
dans crer de tableau auxiliaire. Nous allons utiliser des permutations circulaires. Si on se
donne un tableau [x1 , x2 , . . . , xn1 , xn ], il devient aprs permutation circulaire :
[xn , x1 , x2 , . . . , xn1 ]
1
2
3
4
5
def perm_
ir
(t ):
for k in range ( len (t) -1 ,0 , -1):
t [k, t[k -1= t[k -1 , t [k
# permutation
ir
ulaire: le dernier l ment devient le premier
# et les autres sont d
al s vers la droite
Ensuite, supposons quon dispose dun tableau t et dun indice m dans 0,len(t), de telle
sorte que les sous-tableaux t[:m et t[m: soient tris. Pour raliser la fusion, nous allons
parcourir le tableau de gauche droite de sorte que lorsquon arrive llment t[i :
t[:i est un sous-tableau dun tableau tri t[:j avec j > i et j m,
chaque lment de t[:i est infrieur ou gal x,
le tableau t[j: est tri.
...
t[j]
i
t[i]
tri
...
j
t[j]
...
?
tri
len(t)-1
96
1
2
3
4
5
6
7
8
9
10
11
On peut crire le programme principal du tri fusion en place. Lui aussi doit pouvoir se lancer
sur des portions de liste, il aura donc trois arguments comme la fonction fusion prcdente.
En sortie, il ne renvoie rien mais la liste a t modifie.
1
2
3
4
5
6
Pour trier toute la liste t, il faut lancer trifus2(t,0,len(t)). Comme ce nest pas trs naturel, on peut crer une nouvelle fonction avec un seul argument dentre.
1
2
def tri_fusion( t) :
trifus2 (t ,0 , len (t))
3.4.2 Complexit
On peut valuer empiriquement la complexit en regardant le temps de calcul pour trier des
listes de nombres de taille variant de 1 300.
97
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
On obtient la courbe suivante qui suggre la mme complexit que pour le tri rapide : O n. log2 (n) .
0.035
0.030
0.025
0.020
0.015
0.010
0.005
0.000
0
50
100
150
200
250
300
Nous allons donc valuer la complexit de lalgorithme en fonction de la taille n dune liste
donne en argument dentre.
Dans
j nde
k
j n k le pire des cas (tableau tri lenvers), lors de lappel de la fonction fusion, j varie
n 1, et i prend ses valeurs entre 0 et n 2, donc au total lalgorithme effectue
2
2
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
98
comparaisons. En gardant les notations des paragraphes prcdents, on a donc :
jn k
+ 2.C n
Cn =
2
2
et les mmes calculs que pour le tri fusion donnent :
C n = O n. log2 (n)
n+
jn k
1, donc au total lalDans le meilleur des cas(tableau tri), j ne varie pas et i varie de 0
2
jn k
gorithme effectue
comparaisons. En gardant les notations des paragraphes prcdents,
2
on a donc :
jn k
cn =
+ 2.c n
2
2
et les mmes calculs que pour le tri fusion donnent :
cn = O n. log2 (n)
n+
Ce tri est donc optimal ! Mais ce nest vrai quen prenant en compte le nombre de comparaisons. La version prsente a lavantage dtre en place, donc la complexit spatiale est
constante. Par contre le nombre daffectations est trs grand, et il parat peu rigoureux de ne
pas en tenir compte.
99
19
20
21
22
23
24
25
26
27
28
ordonnees =[
for k in range (n +1) :
liste = rd . randint (0 , k +1 , k +1)
t = time ()
trifus ( liste )
t = time () -t
ordonnees . append ( t)
plt . plot ( abs
isses , ordonnees , linestyle = ': ' , marker = 'o ' , label = '
fusion ')
plt . legend ( lo
=2)
plt . show ()
0.030
0.025
insertion
rapide
fusion
sort()
0.020
0.015
0.010
0.005
0.000
0
50
100
150
200
250
300
100
Pour dterminer la mdiane dun tableau quelconque de nombres flottants, il suffit donc de
le trier, puis dappliquer la dfinition
ci-dessus.
La complexit minimale est donc celle de
Il existe des algorithmes plus performants, appels algorithme de slection, qui permette de
trouver le k-ime plus grand lment dun tableau de nombre flottants, sans avoir trier
systmatiquement tout le tableau. Leur complexit est en moyenne linaire, ie en O (n).
Chapitre 3
Exercices de premire anne
1 Structure de donnes
1.1 Reprsentation des nombres
Exer
i
e 1 (Suite r
urrente linaire instable) Dans cet exercice, on sintresse aux suites
(u n )nN vrifiant la relation de rcurrence linaire :
n N,
8
u n+2 = u n u n+1
3
(R)
102
1.2 Listes
nombre situ sur larte joignant deux sommets est leur distance, suppose entire :
1. Construire la matrice (Mi j )0i ,j 4 , matrice de distances du graphe G, dfinie par : pour
tous les indices i , j , Mi j reprsente la distance entre les sommets i et j , ou encore la
longueur de larte reliant les sommets i et j .
On convient que, lorsque les sommets ne sont pas relies, cette distance vaut 1. La
distance du sommet i lui-mme est, bien sr, gale 0.
2. crire une suite dinstructions permettant de dresser partir de la matrice M la liste
des voisins du sommet 4.
3. crire une fonction voisins, dargument un sommet i , renvoyant la liste des voisins
du sommet i .
4. crire une fonction degre, dargument un sommet i , renvoyant le nombre des voisins
du sommet i , cest--dire le nombre dartes issues de i .
5. crire une fonction longueur, dargument une liste L de sommets de G, renvoyant
la longueur du trajet dcrit par cette liste L, cest--dire la somme des longueurs des
artes empruntes. Si le trajet nest pas possible, la fonction renverra 1.
103
2. crire une fonction de
alage, dargument un entier n, renvoyant une chane de caractres contenant toutes les lettres dans lordre alphabtique, dcales de n, comme
indiqu ci-dessus.
3. crire une fonction indi
es, darguments un caractre x et une chane de caractres
phrase, renvoyant une liste contenant les indices de x dans phrase si x est une lettre
de phrase et une liste vide sinon.
4. crire une fonction
odage darguments un entier n et une chane de caractres phrase,
renvoyant phrase code avec un dcalage de n lettres.
5. Comment peut-on dcoder un mot cod ?
2 Modules
3 Algorithmique
3.1 Algorithmique des tableaux/listes et des chanes de caractres
Exer i e 5 (Re her he d'un lment dans une liste) Montrer la terminaison et la correction de lalgorithme de recherche dun lment dans une liste.
Exer i e 6 (Re her he d'un lment dans une liste : variantes) On souhaite rechercher un lment x dans une liste t.
1. crire une fonction re
her
he_inverse(t,x) qui dtermine le dernier indice i tel
que t[i=x, et renvoie i sil existe, Flase sinon.
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
104
2. crire une fonction re
her
he_all(t,x) qui dtermine la liste de tous les indices i
tel que t[i=x, et la renvoie (si x nappartient pas t, la fonction doit renvoyer la liste
vide [).
Exer i e 7 (Re her he du maximum dans une liste) Montrer la terminaison et la correction de lalgorithme de recherche du maximum dans une liste.
Exer i e 9 (tude de l'os illation d'un pendule par la mthode d'Euler) On consi-
dre un pendule simple oscillant dans un champ de pesanteur constant, compose dune
masse m fixe lextrmit dune tige rigide de masse nulle, tournant sans frottement dans
le plan vertical autour de son extrmit fixe. On note llongation angulaire du pendule, et
on rappelle que vrifie lquation :
g
+ sin() = 0
1 2 2
) g cos()
2
3. Tracer
surun mme graphe les diffrentes orbites de phase, cest--dire les courbes
Exer
i
e 10 (Cir
uit RLC) On considre un circuit lectrique simple constitu dune source
de tension V , dune rsistance R, dune bobine L et dune capacit C montes en srie
comme le montre le schma suivant.
105
Lquation satisfaite par la tension u aux bornes de la bobine est :
d 2u R d u
1
d 2E
+
.
+
.u
=
d t 2 L d t LC
dt2
1. laide de la mthode dEuler, tracer la courbe de la tension aux bornes de la bobine
pour R = 30 , L = 870 mH, C = 630 mF et V (t ) = 10. sin(2. f .t ), avec f = 100 H z, sur
lintervalle de temps [0, 0.4].
2. Faire de mme avec la fonction odeint du module s
ipy.
dx
(t ) = x(t ). a b.y(t )
dt
d y (t ) = y(t ). c d .x(t )
dt
(a) Tracer sur un mme graphe les courbes x(t ), y(t ) , o x(t ) est le nombre de proies
linstant t et y(t ) le nombre de prdateurs, avec comme conditions initiales x(0), y(0) :
(100, 50) (100, 130) (200, 100) (50, 50)
et de prdateurs pour la condition initiale x(0), y(0) = (50, 50) sur une priode de
20 units de temps.
1. Crer une fonction hilbert dargument n qui renvoie la matrice de Hilbert dordre n
sous forme de tableau numpy.
2. Inverser H10 et faire afficher le coefficient en bas droite. Le rsultat attendu (formel)
est 44 914 183 600. Que constate-t-on ? Pour n = 20, le coefficient correspondant devrait tre 48 722 219 250 572 027 160 000.
On peut dmontrer que la matrice inverse de Hn est coefficients dans Z.
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
106
7.7
7.7
6.
6.
0.4
0.5
0.
0.
Que peut-on en conclure ?
.
.
1 . . . .
.. ..
Vn =
.
.
..
..
..
. 1
1 2
Rsoudre crire une fonction resolution(Y) qui donne en sortie la solution du systme
linaire Vn X = Y , en adaptant lalgorithme du pivot de Gauss la forme particulire de Vn
(forme tridiagonale).
>>> fill('resultat.txt',100)
2. crire une fonction file2list qui prend en paramtres un nom de fichier rempli
comme resultat.txt, en rcupre le contenu sous forme dune liste dont les lments sont des listes de trois lments :lidentifiant, la note, et le sexe. Exemple :
>>> file2list('resultat.txt')
[[18706, 14.1, 'F',
[53651, 14.3, 'F',
[59644, 13.5, 'H'
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
107
3. crire une fonction averageByGenre qui prend en paramtres une liste de listes, comme
celle retourne par la fonction prcdente et un caractre H (homme) ou F (femme).
La fonction retourne la moyenne des filles, ou la moyenne des garons.
>>> liste=file2list('resultat.txt')
>>> averageByGenre(liste,'H')
13.5
>>> averageByGenre(liste,'F')
14.2
108
(h) Combien de communes franaises contiennent la lettre x ou X dans leur nom ?
Linstruction WHERE Attribut LIKE '
haine' teste si la chane de caractre
Attribut est gale '
haine'. Le caractre '%' reprsente une chane quelconque
(mme vide). Le test est insensible la casse (= majuscule ou minusucule)
(i) Combien de communes franaises contiennent les six voyelles a, e, i, o, u, y
(en majuscule ou minuscule) dans leurs noms ?
(j) Existe-t-elle une telle commune sur lle de la Runion ?
(k) Quelles sont les 15 communes de France dont lcart entre laltitude la plus haute,
et laltitude la plus basse, est le plus lev ?
(l) Quelles sont les cinq communes de lle de la Runion o la population a le plus
augment entre 1999 et 2010 ?
(m) Quelles sont les cinq communes de lle de la Runion o la population a le plus
augment en pourcentage entre 1999 et 2010 ?
On affichera le nom des communes, laugmentation effective, et laugmentation
en pourcentage.
2. Jointures deux tables.
(a) Obtenez la liste des dpartements (les noms !), et pour chaque dpartement correspondant, le nombre de communes.
Vous ordonnerez par nombre de communes dcroissant.
(b) Obtenez la liste des dpartements (les noms !) des rgions Auvergne et Aquitaine.
(c) Quelle est la population de chaque dpartement (on veut les noms des dpartements en toutes lettres) ?
Les dpartements seront classs par population dcroissante.
(d) Quelle est la densit de population de chaque dpartement (on veut les noms des
dpartements en toutes lettres et le classement par ordre de densit dcroissante) ?
(e) Obtenez la liste des rgions de France, ainsi que le nombre de dpartements composant la rgion, range par nombre de dpartements dcroissant.
(f) Obtenez la liste des dpartements (les noms !) de plus de 1 200 000 habitants.
(g) Existe-t-il une commune de la rgion Aquitaine, dont le nom contient les six voyelles
'a', 'e', 'i', 'o', 'u', 'y' (en majuscule ou minuscule) ?
Indice : lAquitaine est la rgion numro 2.
(h) Obtenez (sans doublons) la liste des rgions contenant des dpartements dont le
nom commence par c ou C.
3. Jointures trois tables.
(a) Obtenez la liste des rgions de France, et pour chaque rgion, la population totale,
ainsi que le nom et le nombre dhabitants de la commune la plus peuple de la
rgion.
Les rsultats seront affichs par ordre dcroissant de population totale.
(b) Obtenir la liste des rgions (avec le nom en franais), avec la population totale de
chaque rgion, classes par ordre dcroissant de population ?
(c) Densit de population de chaque rgion ?
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
109
(d) Quelles sont les 15 communes de France dont lcart entre laltitude la plus haute,
et laltitude la plus basse, est le plus lev ? Cette fois, prcisez le nom du dpartement et le nom de la rgion pour chaque commune. . .
(e) Combien de communes dans la rgion Basse Normandie ?
4. Sous-requtes.
Pour la clart de la rdaction, on pourra prsenter les requtes sous la forme :
La figure prcdente est une reprsentation graphique des villes de mtropole par
des points dont la couleur dpend de laltitude. Elle a t obtenue avec le programme
suivant :
1
2
3
4
import numpy as np
from math import
os , pi
import matplotlib. pyplot as plt
import MySQLdb
110
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Base = MySQLdb .
onne
t ( host = ' *** ' , user = ' *** ' , passwd = ' *** ' ,db
= ' geographie ')
requete = ' SELECT longitude , latitude , zmax FROM
ommunes
WHERE num_departement <= 95 '
Base . query ( requete )
resultat = Base . use_result ()
res = resultat . fet
h_row ( maxrows =0)
orr =
os (40* pi /180)
Lx =[
Ly =[
Lz =[
for ligne in res :
Lx . append ( float ( ligne [0) )
Ly . append ( float ( ligne [1) )
Lz . append ( float ( ligne [2) )
plt . s
atter (
orr * np . array ( Lx ) ,Ly ,
= Lz )
plt . axis ( ' equal ')
plt . show ()
Base .
lose ()
(a) Adapter le programme prcdent pour quil regroupe les communes par canton.
(b) Reprsenter par des points de couleur lattractivit des cantons franais, reprsente par laugmentation relative du nom dhabitants entre 1999 et 2010 (points
placs en fonction de longitude et latitude).
(c) Reprsenter par des points les 5000 plus grosses communes de mtropole (points
placs en fonction de longitude et latitude).
Chapitre 4
Exercices de seconde anne
1 Piles
Exer i e 16 (Fon tions sur les piles) Les piles seront modlises par des listes, et on ne
sautorisera comme oprations que les mthodes pop(), append(), ainsi que la comparaison la liste vide [.
On rappelle que les variables de type list sont modifies en place lorsquelles sont donnes
en argument dune fonction.
On pourra effectuer une copie dune pile ainsi : l2 = [ x for x in l (et non l2=l).
Dans les questions suivantes, on nutilisera que les oprations ci-dessus, ainsi que les fonctions programmes dans les questions prcdentes.
1. Ecrire une fonction isempty qui renvoie un boolen indiquant si une pile est vide ou
non.
2. Ecrire une fonction
ard qui renvoie le nombre dlments dune pile.
3. Ecrire une fonction peek qui renvoie llment de tte sans le dpiler.
4. Ecrire une fonction
lear qui vide une liste en dpilant tous ses lments et ne renvoie rien.
5. Ecrire une fonction dup qui duplique llment du haut de la pile et ne renvoie rien.
6. Ecrire une fonction swap qui permute les deux lments du haut de la pile et ne renvoie rien.
7. Ecrire une fonction permut qui effectue une permutation circulaire des lments dune
pile (pour cela, on pourra utiliser une pile auxiliaire) et ne renvoie rien.
Par exemple [6,4,2,7,9 devient [9,6,4,2,7.
dcrire un calcul sans aucune parenthse. Pour cela on place en premier les oprandes, suivi
des oprateurs.
Par exemple, le calcul 32+2*(12-3*(7-2)) se note 32 2 12 3 7 2 - * - * +.
En python le calcul en NPI sera donn sous forme dune liste :
[32,2,12,3,7,2,'-','*','-','*','+'
appele
al
ul, o les oprandes sont des nombres de type float, et les oprateurs sont des
chanes de caractres. On se limitera aux oprations : addition, soustraction, multiplication
et division.
Pour valuer le calcul, on parcourt utilise une pile auxiliaire pile_aux. On parcourt la liste
reprsentant le calcul de gauche droite, lment par lment :
111
112
si llement est un oprande, on lempile dans la pile pile_aux ;
si llment est un oprateur, on dpile les deux lments du sommet de la pile pile_aux,
on leur applique loprateur, on empile le rsultat sur pile_aux.
A la fin, la pile auxiliaire ne contient plus quun lment qui est le rsultat du calcul. Par
exemple, pour le calcul [32,2,12,3,7,2,'-','*','-','*','+', la variable pile_aux
volue de la faon suivante :
[
[32
[32,
[32,
[32,
[32,
[32,
[32,
[32,
[32,
[32,
[26
2
2, 12
2, 12,
2, 12,
2, 12,
2, 12,
2, 12,
2, -3
-6
3
3, 7
3, 7, 2
3, 5
15
Ecrire une fonction NPI qui prend en entre une liste reprsentant un calcul, et qui value ce
calcul en utilisant lalgorithme prsent ci-dessus.
Pour tester si un lment de la liste est un oprande ou un oprateur, on pourra utiliser une
variable op = ['+','-','*','/'.
est bien parenthse, cest--dire quelle possde autant de parenthses ouvrantes que de
parenthses fermantes et ceci dans le bon ordre, on utilise une pile.
Lalgorithme consiste parcourir la chane de caractres de gauche droite :
chaque fois quon rencontre une parenthse ouvrante, on empile une parenthse
fermante ;
chaque fois quon rencontre une parenthse fermante :
si la pile est vide cest que lexpression est mal parenthse,
sinon on dpile une fois ;
la fin du parcours, il faut que la pile soit vide pour dire que lexpression est bien
parenthse.
Ecrire une fonction parentheses qui prend en entre une chane de caractres, et qui renvoie en sortie un boolen indiquant si lexpression est bien parenthse.
113
2 Rcursivit
Exer i e 21 (PGCD)
Si a et b sont deux entiers naturels (avec b 6= 0), et si la division euclidienne de a par b scrit a = bq + r avec r 0, b 1, alors on montre que pgcd(a, b) =
pgcd(b, r ).
En dduire un algorithme itratif et un algorithme rcursif de calcul du pgcd.
Exer
i
e 22 (Inversion r
ursive d'une liste) crire un programme rcursif qui inverse
lordre des lments dune liste.
n nN
dfinie par :
u 0 = u 1 = 1 et n N, u n+2 = u n+1 + u n
1. crire une fonction itrative qui calcule u n pour n donn..
valuer sa complexit spatiale et temporelle.
2. (a) crire une fonction rcursive qui calcule u n pour n donn..
valuer sa complexit spatiale et temporelle.
(b) Utiliser une variable globale nb_re
al
uls de type list n + 1 lments, pour
que nb_re
al
uls[k soit gal au nombre de fois o u k a t calcul lors du calcul
de u n (k 0, n).
u n u n1
1 1
(a) Montrer que, pour tout n N ,
=
.
1 0
u n1 u n2
(
2
u 2n1 = 2u n1 u n u n1
En dduire que, pour tout n N ,
2
u 2n = u n1
+ u n2
(b) En dduire une fonction rcursive qui calcule le couple (u n1 , u n ) pour n donn.
valuer sa complexit spatiale et temporelle.
114
Exer i e 24 (Tours de Hano) Le problme des tours de Hano est un jeu de rflexion
imagin par le mathmaticien franais douard Lucas, et consistant dplacer des disques
de diamtres diffrents dune tour de dpart une tour d arrive en passant par une
tour intermdiaire , et ceci en un minimum de coups, tout en respectant les rgles suivantes :
on ne peut dplacer plus dun disque la fois,
on ne peut placer un disque que sur un autre disque plus grand que lui ou sur un
emplacement vide.
1. Proposer alors une fonction rcursive hanoi(n,dep,aux,arr) qui affiche les dplacements effectuer pour dplacer n disques du piquet dep vers le piquet arr, en utilisant le piquet intermdiaire aux.
2. Combien de dplacements sont ncessaires pour que les n disques passent tous du
piquet de dpart au piquet d arrive ?
3. Selon la lgende imagine par E. Lucas, le jeu a commenc en 1500 avant J.C., dans
un temple Hano, avec 64 disques dor, et la fin du monde arrivera quand le jeu se
termine ( raison dune seconde par dplacement). Est ce vrai ? (on prendra 14 milliards dannes comme ge de lunivers)
Exer i e 25 (Sudoku) Dans cette exercice, on se propose de rsoudre les grilles de sudoku
de manire rcursive. Une grille de sudoku sera represente par une matrice 9 9 comme
suit :
1. crire une fonction re
her
he_zero(M) qui renvoie les coordonnes de la premire
case non remplie de la grille M, et qui renvoie [10,10 si toutes les cases sont remplies.
2. crire une fonction test_ligne_
olonne(M,i,j,val) qui vrifie si on peut mettre
la valeur val dans la case [i,j de la grille M en vrifiant que val nest pas dj dans
la ligne i ou la colonne j.
Cette fonction renverra True ou False.
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
115
3. crire une fonction test_sous_
arre(M,i,j,val) qui fait la mme chose mais vrifie si val nest pas prsent dans le sous-carr qui contient la case [i,j.
4. Complter le code ci-dessous pour crer une fonction qui vrifie si on peut mettre la
valeur val dans la case [i,j de la grille M (vous navez le droit qu une ligne de code.)
1
2
5. laide des fonctions prcdentes, crire une fonction rcursive sudoku qui va rsoudre la grille de sudoku en testant toutes les valeurs possibles pour chaque case.
La fonction se contentera dafficher la grille solution. Sil y a plusieurs solutions on les
affichera toutes (bien que dans la vraie rgle cette grille serait dclare insoluble)
nX
3. Comparer les complexits ces algorithmes (on ne prendra en compte que les multiplications).
Exer
i
e 29 (Serpent vietnamien) Le but du jeu est de remplir les cases de la grille suivante, avec des chiffres de 1 9 (quil ne faut utiliser quune fois chacun), en suivant lordre
des oprations, de faon obtenir 66 comme rsultat final :
116
1. crire une fonction rcursive qui prend en entre une liste l de nombres, et donne
en sortie la liste de toutes les permutations de cette liste (donc si l est une liste de n
nombres, la liste donne en sortie est une liste de n! listes).
2. En dduire un programme Python qui dtermine toutes les solutions au jeu du serpent vietnamien (en sortie on pourra se contenter de nafficher que le nombre total
de solutions).
Exer i e 30 (Algorithme de Strassen) Dans cet exercice, nous allons voir plusieurs fa-
ons de programmer le produit de deux matrices carres dordre k. Pour manipuler les matrices on utiliser le module numpy.
1. crire un algorithme qui effectue le produit matriciel grce la formule appris dans
le cours de mathmatiques. valuer sa complexit.
2. On va essayer damliorer les performances.
(a) crire une fonction logdeux(k) qui prend en entre un entier naturel k, et renvoie
en sortie le plus petit entier naturel n tel que k 2n .
(b) Crer une fonction newsize(m) qui prend en paramtres une matrice carre m, et
retourne une nouvelle matrice qui est une copie de m laquelle on ajoute des zros
pour en faire une matrice 2n 2n .
(c) Crer une fonction one2four(m) qui prend en paramtre une matrice carre 2n
2n et renvoie les 4 sous-matrices usuelles de tailles 2n1 2n1 .
(e) En utilisant ce qui prcde, crer une fonction rcursive produit(m1,m2) qui prend
en paramtres deux matrices carres de mme dimensions2n 2n et les dcoupe
en blocs comme ici :
A B
A B
m1 =
et
m2 =
C D
C D
La fonction calcule ensuite rcursivement le produit m 1 m 2 en utilisant le produit
par blocs vu en cours.
(f) crire le programme principal mult(m1,m2) qui prend en entre deux matrices
carres m1, m2, les redimensionne en matrices de taille 2n 2n , effectue leur produit matriciel avec la fonction produit, puis affiche le rsultat sans les lignes et
colonnes de zros ajouts par la fonction newsize.
(g) Quelle est la complexit de cet algorithme ?
(h) Pour diminuer cette complexit, Volker Strassen a mis en place la mthode suivante en 1968. Pour effectuer le produit m 1 m 2 , on pose :
X 1 = (A + D)(A + D )
X 2 = (C + D)A
X 3 = A(B D )
X 4 = D(C A )
X 5 = (A + B)D
X 6 = (C A)(A + B )
X 7 = (B D)(C + D )
117
et vrifie alors facilement que :
X1 + X4 X5 + X7
X3 + X5
m1m2 =
X2 + X4
X1 X2 + X3 + X6
Transformer la fonction mult(m1,m2) en une fonction strassen(m1,m2) qui utilise la mthode de Strassen.
Quelle est la complexit de ce nouvel algorithme ?
3 Tris
le nombre qui est plus grand que la moiti de ces nombres, et plus petit que lautre moiti
de ces nombres. Autrement dit, cest le nombre qui se trouve au milieu du tableau si on trie
celui-ci. Pour une liste trie de 2N + 1 nombres cest donc le (N + 1)-ime nombre, pour une
liste trie de 2N nombres, une mdiane est nimporte quel nombre compris entre le N -ime
et le (N + 1)-ime.
1. Proposer une fonction mediane_tri qui calcule une mdiane dune liste en utilisant
un algorithme de tri.
Pour une liste quelconque, le mieux quon puisse faire est alors en O(n logn), mme si, dans
certains cas, le tri insertion donne une complexit en O(n).
On ne va donc pas trier la liste, juste chercher sa mdiane.
On implante ici la mthode Quickselect de Hoare qui a une complexit moyenne en O(n),
O(n 2 ) dans le pire des cas.
2. Implmenter la fonction partition(l,g,d) du cours, qui transforme la sous-liste
l[g:d de telle sorte qu gauche de la valeur l[g se trouve les lments plus petits
et droite les lments plus grands. En sortie elle donne la position du pivot l[g.
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
118
3. On crit une fonction rcursive sele
t_re
(l,g,d,k) qui prend en paramtres une
liste l , deux indices gauche et droite, g , d ainsi quun indice k.
Cette fonction retourne le k-ime lment de la liste dans le classement croissant
(sans trier la liste).
Pour ce faire, on partitionne dabord la portion entre g et d de la liste et on note p,
lindice du pivot (donn par lappel partition(l,g,d)) :
(a) Si p = k, on a llment k de la liste.
(b) Si p < k, llment k est droite de p, on appelle sele
t_re
sur la portion droite
du pivot.
(c) Sinon, le k-ime lment est gauche de p, on appelle sele
t_re
sur la portion
de la liste gauche du pivot.
La close darrt est donne par le cas o la sous-liste na quun seul lment.
Comme pour le tri rapide en place, on crit ensuite une fonction sele
t(l,k) qui
appelle sele
t_re
pour obtenir le k-ime lment du tableau dans le classement
croissant.
Tester sur des exemples et remarquer que la liste na pas besoin dtre entirement
trie.
4. Pour une liste l tri de longueur N , la mdiane est llment plac proximit immdiate de lindice N /2 (suivant la parit du nombre dlments) :
(a) si N est impair, la mdiane est t [(N 1)/2],
(b) si N est pair (et la liste non vide), la mdiane est nimporte quel nombre strictement compris entre t [N /2 1] et t [N /2].
4 Autres
4.1 Stganographie
La stganographie est lart de la dissimulation : son objet est de faire passer inaperu un
message dans un autre message. Elle se distingue de la cryptographie, art du secret , qui
cherche rendre un message inintelligible autre que qui-de-droit. Pour prendre une mtaphore, la stganographie consisterait enterrer son argent dans son jardin l o la cryptographie consisterait lenfermer dans un coffre-fort cela dit, rien nempche de combiner
les deux techniques, de mme que lon peut enterrer un coffre dans son jardin.
On peut utiliser Python pour cacher une image dans une autre. Commenons par quelques
notions sur les images en informatique :
une image est une reprsentation visuelle de quelque chose ;
cette reprsentation est dcoupe en lments carrs appels pixels (picture element),
chaque pixel tant compos dune seule couleur ;
un cran possde un nombre fixe de pixels dfini comme tant le produit du nombre
de pixels en largeur par le nombre de pixels en hauteur (cest la dfinition dcran, par
exemple : 1024 768).
On peut dfinir la taille et la dimension dune image :
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
119
Taille dune image. Espace mmoire quoccupe un fichier image sur le disque dur,
exprime en octets. Exemple : 250 Ko.
Dimensions dune image. Espace visuel quoccupe une image sur lcran, reprsentes par un couple de valeurs longueur largeur. Lunit utilise ici sera le pixel.
Exemple : 360 200.
Pour reprsenter un couleur, on utilise une combinaison de couleurs primaires. Il existe plusieurs faons de le faire : ce sont les modes colorimtriques.
Nous nous intresserons ici au mode RGB (Red-Green-Blue) ou RVB (Rouge-Vert-Bleu). Ce
mode attribue chaque pixel une intensit de rouge, vert et bleu. Cette intensit est un
nombre compris entre 0 (intensit nulle) et 255 (intensit maximum). On peut reprsenter
de cette faon 2563 = 16777216 couleurs diffrentes !
Chaque intensit tant une valeur comprise entre 0 et 255, il faut donc 8 bits (1 octet) pour
coder une intensit en binaire (28 = 256).
120
Nous allons cacher notre image secrte (hidden image) lintrieur de chaque pixel de notre
image originale (cover image). Pour simplifier, les dimensions de ces 2 images seront identiques. Chaque pixel de notre image originale sera lgrement modifi : plus prcisment
nous allons modifier les bits de poids faible de chaque pixel. Cest la mthode LSB : Least
Significant Bit.
Sur lexemple ci-dessous, les composantes R,G et B de ces deux couleurs diffrent de 2.
Pourtant loeil nu on ne voit pas la diffrence.
Pour cacher un pixel B dans un pixel A, nous allons donc remplacer les 4 bits de poids faible
du pixel A par les 4 bits de poids fort du pixel B.
Par exemple si :
R : 39 = 0010 01112
2
A G : 88 = 0101 1000
et
R : 62 = 0011 11102
2
B G : 73 = 0100 1001
B : 75 = 0100 10112
R : 0010 00112 = 35
2
A G : 0101 0100 = 84
en
Inversement pour retrouver limage cach, on fait lopration inverse : on extrait les bits de
poids faible du pixel reu et on complte par quatre 0.
Dans lexemple prcdent, le pixel A devient :
R : 0011 00002 = 48
2
B G : 0100 0000 = 64
B : 0100 00002 = 64
donc le pixel
Une image de dimension p n sera reprsente par un tableau numpy trois dimensions
n p 3 (noter linversion de n et p). La troisime dimension correspond la couleur (rouge,
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
121
vers ou bleu, indice 0, 1 ou 2). Les valeurs stockes dans ce tableau sont des entiers entre 0
et 255 : on imposera donc ces valeurs dtre du type uint8 de numpy (entiers non signs
cods sur 8 bits).
Dans la suite on suppose quon a import le module numpy.
1. La fonction bin donne la reprsentation binaire dun entier. Les entiers entre 0 et 255
sont reprsents sous la forme dune chane de caractre '0b...' composs de 3 10
caractres.
Pour appliquer lalgorithme de stganographie, on a besoin quil soient reprsents
par des chanes de 8 caractres, sans le prfixe '0b' (les premiers caractres tant
ventuellement nuls).
(a) En utilisant la concatnation mot1+mot2 et lextraction mot[n:p (o n et p peuvent
tre ngatifs), crire une ligne de commande qui transforme une chane de 3 8
caractres 0b... en une chane de 8 caractres exactement, sans le prfixe 0b, les
premiers caractres tant ventuellement nuls.
Par exemple '0b10100' doit devenir '00010100'.
(b) En dduire une fonction tab2bin(tableau) qui prend entre une variable tableau
qui est un tableau numpy de dimensions n p 3 dentiers de type uint8, les transforme en binaire avec la fonction bin, puis les met sous la forme de chanes de 8
caractres.
On rappelle que si f est une fonction dfinie sur les nombres, alors ve
torize(f)
donne une fonction dfinie sur les tableaux numpy.
De plus, tableau.shape donne [n,p,3.
(c) Inversement, ces chanes de 8 caractres peuvent tre transformes en entiers avec
la fonction int(.,2).
crire une fonction bin2tab(tableau) qui prend entre un tableau numpy de
chanes de 8 caractres reprsentant en binaire des entiers entre 0 et 255, cre
un tableau numpy appel tableau2 dont les valeurs sont de type uint8, puis affecte chaque case de tableau2 lentier reprsent par la case correspondant de
tableau. En sortie cette fonction retournera la variable tableau2.
On rappelle que zeros((n,p,3),dtype=uint8) cre un tableau numpy de dimensions n p 3, dont les valeurs sont de type uint8.
122
cre un tableau numpy de mme dimension, dont les cases sont du type S10
(chanes de 10 caractres), appel tab_de
ode ;
applique chaque case de tab_image lalgorithme de dcodage et enregistre
le rsultat dans la case correspondante de tab_de
ode
En sortie la fonction doit retourner le tableau tab_de
ode.
Nous allons maintenant utiliser le module matplotlib.pyplot pour manipuler des images
au format PNG (attention ce dernier point est indispensable). Si image.png est le nom du
fichier (donc une chane de caractres), les commandes :
tableau_float=imread('image.png')
tableau_int=uint8(255*tableau_float)
cre le tableau numpy de dimensions n p 3 associ (pour image.png de dimensions p n),
sous le nom tableau_int.
Ensuite imshow(tableau_int) permet de visualiser limage.
Inversement imsave('image2.png',tableau_int) cre limage PNG associe au tableau
et lenregistre sous le nom image2.png.
3. (a) Donner une fonction image_en
ode(masque, se
ret) qui :
prend en entre deux noms dimages masque et se
ret qui sont des chanes
de caractres ;
cre les tableaux dentiers numpy tab_masque et tab_se
ret associs ;
les transforme en tableaux de chanes de caractres comme indiqu la question 1. ;
leur applique lalgorithme de stganographie et enregistre le rsultat dans une
variable tab_en
ode ;
transforme ce tableau en tableau dentiers comme la question 1. et enregistre
le rsultat dans une variable en
ode ;
affiche limage associe et lenregistre dans le nouveau fichier en
ode.png.
Cette fonction ne renvoie rien en sortie.
(b) Donner une fonction image_de
ode(image) qui :
prend en entre un nom dimage image qui est une chane de caractres ;
cre le tableau dentiers numpy tab_image associ ;
le transforme en tableaux de chanes de caractres comme indiqu la question 1. ;
lui applique lalgorithme de dcodage et enregistre le rsultat dans une variable
tab_de
ode ;
transforme ce tableau en tableau dentiers comme la question 1. et enregistre
le rsultat dans une variable de
ode ;
affiche limage associe et lenregistre dans le nouveau fichier de
ode.png.
Cette fonction ne renvoie rien en sortie.
123
Si on veut essayer tous les chemins possibles, on arrive trs vite un temps colossal, et
calculer un itinraire sur un GPS pourrait prendre plus de 1030 annes !
Lide cl de Dijkstra est la suivante : si un chemin optimal de A vers B apsse par un sommer
X , alors la partie de ce chemin de A X est encore un itinraire optimal de A vers X . En effet,
sil existait un chemin plus rapide de A vers X , il permettrait de rduire le trajet total de A
vers B.
On associe alors, chaque sommet X (autre que A) son prdecesseur p(X ), cest--dire le
sommet immdiatement prcdent dans le chemin optimal menant de A X . Dans lexemple
ci-dessus, on a p(B) = H, p(H) = G, et ainsi de suite jusqu p(C ) = A (le chemin optimal est
indiqu en vert).
La fonction p permet de reconstruire, de proche en proche, pour chaque sommet X , un
chemin optimal de A vers X . On note t (X ) le temps de parcours correspondant.
Au dpart, on ne dispose pas des valeurs dfinitives de t (X ) et p(X ) : on ne se contente que
de valeurs provisoires, respectivement (X ) et (X ), donnes par le meilleur itinraire de A
vers X actuellement connu. Ces valeurs vont voluer, par amliorations successives, vers les
valeurs dfinitives.
Appelons lensemble des sommets du graphe pour lesquels on sait que les fonctions t et p
ont atteint leur valeurs dfinitives. Lalgorithme consiste faire grossir de proche en proche
en lui ajoutant, chaque itration, un nouveau sommet.
Voici comment :
Initialisation :
au dpart = A avec (A) = t (A) = 0 (le trajet optimal de A vers A prend un temps
nul, par un chemin form de zro arte)) ;
pour les sommets X diffrents de A, on ne connat pas de chemin et on initialise
donc (X ) + en convenant que, tant que (X ) naura pas de valeur finie, (X )
ne sera pas dfini.
Une itration se fait en deux tapes :
Dabord, on considre toutes les artes U V dont lorigine U est dans et lextrmit v est lextrieur de Ome g a. Pour chacune delles, on connat un trajet
optimal de A vers U (car U est dans ). En prolongeant ce trajet jusqu V on a un
temps total de parcours gal t (U ) + (U V ), o (U V ) est le temps de parcours
de U V (donn par le graphe).
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
124
125
Troisime itration. On considre les artes AL, AN , C D et ML. Les deux tapes
conduisent = {A,C , M, N }, t (N ) = 3 et p(N ) = A.
Quatrime itration. Les artes considrer sont AL, C D, ML, N P et N R. Le point
suivant tre englob dans est L ave t (L) = 4 et p(L) = A.
Nous modliserons le graphe orient pondr par sa matrice des distances : si il y a n sommets numrots de 0 n 1, on dfinit une matrice A dordre n (avec les lignes et colonnes
numrotes partir de 0 comme en Python) telle que ai j donne le temps de parcours du
sommet i vers le sommet j . Si on ne peut aller de i vers j , on pose ai j = 0.
Les matrices seront reprsents en Python par des listes de listes.
1. (a) crire la matrice des distances du graphe donn en exemple.
(b) Elle est donne dans le fichier Exemple.txt. crire un script Python qui permet
de lire le fichier et denregistrer la matrice dans une variable arbre (commencer
par visualiser le fichier pour comprendre sa strucutre)
2. crire une fonction ind_min(liste,omega) qui prend en entre :
une liste liste de n nombres ;
une liste omega de nombres entre 0 et n 1 ;
et donne en sortie lindice X qui minimise liste[k pour tous les k pris lextrieur
de omega.
3. Dans cette question, on va crire la fonction principale dijkstra(arbre,A,B,sommets) :
arbre est la matrice des distances ;
A est lindice du sommet de dpart ;
B est lindice du sommet darrive ;
sommets est la liste des noms de sommets : sommets[k donne le nom du somme
numro k.
En Python il existe un flottant qui reprsente + : infini=float('inf').
(a) Initialiser les variables suivantes :
n comme le nombre de sommets ;
Omega comme une liste ne contenant que le sommet A ;
tau comme une liste de n nombres gaux infini ;
t comme une liste de n zros ;
pi et p comme deux listes de n fois None.
(b) crire une boucle while effectuant lalgorithme de Dijkstra : la fin t[B donne
le temps de parcours optimal de A vers B, et la trajet optimal est contenu dans la
liste p.
(c) crire la fin du programme qui permet de rcuprer dans p le trajet optimal et
retourne en sortie de la fonction :
le parcours optimal sous forme dune liste de noms de sommets ;
le temps de trajet optimal sous forme dun flottant.
4. Tester avec lexemple donn dans lnonc.
5. Que fait lalgorithme si B nest pas accessible depuis A dans le graphe propos ?
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
126
Le mur a une paisseur e = 40 cm. Les proprits physiques du mur sont constantes : conductivit thermique = 1, 65 W.m 1 .K 1 , capacit thermique massique c p = 1 000 J .kg 1 .K 1 ,
masse volumique = 2 150 kg .m 3 .
On suppose que la temprature dans le mur T ne dpend que du temps t et de la coordonne
x. Lquation qui dcrit lvolution de cette temprature est :
=
T 2 T
=
t
x 2
(1)
Pour rsoudre le problme de manire numrique, on discrtise lespace et le temps. On divise lintervalle [0, e], reprsentant lpaisseur du mur, en N +2 points, numrots de 0 N +1,
rgulirement espacs de x. Cette division est appele discrtisation . La distance x est
appele le pas despace . lintrieur du mur (frontires intrieure et extrieure exclues)
se trouvent donc N points. On cherche obtenir la temprature en ces points particuliers
chaque instant.
127
On remarquera que x =
e
et, pour i 0, N + 1 : xi = i x.
N +1
t
, et k N.
.(x)2
T1k
T k
2
Tk = .
..
T Nk
et
T1
11
T
Tt ousk = 2
...
T N1
T12
T22
...
T N2
. . . T1k
. . . T2k
... ...
. . . T Nk
. . . T1k1 T1k
. . . T2k1 T2k
...
...
...
. . . T Nk1 T Nk
128
calculer le profil de temprature linstant k = 1 (ie t = t ) en disinguant les
cas i = 1, 2 i N 1 et i = N , et laffecter la deuxime colonne de T_tous_k ;
laborer une boucle permettant de calculer itrativement le profil de temprature aux instants tk = k.t (avec k 2), boucle interrompue lorsque le la
norme de Tk Tk1 deviendra infrieur 102 ou lorsque le nombre ditrations atteindra la valeur ItMax ;
retourner en sortie le nombre ditrations nbIter et la matrice T_tous_k.
(xi , tk+1 )
x 2
x 2
129
o on a pos r =
t
, et k N.
.(x)2
Cette quation est appele schma implicite car la temprature linstant t k est exprime en fonction de la temprature linstant ultrieur tk+1 .
Le systme dquations ainsi obtenu peut tre crit sous la forme :
M.Tk+1 = Tk + r.v
o M est une matrice carre N N , et v est un vecteur de taille N faisant intervenir les
conditions aux limites.
(b) Prciser lexpression de la matrice M et lexpression du vecteur v.
chaque pas de temps, il faut inverser le systme matriciel :
M.Tk+1 = Tk + r.v
pour obtenir Tk+1 partir de Tk .
Pour cela, on va utiliser lalgorithme de Thomas qui permet de rsoudre un systme
matriciel tridiagonal de la forme :
M.u = d
o M est une matrice de dimensions N N tridiagonale, et u et d des matrices colonnes de dimension N .
Dans cet algorithme, on calcule dabord les coefficients suivants :
c1 =
ci =
c1
b1
ci
b i ai ci 1
et
d 1 =
d i =
d1
b1
d i ai d i 1
b i ai ci 1
pour i = 2, 3, . . ., N 1
pour i = 2, 3, . . ., N
uN = dN
u i = d i ci u i +1 pour i = N 1, N 2, . . . , 2, 1
(c) En utilisant lalgorithme de Thomas, crire une fonction Cal
Tkp1(M,d) qui permet de calculer le vecteur u.
(d) crire la fonction s
hema_impli
ite(T0,alpha,e,Delta_t,Tint,Text2) en suivant les indications suivantes :
dfinir les constantes ItMax, N, Delta x et r ;
crer avec la matrice T_tous_k de dimensions N I t M ax en la remplissant de
zros ;
remplacer la premire colonne de T_tous_k par T0 ;
calculer le profil de temprature linstant k = 1 (ie t = t ) en disinguant les
cas i = 1, 2 i N 1 et i = N , et laffecter la deuxime colonne de T_tous_k ;
PSI, Lyce Leconte de Lisle, Saint-Denis de la Runion. http://mathcpge.org/
130
laborer une boucle permettant de calculer itrativement le profil de temprature aux instants tk = k.t (avec k 2), boucle interrompue lorsque le la
norme de Tk Tk1 deviendra infrieur 102 ou lorsque le nombre ditrations atteindra la valeur ItMax ;
retourner en sortie le nombre ditrations nbIter et la matrice T_tous_k.