Main 1TSI Cours PYTHON Chap01 To Chap08
Main 1TSI Cours PYTHON Chap01 To Chap08
Main 1TSI Cours PYTHON Chap01 To Chap08
6 Analysis of an algorithm 67
Cours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
7 Sorting recursionless 87
Cours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
1
Objectifs
Les incontournables :
I savoir nommer simplement et efficacement une variable et l’affecter ;
I utiliser del x pour désaffecter la variable x ;
I savoir reconnaître les types de base ;
I savoir utiliser les opérations not, or, and sur les booléens ;
I savoir utiliser les opérations classiques sur les entiers ou sur les flottants ;
I savoir écrire les comparaisons en code Python ;
I savoir écrire les différents types structurés : tuple, chaîne et liste ;
I savoir utiliser les opérations classiques communes à ces types structurés : concaténation,
recherche d’un élément, extraction de tranche, répétition etc. ;
I savoir utiliser les opérations les plus classiques propres aux listes comme append ou la
méthode pop qui permettent d’ajouter ou d’enlever des éléments à une liste ;
I savoir écrire une instruction conditionnelle avec if, elif, else ;
I savoir utiliser range pour créer un intervalle d’entiers ;
I savoir utiliser une boucle for ou une boucle while ;
I savoir utiliser l’instruction break ;
I savoir utiliser la fonction print ;
I savoir utiliser l’instruction assert.
Et plus si affinités :
I Connaître les affectations spécifiques à Python qui permettent l’incrémentation ;
I savoir écrire une succession croissante d’entiers avec un pas fixé et récupérer ou éliminer
des éléments d’une liste avec un pas fixé ;
I savoir utiliser la fonction id :
I savoir faire un dépaquage de tuples ;
I savoir utiliser les opérations des listes un peu plus exotiques : sort, count, insert, sum, del.
2 CHAPITRE 1
Cours
Variables et types
1. Un exemple d’affectation
Commençons par observer un exemple d’affectation :
I n [ 1 ] : v a r 1 = 6+7
I n [ 2 ] : var1 , i d ( var1 ) , type ( var1 )
Out [ 2 ] : ( 1 3 , 1 4 0 7 0 7 5 4 3 0 0 5 3 4 4 , i n t )
• La table des symboles, où sont stockés les noms des objets. À chaque nom d’objet est associé
un type noté type et une adresse notée id dans la table des valeurs. L’adresse représente la
position de l’objet, elle est repérée par un nombre ;
• La table des valeurs, où sont stockées les valeurs des objets. Ce stockage se fait sous forme
binaire (suites de bits valant 0 ou 1).
Ainsi dans l’exemple précédent, la valeur stockée dans la table des valeurs pour var1 est 1101.
Plus précisément, Python procède en deux temps : d’abord il évalue 6 + 7 puis il stocke le résultat
obtenu donc 1101 dans la table des valeurs et note l’adresse utilisée. Enfin, il inscrit le nom var1
dans la table des symboles en précisant le type et l’adresse associés.
Si l’on réaffecte notre variable var1, c’est-à-dire si l’on lui donne une autre valeur, l’adresse change.
En fait, Python supprime le nom de la table des symboles puis le réinscrit, c’est une nouvelle adresse
qui est créée.
I n [ 4 ] : v a r 1 = 47∗2
I n [ 5 ] : var1 , i d ( var1 )
Out [ 5 ] : ( 9 4 , 1 4 0 7 0 7 5 4 3 0 0 7 9 3 6 )
Out [ 7 ] : ( 3 . 0 1 , f l o a t )
I n [ 8 ] : var3 = complex ( 1 , 2 )
I n [ 9 ] : var3 , type ( var3 )
Out [ 9 ] : ((1+2 j ) , c o m p l e x )
In [ 1 0 ] : v a r 4 = (3 <8)
In [ 1 1 ] : var4 , type ( var4 )
Out [ 1 1 ] : ( True , b o o l )
In [ 1 2 ] : v a r 5 =(3>8)
In [ 1 3 ] : var5 , type ( var5 )
Out [ 1 3 ] : ( False , bool )
In [ 1 4 ] : var6 = " tout cela est trop simple "
In [ 1 5 ] : var6 , type ( var6 )
Out [ 1 5 ] : ( ’ tout cela est trop simple ’ , s t r )
In [ 1 6 ] : v a r 7 = n o t (3>=8)
In [ 1 7 ] : var7
Out [ 1 7 ] : True
In [ 1 8 ] : v a r 8 = (4==8) o r (4 <8) ; v a r 9 = (4==8) and (4 <8)
In [ 1 9 ] : var8 , var9
Out [ 1 9 ] : ( True , F a l s e )
3. Les opérations classiques. On a commencé à en voir avec le dernier exemple. a >= b (respec-
tivement a <= b) signifie que a est supérieur ou égal (respectivement inférieur ou égal) à b. Pour
la comparaison, l’égalité entre a et b est a == b et pour signifier que a n’est pas égal à b, on écrit
a != b. Le produit de a et b se tape a*b et a à la puissance b est a ** b. Notons que pour écrire
une puissance de 10, on peut taper 1e - 7 et ce qui donne 10−7 . Puis max(a,b) (respectivement
min(a,b)) renvoie le maximum (respectivement le minimum) entre a et b. Enfin la commande
4 CHAPITRE 1
int(a) donne l’entier le plus proche de a.
4. L’instruction assert. Si l’on tape assert p où p est une proposition, l’exécution envoie un
message d’erreur si p est fausse.
I n [ 2 2 ] : a s s e r t 3 <= 5
I n [ 2 3 ] : a s s e r t 5 <= 3
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
F i l e "<i p y t h o n −i n p u t −23−4b731aa5c1c2 >" , l i n e 1 , i n <module>
a s s e r t 5 <= 3
AssertionError
I n [ 2 3 ] : F a l s e = 2023
F i l e "<i p y t h o n −i n p u t −23−1a b 1 d 7 6 c 5 f 7 b >" , l i n e 1
F a l s e = 2023
^
SyntaxError : cannot a s s i g n to F a l s e
Notons enfin que Python fait la différence entre les majuscules et les minuscules. On peut ainsi
noter une variable false mais il vaut mieux éviter ce genre de pirouette.
6. Affectation
La commande d’affectation est le symbole = comme on a vu plus haut. Attention donc, a=8 signifie
que l’on affecte la valeur 8 à a et a==8 est une instruction booléene de valeur True si 8 est affecté
à a et de valeur False sinon.
In [ 2 4 ] : # affectations successives
In [ 2 5 ] : a = 5 ; b = 3∗ a
In [ 2 6 ] : a,b
Out [ 2 6 ] : (5 , 15)
In [ 2 7 ] : # affectations simultanees
In [ 2 8 ] : a = b = −5
In [ 2 9 ] : a ,b , id (a) , id (b)
Out [ 2 9 ] : ( −5 , −5, 1 4 0 7 0 7 5 4 3 0 0 4 7 6 8 , 1 4 0 7 0 7 5 4 3 0 0 4 7 6 8 )
In [ 3 0 ] : # affectations paralleles
In [ 3 1 ] : a , b , c = 3 ,4 ,5
In [ 3 2 ] : c−a+b ∗∗2
Out [ 3 2 ] : 18
I n [ 7 5 ] : x=1
In [ 7 6 ] : x , id (x)
Out [ 7 6 ] : ( 1 , 1 4 0 7 0 7 9 5 4 7 0 2 1 1 2 )
In [ 7 7 ] : del x
In [ 7 8 ] : x
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
F i l e "<i p y t h o n −i n p u t −78−6 f c f 9 d f b d 4 7 9 >" , l i n e 1 , i n <module>
NameError : name ’ x ’ i s n o t d e f i n e d
6 CHAPITRE 1
8. Affectations spécifiques à Python qui permettent l’incrémentation
• L’instruction x += y est équivalente à x = x+y ;
• L’instruction x -= y est équivalente à x = x-y ;
• L’instruction x *= y est équivalente à x = x*y ;
• L’instruction x **= y est équivalente à x = x**y (mathématiquement xy ) ;
• L’instruction x /= y est équivalente à x = x/y ;
Boucles simples
1. Plantons le décor
Un programme est composé d’une suite d’instructions, exécutées l’une après l’autre dans l’ordre
où elles sont écrites, contenant des définitions de variables et de fonctions (on verra plus loin des
fonctions usuelles), des affectations, des boucles (simples ou imbriquées), des instructions condition-
nelles qui utilisent des expressions pouvant être des résultats d’appels de fonctions (l’aboutissement
ce sont les fonctions récursives que l’on voit en TSI1 au printemps).
On distingue deux types de boucles (pour l’instant les boucles simples).
• les boucles conditionnelles
while condition :
instructions
f o r e l t in sequence :
instructions
Avec une boucle non conditionnelle, le bloc d’instructions est répété par exemple n fois si n est la
longueur de la séquence. Cette séquence peut être une liste, un tuple, une chaîne de caractères).
Nous verrons plus loin ce qu’est une liste ou un tuple en Python. La variable elt prend la valeur
de l’un des n éléments de la séquence. Donnons un exemple.
In [ 9 ] : f o r i in range (4) :
...: i=i +1
In [ 1 0 ] : i
Out [ 1 0 ] : 4
# VARIANTE q u i donne l e meme r e s u l t a t
I n [ 9 ] : f o r i i n r a n g e ( 4 ) : i=i +1
Avec le code qui suit qui utilise une boucle conditionnelle, on aboutit au même résultat.
En général, si l’on connait avant de démarrer la boucle le nombre d’intérations à exécuter, on choisit
une boucle for. Au contraire, si la décision d’arrêter la boucle ne peut se faire que par un test, on
choisit une boucle while Nous verrons plus loin des exemples utilisant la boucle appropriée.
8 CHAPITRE 1
k Mode 1.1.—
S = 1 ∗∗ 2
f o r k i n r a n g e ( 2 , 6 ) : S += k ∗∗2
S
P = 1
f o r k i n r a n g e ( 2 , 6 ) : P ∗= k
P
On obtient 5! = 120.
n
Y
I De façon générale, pour écrire P = ak , on peut utiliser encore une boucle
k=1
comparable à celle de la somme en remplaçant S += par P *=
On peut aller plus loin, par exemple si l’on veut calculer des coefficients binomiaux nk (qui sont
des entiers), on peut le faire en calculant des factorielles et en faisant le rapport, on peut utiliser
des fonctions récursives (voir plus tard) et il existe des modules qui les donne directement (par
exemple la fonction binom de scipy.special mais ça ce sera pour ceux qui en veulent plus).
Remarque : Ne pas confondre a//b qui est le quotient de la division de a par b et est donc toujours
In [ 2 1 ] : 17 // 4
Out [ 2 1 ] : 4
In [ 2 2 ] : 17/4
Out [ 2 2 ] : 4.25
3. Instruction conditionnelle
On utilise les instructions prédéfinies en Python qui sont if, elif et else de la façon suivante.
# c a s d ’ une a l t e r n a t i v e
i f condition :
instructions1
else :
instructions2
# c a s de p l u s i e u r s a l t e r n a t i v e s
i f condition1 :
instructions1
e l i f condition2 :
instructions2
e l i f condition3 :
instructions3
else :
instructions4
Par exemple :
I n [ 2 8 ] : x = 10
In [ 2 9 ] : i f x < 5 :
...: p r i n t ( x , " e s t p l u s p e t i t que 5 " )
. . . : else :
...: p r i n t ( x , " e s t e g a l ou p l u s g r a n d que 5 " )
...:
10 e s t e g a l ou p l u s g r a n d que 5
10 CHAPITRE 1
I n [ 1 ] : a=3
I n [ 2 ] : p r i n t ( 2 ∗ a , a ∗a , a ∗ ∗ 1 0 )
6 9 59049
On voit aussi sur l’exemple du paragraphe précédent que print peut afficher du texte et la syntaxe
est print("texte")
Exercice 01 Affecter 5 à la variable x puis écrire le code qui affiche « x est positif » si x > 0 et
qui affiche « x est negatif ou nul » sinon.
Remarque : Il existe une autre fonction qui agit comme print c’est-à-dire affiche le résultat.
C’est return. Mais attention, il y a une différence importante. Si l’on fait appel à print trois fois
consécutivement par exemple, il y aura trois affichages et pour return, c’est le premier exécuté qui
s’affiche. On reviendra sur return plus loin au moment de la construction de procédures Python.
Cette fonction sera alors tout à fait adéquate.
5. L’instruction break
L’instruction break permet de casser l’exécution d’une boucle while ou for. Elle fait sortir de la
boucle et passer à l’instruction suivante éventuelle.
In [ 1 ] : f o r i in range (10) :
...: p r i n t ( " debut i t e r a t i o n " , i )
...: p r i n t ( " good bay " )
...: i f i == 2 :
...: break
...: print (" fin iteration " , i )
. . . : print ( " cette h o r r i b l e boucle est f i n i e " )
debut i t e r a t i o n 0
good bay
fin iteration 0
debut i t e r a t i o n 1
good bay
fin iteration 1
debut i t e r a t i o n 2
good bay
cette h o r r i b l e boucle est f i n i e
Notons enfin que dans le cas de boucles imbriquées (voir plus loi dans le cours), l’instruction break
ne fait sortir que de la boucle la plus interne.
6. Les chaînes, les ensembles, les tuples et les listes
Dans tout programme Python, on rencontre rapidement ces types de structures. Il faut les recon-
naître et utiliser les bonnes syntaxes.
6-1 Commençons par les tuples
Un tuple permet de créer une collection ordonnée de plusieurs éléments. Ce sont mathémati-
quement des p-uplets. Comme pour les p-uplets, un tuple peut commencer par ( et finir par ),
c’est-à-dire des parenthèses. Mais ce n’est pas obligatoire comme nous allons le voir.
V a l u e E r r o r : t o o many v a l u e s t o unpack ( e x p e c t e d 3 )
# on v o i t que d a n s l e t u p l e on a t t e n d 3 e l e m e n t s
In [ 1 8 ] : a , b , c
Out [ 1 8 ] : ( ’ m i c k e y ’ , [ ’ d o n a l d ’ , ’ p i c s o u ’ ] , ’ d a i s y ’ )
# on a a l o r s b i e n 3 e l e m e n t s c a r 2 e l e m e n t s
# s e s o n t c o n c a t e n e s en une l i s t e ( v o i r 5−3)
12 CHAPITRE 1
6-2 Continuons par les chaînes de caractères
Une chaîne de caractère en Python ou string est une série ordonnée de caractères. Elle peut être
une combinaison d’une ou plusieurs lettres, chiffres et caractères spéciaux. Comme pour les tuples,
on ne peut pas modifier une chaîne de caractères une fois créée. Elle est non mutable. Une chaîne
de caractères commencent et finissent par des apostrophes ou des guillemets. Ainsi on a déjà écrit
des chaînes de caractères plus haut. elles sont de type str et par exemple "mickey" est une chaîne
de caractères.
Comme pour les tuples, les opérations possibles sont : longueur, accès par indice positif, concaté-
nation avec +, répétition avec * et tranche. Nous allons donner des exemples détaillés.
Concaténation et répétition des chaînes de caractères en Python
Pour la concaténation :
I n [ 1 ] : s t r 1 = ’ S a l u t ! ’ ; s t r 2 = ’ l e s champions ’
# premiere syntaxe
In [ 3 ] : # autre syntaxe
Pour la répétition :
Out [ 7 ] : ’ S a l u t ! l e s c h a m p i o n s S a l u t ! l e s c h a m p i o n s S a l u t ! l e s
champions S a l u t ! l e s champions S a l u t ! l e s champions S a l u t ! l e s
champions S a l u t ! l e s champions S a l u t ! l e s champions ’
On remarque comme prévu que g et G ne sont pas identiques et ne sont donc pas à la même adresse.
In [ 2 1 ] : s t r 3 = ’ python e s t t r o p chouette ’
I n [ 2 2 ] : s t r 3 [ 0 ] , s t r 3 [ −1] , s t r 3 [ 6 ] , s t r 3 [ 2 3 ]
Out [ 2 2 ] : ( ’ p ’ , ’ e ’ , ’ ’ , ’ e ’ )
# r e m a r q u e r que l e s e s p a c e s d a n s s t r 3 comptent chacun p o u r un
caractere
In [ 2 3 ] : str3 [2 : 5]
Out [ 2 3 ] : ’ t h o ’
# On a une commande q u i r e n v o i e t o u t e l a c h a i n e
In [ 2 4 ] : str3 [ : ]
Out [ 2 4 ] : ’ p y t h o n e s t t r o p c h o u e t t e ’
I n [ 2 5 ] : # on a une commande q u i pe rm e t de s a u t e r d e s i n d i c e s i c i
de i n d i c e 1 a i n d i c e 8 en s a u t a n t 1 i n d i c e s u r 2
In [ 2 6 ] : str3 [ 2 : 9 : 2 ]
Out [ 2 6 ] : ’ t o s ’
In [ 2 7 ] : str3 [ 0 : 9 : 1 ]
Out [ 2 7 ] : ’ p y t h o n e s ’
In [ 2 8 ] : str3 [ : : 3 ]
Out [ 2 8 ] : ’ ph t r o t ’
14 CHAPITRE 1
Caractère d’immuabilité d’une chaîne de caractères. Revenons sur le fait que les chaînes
de caractères en Python ne peuvent pas être modifiées. Reprenons l’exemple de str3 précédent.
I n [ 3 2 ] : s t r 3 [ 0 ] = ’P ’
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
# U t i l i s a t i o n de l a b o u c l e f o r e t de r a n g e
In [ 3 3 ] : L = [ k f o r k in range (0 ,11 ,2) ]
In [ 3 4 ] : L
Out [ 3 4 ] : [ 0 , 2 , 4 , 6 , 8 , 1 0 ]
Exercice 04 : Créer une liste composé des 10 premiers cubes d’entiers en utilisant une boucle for
# U t i l i s a t i o n de l ’ o p e r a t e u r ∗
In [ 3 5 ] : 14∗[0]
Out [ 3 5 ] : [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]
I n [ 2 ] : c = [ " B o n n i e " , " C l y d e " , " L a u r e l " , " Hardy " , " T r i s t a n " , " I s e u " ]
16 CHAPITRE 1
In [ 4 ] : for k in c :
...: p r i n t ( "k vaut " , k )
...:
k vaut Bonnie
k vaut Clyde
k vaut Laurel
k v a u t Hardy
k vaut Tristan
k vaut I s e u
Pour ajouter en fin de liste, on utilise append, pour ajouter entre deux éléments, on utilise insert.
Pour enlever le dernier élément de L, on utilise L.pop() et pour enlever l’élément d’indice i, on
utilisera L.pop(i). On peut remarquer que ces opérations transforment définitivement la liste.
In [ 6 4 ] : L = [1 ,2 ,3 ,4 ,5 ,6 ,7]
I n [ 6 5 ] : e l t = L . pop ( )
In [ 6 6 ] : elt , L
Out [ 6 6 ] : ( 7 , [ 1 , 2 , 3 , 4 , 5 , 6 ] )
I n [ 6 7 ] : # P u i s on e n l e v e l ’ e l e m e n t d ’ i n d i c e 3 q u i e s t 4
I n [ 6 8 ] : n e w _ e l t = L . pop ( 3 )
I n [ 6 9 ] : new_elt , L
Out [ 6 9 ] : ( 4 , [ 1 , 2 , 3 , 5 , 6 ] )
I n [ 7 0 ] : # on c h e r c h e l ’ emplacement de L d a n s l a memoire
In [ 7 1 ] : id (L)
Out [ 7 1 ] : 2658740700224
I n [ 7 2 ] : # on r e m e t 7 a l a f i n de L
I n [ 7 3 ] : L . append ( 7 )
In [ 7 4 ] : L
Out [ 7 4 ] : [ 1 , 2 , 3 , 5 , 6 , 7 ]
I n [ 7 5 ] : # P u i s on e n l e v e 7 de nouveau
I n [ 7 6 ] : L . pop ( )
Out [ 7 6 ] : 7
In [ 7 7 ] : L
Out [ 7 7 ] : [ 1 , 2 , 3 , 5 , 6 ]
In [ 7 8 ] : id (L)
Out [ 7 8 ] : 2658740700224
I n [ 7 9 ] : # C o n c l u s i o n : a p r e s l ’ a c t i o n de append e t pop ( ) , L s e
r e t r o u v e a l a meme p l a c e d a n s l a memoire qu ’ a v a n t c e s deux
a c t i o n s e t donc i l s ’ a g i t de l a meme l i s t e .
18 CHAPITRE 1
Pour finir le paragraphe des types structurés, on va maintenant mélanger les genres. En effet, les
tuples, les listes et les chaînes de caractères peuvent cohabiter dans le meilleur des mondes. C’est
l’occasion d’utiliser quelques unes des opérations propres à ces types structurés.
In [42]: t1 = 1, 3, 5
In [43]: t2 = " A l f r e d " , 20
In [44]: t3 =(" A l f r e d " , 2 0 , [ " T r a i l " , " T r i a t h l o n " ] )
In [45]: t4 =(" A l f r e d " , 2 0 , ( " t r a i l " , " t r i a t h l o n " ) )
In [ 4 6 ] : t2 [ 0 ]
Out [ 4 6 ] : ’ A l f r e d ’
In [ 4 7 ] : type ( t3 )
Out [ 4 7 ] : t u p l e
In [ 4 8 ] : type ( t3 [ 2 ] )
Out [ 4 8 ] : l i s t
In [ 4 9 ] : type ( t4 [ 2 ] )
Out [ 4 9 ] : t u p l e
I n [ 5 0 ] : t 3+t 4
Out [ 5 0 ] : ( ’ A l f r e d ’ , 2 0 , [ ’ T r a i l ’ , ’ T r i a t h l o n ’ ] , ’ A l f r e d ’ , 2 0 , ( ’
trail ’ , ’ triathlon ’))
In [ 5 1 ] : t3 [2]+ t4 [ 2 ]
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
F i l e "<i p y t h o n −i n p u t −51−4cea6a805325 >" , l i n e 1 , i n <module>
t3 [2]+ t4 [ 2 ]
T y p e E r r o r : can o n l y c o n c a t e n a t e l i s t ( n o t " t u p l e " ) t o l i s t
I n [ 5 2 ] # on ne p e u t donc p a s c o n c a t e n e r un t u p l e e t une l i s t e
In [ 5 3 ] : l e n ( t3 ) , l e n ( t4 )
Out [ 5 3 ] : ( 3 , 3 )
In [ 5 6 ] : t3 [ 2 ] [ 0 ]
Out [ 5 6 ] : ’ T r a i l ’
In [ 5 7 ] # F i n i s s o n s par p l u s i e u r s o p e r a t i o n s a l a f o i s
I n [ 5 8 ] : t 1 ∗3+ t 2
Out [ 5 8 ] : ( 1 , 3 , 5 , 1 , 3 , 5 , 1 , 3 , 5 , ’ A l f r e d ’ , 2 0 )
In [ 7 9 ] : S = [ ]
In [ 8 0 ] : f o r a in range (1 ,6) :
...: f o r b in range (1 ,6) :
...: S . append ( [ a , b ] )
Que fait cette double boucle ? Au départ, on crée une liste S qui est la liste vide. Puis on pose
a = 1 et on ajoute avec l’attribut append dans L les listes [1,b] où b varie de 1 à 5. Puis on pose
a = 2 et on continue en ajoutant dans L les listes [2,b] où b varie de 1 à 5. On s’arrête à a = 5 et
le dernier élément ajouté est [5,5]. On remarque que S devient une liste de listes. Vérifions.
In [ 8 1 ] : p r i n t (S)
[[1 , 1] , [1 , 2] , [1 , 3] , [1 , 4] , [1 , 5] , [2 , 1] , [2 , 2] , [2 , 3] ,
[2 , 4] , [2 , 5] , [3 , 1] , [3 , 2] , [3 , 3] , [3 , 4] , [3 , 5] , [4 ,
1] , [4 , 2] , [4 , 3] , [4 , 4] , [4 , 5] , [5 , 1] , [5 , 2] , [5 , 3] ,
[5 , 4] , [5 , 5]]
3 X
X 4
Exercice 05 Écrire une double boucle utilisant for et range qui retourne ij.
i=1 j=1
On pourra appeler S le résultat et initialiser avec S = 0.
Pour finir, l’imbriquement peut concerner des instructions conditionnelles. Par exemple :
In [ 8 2 ] : a = 2
In [ 8 3 ] : i f a > 0 :
...: i f a % 2 == 0 :
...: p r i n t ( " l e nombre est p o s i t i f et pair " )
...: else :
...: p r i n t ( " l e nombre p o s i t i f est impair " )
...:
l e nombre e s t p o s i t i f e t p a i r
In [ 8 4 ] : a = − 2
In [ 8 5 ] : i f a > 0 :
...: i f a % 2 == 0 :
...: p r i n t ( " l e nombre est p o s i t i f et pair " )
...: else :
...: p r i n t ( " l e nombre p o s i t i f est impair " )
In [ 8 6 ] :
Dans le second cas, il n’y a rien d’afficher. C’est normal l’instruction if intérieure n’est pas sollicitée.
Enfin, on peut imbriquer des while, des for, des if etc. Que du bonheur !
20 CHAPITRE 1
Chapitre 2
Introduction to functions and
procedures
21
Objectifs
Les incontournables :
I connaître la syntaxe pour créer une fonction Python ;
I connaître la différence entre return x et print(x) dans une fonction.
Et plus si affinités :
I savoir faire la différence entre une variable locale et une variable globale dans une pro-
cédure ;
I savoir créer une variable globale ;
I savoir créer une fonction booléenne.
22 CHAPITRE 2
Cours
Définition et création d’une fonction sous Python
1. Définition
Une fonction (on peut dire aussi procédure) est au sens informatique un ensemble d’instructions
regroupées sous un nom qui renvoie un résultat lorsque son exécution se termine. Elle représente
un sous-programme relativement indépendant du reste du programme et elle peut être appelée en
plusieurs endroits du programme. En Python, le type correspondant est function et la définition
d’une fonction doit impérativement respecter les règles ci-dessous.
• La première ligne de la définition commence par le mot-clé def suivi du nom de la fonction,
de parenthèses entourant les paramètres (on dit aussi arguments) de la fonction séparés par
des virgules puis du caractère « deux points ». Le nombre d’arguments est variable selon la
fonction créée, certaines fonctions n’ont pas d’argument (attention elles conservent quand-
même le parenthésage ())
• Les lignes suivantes (là aussi le nombre de lignes est variable selon la fonction) constituent
le bloc d’instructions, indenté par rapport à la ligne de définition et forment le corps de
la fonction. Dans ce bloc d’instruction, on peut rencontrer des boucles, des instructions
conditionnelles et qui peuvent être imbriquées ;
• Le retour à la ligne signale la fin de la définition de la fonction.
Pas de begin ou de end. C’est l’indentation des lignes qui permet d’isoler le corps de la fonction.
2. L’instruction return et la différence avec print
Cette instruction return est assez fondamentale dans la construction d’une fonction. Elle n’est
pas obligatoire (voir par exemple ma_fonction du paragraphe suivant), mais souvent très utile.
En effet son appel dans la procédure permettra de renvoyer non seulement (et d’afficher) le (ou
les) résultat(s) voulu(s) mais aussi d’affecter à NOMDEFONCTION la valeur trouvée.
En effet, supposons avoir construit la fonction NOMDEFUNCTION(argument1,argument2) alors on
donne une valeur à argument1 et à argument2, respectivement v1 et v2.
On tape alors NOMDEFUNCTION(v1,v2) et un résultat doit s’afficher. C’est la commande return
qui va permettre cela.
Donnons un exemple. On crée une fonction de nom : multiplie_par_11 ayant un seul argument
n et qui doit renvoyer 11n. La commande appropriée est alors return 11*n
On remarque donc que a priori les deux fonctions sont comparables. Maintenant tapons :
I n [ 5 ] : m u l t i p l i e _ p a r _ 1 1 ( 7 ) ∗2
Out [ 5 ] : 154
I n [ 6 ] : n e w _ m u l t i p l i e _ p a r _ 1 1 ( 7 ) ∗2
77
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
T y p e E r r o r : u n s u p p o r t e d o p e r a n d t y p e ( s ) f o r ∗ : ’ NoneType ’ and ’ i n t
’
La différence c’est que new_multiplie_par_11(7) ne fait que renvoyer l’affichage du résultat qui
est 77, c’est un NoneType pour Python et on ne peut pas le multiplier par 2 qui est un entier.
Conclusion : si seulement afficher le résultat compte, un print en fin de corps d’instruction suffira
et si par contre on doit utiliser le résultat dans d’autres opérations (voire dans d’autres fonctions),
un return s’impose.
Warning : il faut quand même utiliser return avec modération dans la création d’une fonction.
En effet, l’instruction return interrompt l’exécution de la fonction : aucune des instructions situées
après le premier return ne sera exécutée.
Le mieux encore une fois c’est un exemple pour comprendre et visualiser le problème.
24 CHAPITRE 2
In [ 3 ] : def multiplie_par_11 (n) :
...: r e t u r n ( " a r r e t e z vos etudes ! " )
...: r e t u r n 11∗ n
...:
In [ 4 ] : multiplie_par_11 (5)
Out [ 4 ] : ’ a r r e t e z v o s e t u d e s ! ’
Par contre dans le cas de boucles conditionnelles imbriqués, chaque racine de ces boucles peut
contenir un return qui ne sera pas en compétition avec les autres. On le verra plus loin dans des
fonctions plus élaborées que celles du début du cours.
Exercice 01 : Écrire une procédure MIXAGE_SOM_PROD d’arguments x et y et qui renvoie un couple
de première composante la somme de x par y et de seconde composante le produit de x par y.
On désire ensuite obtenir MIXAGE_SOM_PROD(4,2)**3 Que tape t-on ?
3. Exemple de fonction sans argument. Introduction aux variables locales et globales
In [ 5 ] : def ma_fonction ( ) :
...: x = 2
...: p r i n t ( " x vaut {x} dans l a f o n c t i o n " )
In [ 6 ] : ma_fonction ( )
x vaut 2 dans l a f o n c t i o n
In [ 7 ] : print (x)
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
In [ 8 ] : def ma_fonction ( x ) :
...: p r i n t ( " x vaut {x} dans l a f o n c t i o n " )
In [ 9 ] : ma_fonction (2)
x vaut 2 dans l a f o n c t i o n
In [ 1 3 ] : def ma_fonction ( ) :
...: print (x)
In [ 1 4 ] : x=3
In [ 1 5 ] : ma_fonction ( )
3
In [ 1 6 ] : print (x)
3
Ici comme x a été réaffecté hors procédure, elle reste donc visible en dehors de celle là.
In [ 1 3 ] : def ma_fonction ( ) :
...: print (x)
In [ 1 4 ] : x=3
In [ 1 5 ] : ma_fonction ( )
3
In [ 1 6 ] : print (x)
3
Par contre Python ne permet pas directement la modification d’une variable globale dans le corps
de la procédure.
In [ 1 7 ] : def ma_fonction ( ) :
...: x = x+1
I n [ 1 8 ] : x =1
In [ 1 9 ] : ma_fonction ( )
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
F i l e "<i p y t h o n −i n p u t −19−b 2 0 f c 4 8 0 8 f 4 9 >" , l i n e 1 , i n <module>
ma_fonction ( )
F i l e "<i p y t h o n −i n p u t −17−227 aa57c397b>" , l i n e 2 , i n m a _ f o n c t i o n
x = x+1
UnboundLocalError : l o c a l v a r i a b l e ’ x ’ r e f e r e n c e d before
assignment
Il faut indiquer à Python que x est bien une variable globale. Et alors ça fonctionne !
26 CHAPITRE 2
In [ 2 5 ] : def ma_fonction ( ) :
...: global x
...: x=x+1
...: return x
In [ 2 6 ] : x=1
In [ 2 7 ] : ma_fonction ( )
Out [ 2 7 ] : 2
In [ 7 ] : a = 5
In [ 8 ] : def f ( x ) :
...: a = 2
...: r e t u r n a∗x
In [ 9 ] : f (3) , a
Out [ 9 ] : ( 6 , 5 )
En effet, pour calculer f(3) , Python a utilisé la valeur 2 poue a mais quand on lui demande
d’afficher a à l’extérieur de la procèdure, il se souvient que a vaut 5. Allons chercher global dans
le rôle de Zorro.
In [ 1 1 ] : a = 5
In [ 1 2 ] : def f (x) :
...: global a
...: a = 2
...: r e t u r n a∗x
In [ 1 3 ] : f (3) , a
Out [ 1 3 ] : ( 6 , 2 )
In [ 6 ] : def SOMME_SPECIALE( n ) :
...: s = 0
...: f o r i i n r a n g e ( 1 , n+1) :
...: f o r j i n r a n g e ( 1 , n+1) :
...: s += ( i ∗ ∗ 3 ) ∗ ( j ∗ ∗ 2 )
...: return s
...:
I n [ 7 ] : SOMME_SPECIALE( 1 0 )
Out [ 7 ] : 1164625
I n [ 8 ] : SOMME_SPECIALE ( 0 )
Out [ 8 ] : 0
I n [ 1 ] : d e f UNKNOWN01( n ) :
...: f o r i in range (20) :
...: i f ( i ∗ n ) % 3 == 0 :
...: p r i n t ( i ∗n , " ∗ " )
...: else :
...: p r i n t ( i ∗n )
Que fait cette fonction ? Si l’on tape UNKNOWN01(5), que va t-elle afficher ?
Exemple 03. Soit la fonction mathématique g définie sur [0, 2[ par :
x pour 0 6 x < 1
g : x 7→
1 pour 1 6 x < 2
28 CHAPITRE 2
Créer une fonction Python nommée g d’argument x qui retourne g(x) puis écrire l’instruction qui
affiche la liste des valeurs g(1/k) pour k ∈ [[1, 6]].
Si l’on affiche la liste des valeurs g(k) pour k ∈ [[1, 6]], qu’obtient-on ?
Indication : pour la création de la fonction, on utilisera les instructions conditionnelles if, elif
et else. On pourra faire afficher « valeur de l’antecedent erroné » dans le cas où x ∈ / [0, 2[ dans
la procédure. Par ailleurs, on rappelle que a < x and x <= b signifie que x ∈]a, b].
Réponse :
In [ 3 ] : def g(x) :
...: i f 0 <= x and x < 1 :
...: return x
...: e l i f 1 <= x and x <2 :
...: return 1
...: else :
...: p r i n t ( " v a l e u r de l ’ a n t e c e d e n t e r r o n e " )
In [ 4 ] : [ g ( k ) f o r k in range (1 ,7) ]
v a l e u r de l ’ a n t e c e d e n t e r r o n e
v a l e u r de l ’ a n t e c e d e n t e r r o n e
v a l e u r de l ’ a n t e c e d e n t e r r o n e
v a l e u r de l ’ a n t e c e d e n t e r r o n e
v a l e u r de l ’ a n t e c e d e n t e r r o n e
Out [ 4 ] : [ 1 , None , None , None , None , None ]
I n [ 5 ] : [ g (1/ k ) f o r k i n range ( 1 , 7 ) ]
Out [ 5 ] : [ 1 , 0 . 5 , 0 . 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 , 0 . 2 5 , 0 . 2 ,
0.16666666666666666]
g(x) pour 06x<2
f : x 7→ ,
x(x − 2) pour x>2
Exemple 05. Nous allons créer une fonction booléenne donc qui retourne True ou False. Ce
type de fonction se rencontre fréquemment. Nous allons tester si une liste est un palindrome. Un
palindrome se lit indifféremment de gauche à droite ou de droite à gauche en gardant le même
sens. Par exemple [lamarieeiramal] ou [12321].
Nommons notre fonction palindrome d’argument L qui renverra True si L est un palindrome et
False si L ne l’est pas.
Posons donc L une liste que l’on veut tester et de longueur n, l’idée est de commencer par tester
L[0] != L[n-1]
Si cette assertion est vraie alors on retourne False puis on teste L[1] != L[n-2]
Si cette assertion est vraie alors on retourne False et on continue ainsi.
On peut donc créer une boucle for qui fait varier i de 0 jusqu’à non pas n−1 (ce serait maladroit !)
mais jusqu’à n//2.
Enfin imaginons que l’on a jamais L[i] != L[n-1-i] Dans ce cas, il faut retourner True. On
prendra soin de l’écrire après la fin de la boucle for. Voilà ce que cela donne :
30 CHAPITRE 2
Exemple 06. Donnons un cas avec beaucoup plus d’arguments. Il s’agit ici d’une procédure qui
a 5 arguments : une fonction f, trois flottants t0, t1, y0 et un entier n. Cette procédure renvoie
une courbe qui représente une solution d’équation différentielle par la méthode d’Euler. Vous
comprendrez les codes Python utilisés dans le bloc d’instruction de cette fonction EulerAffich
plus tard dans l’année et en TSI2.
I n [ 2 2 ] : d e f E u l e r A f f i c h ( f , t0 , tn , n , y0 ) :
h = ( tn−t 0 ) / f l o a t ( n ) ; ymin = y0 ; ymax = y0
t = t 0 ; y = y0 ; T = [ t 0 ] ; Y = [ y0 ]
f o r k in range (n) :
y = y + h∗ f ( y , t ) ; t = t + h
ymin = min ( ymin , y )
ymax = max ( ymax , y )
T . append ( t ) ; Y . append ( y )
d e l t a T = ( tn−t 0 ) /10 ; d e l t a Y = ( ymax−ymin ) /10
p l t . p l o t (T , Y , c o l o r = ’ b ’ ) ; p l t . g r i d ( )
p l t . a x i s ( [ t0−d e l t a T , t n+d e l t a T , ymin−d e l t a Y , ymax+
deltaY ] )
plt . axhline ( color = ’ 0 ’ )
p l t . a x v l i n e ( c o l o r = ’ 0 ’ ) ; p l t . show ( )
Remarque : On peut remarquer que dans le cas de la création d’une fonction un peu longue
comme celle là, on peut mettre plusieures commandes indépendantes sur la même ligne de code en
les séparant par ;
Exemple 07. Il y a un cas important non encore développé pour l’instant. C’est le cas où la fonction
est appelée à l’intérieur de son bloc d’instruction. On parle de fonction récursive. Un chapitre spécial
sera consacré bien plus tard dans l’année à ce type de fonction. Il faudra avoir étudié les suites
réelles auparavant en Maths. Donnons quand même juste pour le fun une fonction qui s’appelle elle-
même pour voir ce que c’est. Reprenons la fonction g de l’exemple 03 et transformons la fonction
f de l’exemple 04.
g(x) si 0 6 x < 2
Soit la fonction mathématique newf définie sur [0, +∞[ par : x 7→ .
f (x − 2) si x>2
La fonction Python nommée newf d’argument x qui retourne newf(x) pourra s’écrire :
In [ 2 4 ] : def newf ( x ) :
...: i f 0 <= x and x < 2 :
...: return g(x)
...: e l i f x >= 2 :
...: r e t u r n newf ( x −2)
...: else :
...: p r i n t ( " v a l e u r de l ’ a n t e c e d e n t e r r o n e " )
...:
I n [ 2 6 ] : newf ( 2 )
Out [ 2 6 ] : 0
I n [ 2 7 ] : newf ( 3 )
Out [ 2 7 ] : 1
I n [ 2 8 ] : newf ( 1 0 0 )
Out [ 2 8 ] : 0
I n [ 2 9 ] : newf ( −0.1)
v a l e u r de l ’ a n t e c e d e n t e r r o n e
32 CHAPITRE 2
Chapitre 3
Search for values. Counting
33
Objectifs
Les incontournables :
I savoir créer un compteur simple à partir d’une boucle for ou while ;
I savoir créer une variable accumulatrice à partir d’une boucle for ou while ;
I savoir créer une fonction booléenne qui indique la présence d’une valeur à partir d’une
boucle for ou while ;
I savoir rechercher la première occurrence à partir d’une boucle for ou while ;
I savoir rechercher la dernière occurrence à partir d’une boucle for ou while ;
I savoir créer une fonction qui renvoie le maximum d’une liste ordonnée ;
I savoir créer une fonction qui renvoie le miniimum d’une liste ordonnée ;
I savoir reconnaître un dictionnaire.
Et plus si affinités :
I savoir récupérer les clés ou les valeurs dans un dictionnaire et une valeur connaissant la
clé.
I savoir créer une fonction qui renvoie le nombre de fois où apparaissent tous les éléments
d’une liste d’entiers ;
I savoir créer une fonction qui renvoie le nombre de fois où apparaissent tous les éléments
d’une chaîne de caractères ;
I savoir créer une fonction qui renvoie True si un motif appartient à un texte et False
sinon.
34 CHAPITRE 3
Cours
Compteurs
Lorsqu’on utilise une boucle for, on connaît en général à l’avance le nombre de passage dans
la boucle. À moins que l’on ajoute un test (voir l’exemple 2). Mais par contre lorsqu’on utilise
une boucle while, on ne connaît pas ce nombre de passages mais on peut souhaiter compter le
nombre de passages dans la boucle. On utilise une variable (en général locale) que l’on peut appeler
compteur ou cpt par exemple. Cette variable est toujours initialisée à 0 et incrémentée à chaque
passage de la boucle. C’est ce que l’on va illustrer par l’exemple 01.
Exemple 01.
On construit un programme taille qui désire compter le nombre de divisions euclidiennes succes-
sives de n par 2, jusqu’à arriver à un quotient nul.
In [ 1 ] : def t a i l l e (n) :
...: c p t =0
...: while n > 0:
...: cpt = cpt + 1
...: n = n // 2
...: return cpt
In [ 2 ] : t a i l l e (2) , t a i l l e (5) , t a i l l e (20) , t a i l l e (180000)
Out [ 2 ] : ( 2 , 3 , 5 , 1 8 )
In [ 3 ] : def d i v i s e u r s (n) :
...: cpt = 0
...: f o r d i n r a n g e ( 1 , n+1) :
...: i f n % d == 0 :
...: cpt = cpt + 1
...: return cpt
In [ 4 ] : d i v i s e u r s (1) , d i v i s e u r s (8) , d i v i s e u r s (1458)
Out [ 4 ] : ( 1 , 4 , 1 4 )
Exercice 01. Écrire une fonction nommée nombre_de_e d’argument une chaîne de caractères ap-
pelée chaine et qui renvoie le nombre de ’e’ contenus dans chaine. On nommera cpt la variable
Exemple 03. Dans la procédure que l’on construit, on peut avoir à retourner le résultat pour
lequel la procédure est créée mais aussi le nombre de passages dans la boucle et donc par exemple
il est alors pratique de retourner un couple résultat-compteur. Reprenons diviseurs en ce sens et
modifions le.
Accumulateurs
C’est une extension de la notion de compteur. Un accumulateur peut être incrémenté d’une valeur
différente de 1 ou même être décrémenté. Le mieux ce sont encore des exemples.
Exemple 01.
In [ 1 ] : def somme_pairs ( L ) :
...: acc = 0
...: for x in L:
...: i f x % 2 == 0 :
...: acc = acc + x
...: r e t u r n acc
36 CHAPITRE 3
Que renvoie mystery01([-2,0,4,1,5,4,8,0,1,-1]) ?
Dans la fonction mystery01, si n est la longueur de la liste L, nous disons que le coût est linéaire
en n car nous opérons n additions et n affectations dans la boucle for. Et l’obtention de la lon-
gueur par len(L) a un coût constant (une seule opération).
Recherche de valeurs
1. Recherche de la présence d’une valeur avec while ou for
Commençons avec des exemples utilisant une boucle while. L’idée est de rechercher si val est un
élément de tab qui est un type structuré. Les fonctions proposées seront booléennes c’est-à-dire
qu’elles renverront True si val est dans tab et False sinon.
Exemple 01. La fonction ici s’appelle recherche_V1.
Nommons presence la variable booléenne qui est renvoyée à la fin de la procédure. . Elle vaut
False par défaut.
Comme on utilise while, on incrémente avec i initialisé à i=0. Et on met i = i+1 dans la boucle
en dernière instruction.
Ensuite, que va t-on mettre dans la condition de la boucle ? On doit mettre pour commencer
i < len(tab) car quand i devient au moins aussi grand que len(tab), la quantité tab[i] n’a
plus de sens. Il faut aussi signaler à Python que dès qu’il découvre que tab[i] vaut val, il doit
sortir de la boucle. On se sert de la variable presence. En effet, tant que val n’est pas trouvé, la
valeur de presence reste False et not presence est alors True. Or si l’on rajoute la condition
True dans une boucle while, elle fonctionne et si l’on rajoute par contre la condition False, elle
ne fonctionne pas. Regardons ce code :
In [ 3 ] : i = 0
In [ 4 ] : w h i l e i < 5 and True :
...: i=i +1
In [ 5 ] : i
Out [ 5 ] : 5
In [ 8 ] : i = 0
In [ 9 ] : w h i l e i <5 and F a l s e :
...: i=i +1
In [ 1 0 ] : i
Out [ 1 0 ] : 0
I n [ 1 2 ] : r e c h e r c h e _ V 1 ( " j e ne s a i s p a s l e f a i r e " , ’ f ’ )
Out [ 1 2 ] : True
I n [ 1 3 ] : r e c h e r c h e _ V 1 ( " j e ne s a i s p a s l e f a i r e " , ’ f f ’ )
Out [ 1 3 ] : F a l s e
Exemple 02. C’est en fait une forme remaniée de recherche_V1 que l’on va appeler recherche_V2.
On n’introduit plus le booléen presence et dans la boucle while, on remplace not presence par
tab[i] != val et donc on boucle tant que i<len(tab) et tab[i] != val.
In [ 1 1 ] : def r e c h e r c h e _ V 2 ( tab , v a l ) :
...: i = 0
...: w h i l e i < l e n ( t a b ) and t a b [ i ] != v a l :
...: i = i +1
...: r e t u r n t a b [ i ] == v a l
In [ 1 2 ] : recherche_V2 ( [ 1 , 2 , 0 , 4 , 4 , 8 , 4 , 5 ] , 2 )
Out [ 1 2 ] : True
In [ 1 3 ] : recherche_V2 ( [ 1 , 2 , 0 , 4 , 4 , 8 , 4 , 5 ] , 5 )
Out [ 1 3 ] : True
Tout semble bien aller ! Faisons un cas où val n’est pas dans tab.
38 CHAPITRE 3
In [ 1 4 ] : recherche_V2 ( [ 1 , 2 , 0 , 4 , 4 , 8 , 4 , 5 ] , 7 )
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
F i l e "<i p y t h o n −i n p u t −14−54 f 3 d a 8 e 4 1 2 0 >" , l i n e 1 , i n <module>
recherche_V2 ( [ 1 , 2 , 0 , 4 , 4 , 8 , 4 , 5 ] , 7 )
Zut, on a un problème. En fait l’index i est hors du range. Cela vient du fait que comme Py-
thon ne trouve pas val pour le dernier i, il incrémente i=i+1 et tab[i] n’existe pas. Donc il faut
remplacer la condition i<len(tab) par i<len(tab) -1 et là ça va fonctionner comme on va le voir.
I n [ 1 5 ] : d e f r e c h e r c h e _ V 2 ( tab , v a l ) :
...: i = 0
...: w h i l e i < l e n ( t a b )−1 and t a b [ i ] != v a l :
...: i = i +1
...: r e t u r n t a b [ i ] == v a l
In [ 1 6 ] : recherche_V2 ( [ 1 , 2 , 0 , 4 , 4 , 8 , 4 , 5 ] , 7 )
Out [ 1 6 ] : F a l s e
Question : pourquoi i <len(tab) a fonctionné dans recherche_V1 ? Car pour la dernière valeur
de i affactée, on ne demande pas d’utiliser tab[i] qui n’existera pas si val n’a pas été trouvé.
Exemple 03. Maintenant donnons une version avec la boucle for qui est entre-nous (légérement)
plus simple.
I n [ 1 9 ] : d e f r e c h e r c h e _ V 3 ( tab , v a l ) :
...: f o r i i n range ( l e n ( tab ) ) :
...: i f t a b [ i ] == v a l :
...: r e t u r n True
...: return False
L’idée est de retourner True la première fois que tab[i] == val. Si cela n’arrive pas, on re-
tourne False. Ne pas oublier que c’est le premier return qui compte et donc si par exemple
tab[0] == val est vrai, on retourne True même si Python continue la boucle avec des valeurs de
tab[i] différentes de val.
In [ 2 1 ] : recherche_V3 ( [ 1 , 2 , 0 , 4 , 4 , 8 , 4 , 5 ] , 7 )
Out [ 2 1 ] : False
In [ 2 2 ] : recherche_V3 ( [ 1 , 2 , 0 , 4 , 4 , 8 , 4 , 5 ] , 1 )
Out [ 2 2 ] : True
I n [ 2 2 ] : d e f f i r s t _ o c c u r r e n c e ( tab , v a l ) :
...: f o r i n d i c e i n range ( l e n ( tab ) ) :
...: i f t a b [ i n d i c e ] == v a l :
...: return indice
...: r e t u r n ( val , "n ’ e s t pas p r e s e n t . Achetez des l u n e t t e s ! " )
On fait fonctionner.
In [ 2 7 ] : d e f l a s t _ o c c u r r e n c e ( tab , v a l ) :
...: i n d i c e = 0.1
...: f o r i i n range ( l e n ( tab ) ) :
...: i f t a b [ i ] == v a l :
...: indice = i
...: i f i n d i c e != 0 . 1 : r e t u r n i n d i c e
...: r e t u r n ( val , "n ’ e s t pas p r e s e n t . Achetez des l u n e t t e s ! " )
On fait fonctionner.
40 CHAPITRE 3
4. Recherche d’un extremum
On va rechercher le maximum, le minimum sans utiliser les fonctions prédéfinies min et max. At-
tention, il faut avoir une liste d’éléments tous comparables. Donc ici on ne peut pas prendre des
caractères. Il faut des entiers ou des flottants.
Cas du maximum
On va appeler maximum la procédure et surtout pas max qui est prédéfinie. Le but est de retourner le
plus grand élément d’une liste L. On crée dans la procédure une variable locale maxi qui vaut L[0]
en initialisation. Puis on boucle en partant de i = 1 et on compare L[i] et maxi. Si L[i] > maxi
alors L[i] devient le nouveau maxi.
On peut remarquer que si deux valeurs de L sont égales, on ne tient compte que de la première ce
qui peut allèger le nombre d’opérations.
I n [ 3 1 ] : d e f maximum ( L ) :
...: maxi = L [ 0 ]
...: f o r i in range (1 , len (L) ) :
...: i f L [ i ] > maxi :
...: maxi = L [ i ]
...: r e t u r n maxi
...:
I n [ 3 2 ] : maximum ( [ − 2 , 0 . 1 , 0 . 0 1 , 4 5 , 1 0 ∗ ∗ 2 , 1 0 1 , − 5 ] )
Out [ 3 2 ] : 101
Cas du minimum
Exercice 02. C’est à vous ! Créer une procédure minimum qui renvoie le minimum d’une liste L en
s’inspirant de la procédure maximum.
Dictionnaire
Un dictionnaire est un objet de type dict est une séquence d’association d’une clé et d’une valeur.
Une clé peut être n’importe quel objet, un tuple mais pas une liste ou un autre dictionnaire. On
construit un dictionnaire en associant des successions de couples, chaque couple est constitué d’un
premier élément, appelé clé, keys en Python et un second appelé valeur, values en Python. Les
clés ne sont pas mutables, les valeurs associées quelconques (qui peuvent être à leur tour des dic-
tionnaires). Ces clés ne sont pas ordonnées. Pour créer un dictionnaire, on écrit entre des accolades
les couples clé-valeur, la clé et la valeur sont séparés par : et les couples par une virgule. Tout ceci
sera approfondi d’ailleurs en TSI2. Donnons des exemples.
I n [ 1 ] : d ={0:1 , ’ l o g i n ’ : ’ l p p r ’ , ’ p a s s ’ : ’ l p p r ’ , ’ p r o c ’ : 6 4 }
In [ 2 ] : d [ ’ login ’ ]
Out [ 2 ] : ’ lppr ’
In [ 3 ] : f o r c l e in d . keys () : p r i n t ( c l e )
Out [ 3 ] : 0 l o g i n pass proc
Ainsi la commande for cle in d.keys(): donne la liste des clés du dictionnaire d et la commande
for val in d.values(): donne la liste des valeurs du dictionnaire d et si l’on veut tous les couples
on tape for cle,val in d.items():
Donnons maintenant un exemple plus élaboré.
On en a profité pour donner quelques commandes utiles pour les dictionnaires. Retenir que si d est
un dictionnaire alors d["nom␣de␣la␣cle"] renvoie la valeur de la clé nommée.
Pour finir, donnons des exemples de gros dictionnaires incorporé dans Python.
Donnons l’exemple de __builtins__. Les clès de ce dictionnaire sont les fonctions classiques (hors
modules). Attention à la syntaxe. La barre __ est constituée de deux fois le tiret sous le 8.
I n [ 5 ] : _ _ b u i l t i n s _ _ . __dict__ [ ’ min ’ ] ( 5 , 2 , 3 )
Out [ 5 ] : 2
Donnons tout ce qu’il y a dans la bête ou plutôt une partie car c’est trop long.
42 CHAPITRE 3
I n [ 4 ] : _ _ b u i l t i n s _ _ . __dict__
Out [ 4 ] :
{ ’__name__ ’ : ’ b u i l t i n s ’ ,
’ __doc__ ’ : " B u i l t −i n f u n c t i o n s , e x c e p t i o n s , and o t h e r o b j e c t s . \ n
\ n N o t e w o r t h y : None i s t h e ‘ n i l ’ o b j e c t ; E l l i p s i s r e p r e s e n t s
‘ . . . ’ in s l i c e s . " ,
’ a b s ’ : <f u n c t i o n a b s ( x , / ) >,
’ a l l ’ : <f u n c t i o n a l l ( i t e r a b l e , / ) >,
’ any ’ : <f u n c t i o n any ( i t e r a b l e , / ) >,
...
’ d i r ’ : <f u n c t i o n d i r >,
’ divmod ’ : <f u n c t i o n divmod ( x , y , / ) >,
’ e v a l ’ : <f u n c t i o n e v a l ( s o u r c e , g l o b a l s=None , l o c a l s=None , / ) >,
...
’ h a s h ’ : <f u n c t i o n h a s h ( o b j , / ) >,
’ hex ’ : <f u n c t i o n hex ( number , / ) >,
’ i d ’ : <f u n c t i o n i d ( o b j , / ) >,
’ i n p u t ’ : <bound method K e r n e l . r a w _ i n p u t o f <s p y d e r _ k e r n e l s .
c o n s o l e . k e r n e l . S p y d e r K e r n e l o b j e c t a t 0 x000001A3BFF15700 >>,
...
’ max ’ : <f u n c t i o n max>,
’ min ’ : <f u n c t i o n min >,
’ n e x t ’ : <f u n c t i o n n e x t >,
...
’ False ’ : False ,
’ True ’ : True ,
’ bool ’ : bool ,
...
’ dict ’ : dict ,
’ e n u m e r a t e ’ : enumerate ,
’ filter ’: filter ,
’ float ’ : float ,
...
’ S y n t a x W a r n i n g ’ : SyntaxWarning ,
’ RuntimeWarning ’ : RuntimeWarning ,
...
’ c e l l _ c o u n t ’ : <f u n c t i o n s p y d e r c u s t o m i z e . c e l l _ c o u n t ( f i l e n a m e=None
) >,
’__IPYTHON__ ’ : True ,
’ d i s p l a y ’ : <f u n c t i o n I P y t h o n . c o r e . d i s p l a y . d i s p l a y ( ∗ o b j s , i n c l u d e
=None , e x c l u d e=None , metadata=None , t r a n s i e n t=None ,
d i s p l a y _ i d=None , ∗∗ k w a r g s ) >,
’ g e t _ i p y t h o n ’ : <bound method I n t e r a c t i v e S h e l l . g e t _ i p y t h o n o f <
i p y k e r n e l . zmqshell . ZMQInteractiveShell object at 0
x000001A3BFF15A00>>}
Autre exemple de gros dictionnaire : globals() à taper en TP d’informatique juste pour le fun.
In [ 1 ] : def compte_version01 ( e n t i e r s ) :
...: m = max ( e n t i e r s )
...: L = [ 0 f o r i i n r a n g e (m+1) ]
...: for n in entiers :
...: L[n] = L[n] + 1
...: return L
Exercice 03. Faire fonctionner à la main compte_version01. On suppose que entiers est la
liste [3,8,1,5,7,4,5]. Faire fonctionner compte_version01 et retourner les différents L à chaque
étape de la boucle for.
Maintenant, faisons bosser Python.
# on p e u t p r e n d r e d e s e n t i e r s n e g a t i f s p o u r v o i r !
In [ 5 ] : compte_version01 ([0 , −3 , −3 , −3 ,9 ,9 ,4 ,11 ,1 ,1 ,1 ,7 ,4])
Out [ 5 ] : [ 1 , 3 , 0 , 0 , 2 , 0 , 0 , 1 , 0 , 5 , 0 , 1 ]
En effet, dans entiers, si l’on met des entiers négatifs, Python les transforme en entiers positifs
car L[-3] est aussi L[12-3] soit L[9]. Et donc −3 et 9 se cumulent dans la liste finale pour les
occurrences.
Pour finir, tentons un cas où la liste n’a pas d’entiers.
44 CHAPITRE 3
In [ 9 ] : compte_version01 ( [ ’ t ’ , ’ r ’ , ’ o ’ , ’p ’ , ’ c ’ , ’ o ’ , ’ o ’ , ’ l ’ , ’ ! ’ ] )
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
F i l e "<i p y t h o n −i n p u t −9−49 f a 9 7 3 8 3 2 f f >" , l i n e 1 , i n <module>
compte_version01 ( [ ’ t ’ , ’ r ’ , ’ o ’ , ’p ’ , ’ c ’ , ’ o ’ , ’ o ’ , ’ l ’ , ’ ! ’ ] )
F i l e "<i p y t h o n −i n p u t −1−f 6 4 f a 0 b 9 0 6 3 0 >" , l i n e 3 , i n
compte_version01
c p t s = [ 0 f o r i i n r a n g e (m+1) ]
T y p e E r r o r : can o n l y c o n c a t e n a t e s t r ( n o t " i n t " ) t o s t r
In [ 6 ] : def compte_version02 ( o b j e t ) :
...: d ={}
...: for elt in objet :
...: i f elt in d :
...: d[ elt ] = d[ elt ] + 1
...: else :
...: d[ elt ] = 1
...: return d
# Commencons p a r une l i s t e d ’ e n t i e r s p r i s e p o u r c o m p t e _ v e r s i o n 0 1
In [ 7 ] : compte_version02 ([0 ,3 ,4 ,11 ,1 ,1 ,1 ,7 ,4])
Out [ 7 ] : { 0 : 1 , 3 : 1 , 4 : 2 , 1 1 : 1 , 1 : 3 , 7 : 1}
# R e p r e n o n s l a l i s t e a v e c un e n t i e r n e g a t i f .
In [ 8 ] : compte_version02 ([0 , −3 , −3 , −3 ,9 ,9 ,4 ,11 ,1 ,1 ,1 ,7 ,4])
Out [ 8 ] : { 0 : 1 , −3: 3 , 9 : 2 , 4 : 2 , 1 1 : 1 , 1 : 3 , 7 : 1}
Et si l’on essaye directement avec une chaîne de caractères, donc un autre type que list.
Recherche textuelle
Il s’agit maintenant de rechercher la présence ou l’absence d’un motif ou d’un mot dans un texte.
Le texte ou le motif est représenté en Python par des chaînes de caractères (type str). Ils sont donc
composés de caractères qui peuvent être des lettres, des signes de ponctuations, des symboles ou
de l’espace. Si le motif est constitué d’un seul caractère, on est ramené au paragraphe de recherche
de valeurs de ce chapitre et aux fonctions recherche_V1 ou recherche_V2. Dans ce cas, on sait
que le coût de la recherche est linéaire de valeur la longueur de la chaîne.
Nous allons donc construire une procédure nommée recherche_motif qui va être booléenne.
On renvoie True si motif est bien dans texte et False sinon. Donnons la procédure :
Exercice 04. Faire tourner à la main recherche_motif pour texte = "premier essai" et motif
= "er es" puis motif = "e es"
46 CHAPITRE 3
In [ 8 ] : recherche_motif ( " premier e s s a i " , " er es " )
Out [ 8 ] : True
# Un a u t r e t e x t e p o u r l e f u n !
I n [ 1 0 ] : r e c h e r c h e _ m o t i f ( " on r e c h e r c h e s u p e r b i e n ! " , " s u p e r " )
Out [ 1 0 ] : True
I n [ 1 1 ] : r e c h e r c h e _ m o t i f ( " on r e c h e r c h e s u p e r b i e n ! " , " ? ? ? ? " )
Out [ 1 1 ] : F a l s e
Faisons une variante où on renvoie soit le premier indice de texte où motif apparaît, soit on renvoie
que ce motif n’est pas dans le texte.
Pour finir, parlons du coût. Notons n la longueur du texte et m celle du motif. La boucle for est
parcourue (n − m + 1) fois. Dans le pire des cas, la boucle interne while est parcourue au plus m
fois pour tester chaque caractère du motif. Le nombre total de comparaisons entre caractères est
donc majoré par m(n − m + 1).
49
Objectifs
Les incontournables :
I savoir faire tourner le tri-bulles sur une liste donnée.
Et plus si affinités :
I savoir utiliser une variable booléenne qui permette de sortir de la boucle d’un tri-bulles
s’il n’y a pas eu de permutations à un parcours donné.
50 CHAPITRE 4
Cours
Introduction
Un problème classique est le triage de données. Il faut que les données soient comparables les unes
aux autres. Le cas le plus simple est une liste d’entiers par exemple et la liste [1,5,2,4,3,1] peut se
trier selon l’ordre croissant et donner [1,1,2,3,4,5] ou selon l’ordre décroissant [5,4,3,2,1,1].
On peut remarquer dans cet exemple la présence de la même valeur deux fois. Certains tris vont
permuter les deux 1 dans leurs exécutions et certains tris ne vont pas les permuter. On parle de
tris stables ou de tris instables. Parmi les tris classiques stables, on peut citer le tri par insertion, le
tri bulle (celui qui va nous intéresser dans ce chapitre), le tri Shaker, le tri Gnome et le tri fusion.
Parmi les tris classiques instables, le tri par sélection, le tri à peigne, le tri rapide, le tri Shell et le
tri maximier. Les longs week end pluvieux, vous pourrez vous pencher sur ces différents tris. Lequel
choisir ? Ce qui est le plus important pour un tri c’est sa complexité qui est en rapport avec son
temps d’exécution. Sachez que le meilleur de tous est le tri fusion. Nous reparlerons de la plupart
de ces tris dans des chapitres ultérieurs. Maintenant passons au tri à bulles qui est celui qu’on va
développer dans ce chapitre.
Tri à bulle
L’algorithme du tri à bulle consiste à parcourir une liste plusieurs fois jusqu’à ce qu’elle soit triée
du plus petit au plus grand, en comparant à chaque parcours les éléments consécutifs et en
procédant à leur échange s’ils sont mal triés.
Les étapes sont :
I on parcourt la liste et si deux éléments consécutifs sont rangés dans le désordre, on les
échange ;
I si à la fin du parcours au moins un échange a eu lieu, on recommence l’opération ;
I sinon, la liste est triée, on arrête.
Notons que si les deux éléments sont identiques, aucune permutation n’est effectuée.
Les éléments les plus grands remontent ainsi dans la liste comme des bulles d’airs qui remontent à
la surface d’un liquide. D’où le nom de tri-bulle.
Le mieux maintenant c’est un exemple. Soit la liste L = [12,17,14,11,8]. On écrira en gras les
éléments permutés.
Parcours 1 : [12,14,17,11,8] puis [12,14,11,17„8] puis [12,14,11,8,17]
Parcours 2 : [12,11,14, 8,17] puis [12,11, 8,14,17]
Parcours 3 : [11,12, 8,14,17] puis [11, 8,12, 14,17].
Parcours 4 : [8,11, 12,14,17].
Parcours 5 : [8,11,12,14,17].
Lors du parcours 5, aucune permutation n’est effectuée. La liste est donc triée.
Remarquons qu’au bout du parcours 1, le plus grand élément 17 est en fin de liste. Au bout du
parcours 2, les deux plus grands éléments 14, 17 sont en fin de liste. Au bout du parcours 3, les
trois plus grands éléments 12, 14, 17 sont en fin de liste. Et ensuite en fin de parcours 4, les quatre
On effectue les n − 1 comparaisons de 1 avec 2 puis 2 avec 3 etc. et aucune permutation n’est
nécessaire. C’est le cas le plus favorable.
Cas le plus défavorable pour un tri-bulle. Supposons que notre liste de départ soit
La valeur n va se déplacer après chaque itération jusqu’à la fin de la liste. Donc le nombre de
comparaisons puis de permutations pour la valeur n est n − 1.
De manière similaire, pour amener n − 1 à la bonne place, il faut n − 2 permutations (le dernier
élément est n et donc n − 1 ne permutera pas avec lui.
Puis pour amener n − 2 à la bonne place, il faut n − 3 permutations (les deux derniers éléments
sont n − 1 et n et ne sont pas touchés).
Ainsi de suite... jusqu’à [2, 1, 3, 4, ..., n − 1, n]. L’élément 2 est juste comparé et permuté avec 1. Et
ensuite on parcourt toute la liste une fois et on constate que plus rien ne permute.
Combien d’opérations avons nous fait ?
Pour les comparaisons et les permutations,
n(n − 1)
2 ((n − 1) + (n − 2) + ... + 1) = 2 × = n(n − 1).
2
In [ 1 ] : a = 5
In [ 2 ] : b = 7
In [ 3 ] : a,b = b,a
In [ 4 ] : a
Out [ 4 ] : 7
In [ 5 ] : b
Out [ 5 ] : 5
52 CHAPITRE 4
Le code a,b = b,a permute a et b
In [ 6 ] : def t r i _ b u l l e s (L) :
...: n = len (L)
...: f o r d e r n i e r i n r a n g e ( n −1 ,0 , −1) :
...: f o r i in range ( d e r n i e r ) :
...: i f L [ i ] > L [ i +1]:
...: L [ i ] , L [ i +1] = L [ i +1] , L [ i ]
...: return L
Revenons à l’algorithme principal. Ce tri ne permute L[i] et L[i+1] que si L[i] > L[i+1] et
donc deux éléments de même valeur peuvent par des permutations successives se rapprocher et se
retrouver côte à côte mais ne seront pas permutés. Le tri est donc bien stable. Si l’on remplace dans
tri_bulles par if L[i] >= L[i+1], on obtient le même résultat mais il peut y avoir davantage
de permutations et le tri ne serait plus stable.
54 CHAPITRE 4
Chapitre 5
Modules and library
55
Objectifs
Les incontournables :
I Connaître le nom des modules ou bibliothéques les plus utiles qui sont : numpy, numpy.linalg,
matplotlib.pyplot et random
I Savoir créer un alias pour un module ou une bibliothéque
(par exemple import matplotlib.pyplot as plt).
I Savoir utiliser la commande dir.
I Connaître la différence entre importer tout un module (par exemple from math import *)
et certaines fonctions d’un module (par exemple from math import sin, cos)
I Comment nommer une fonction d’un module importé par son nom (par exemple rd.randint
appelle la fonction randint du module random ramené à son alias rd).
Et plus si affinités :
I Connaître le module time et sa fonction perf_counter qui affiche le temps d’exécution.
I Connaître le module sympy qui permet le calcul formel.
I Connaître la bibliothéque scipy et son module scipy.stats qui fournit les lois clas-
siques de probabilité.
56 CHAPITRE 5
Cours
Introduction
Il est conseillé de décomposer un programme en particulier à l’aide de fonctions. Lorsque des
fonctions traitent toutes d’un même sujet, on peut les regrouper dans un fichier, un module. Diffé-
rents modules peuvent être regroupés dans une bibliothèque. Un programme en Python commence
souvent par des lignes contenant le mot import afin d’utiliser des modules et des bibliothèques
(library en langage Python).
pi = 3.14159
def disque ( rayon ) :
" " " " r a y o n de t y p e f l o a t e s t l e r a y o n d ’ un d i s q u e " " "
" " " e t r e n v o i e l ’ a i r e du d i s q u e " " "
r e t u r n pi ∗ rayon ∗ rayon
def rectangle ( largeur , longueur ) :
" " " l a r g e u r e t l o n g u e u r s o n t de t y p e f l o a t " " "
" " " r e n v o i e a i r e r e c t a n g l e de c o t e s l a r g e u r e t l o n g u e u r " " "
return largeur ∗ longueur
d e f t r i a n g l e ( base , h a u t e u r ) :
" " " b a s e e t h a u t e u r de t y p e f l o a t s o n t l a b a s e e t l a
h a u t e u r d ’ un t r i a n g l e " " "
" " " r e n v o i e l ’ a i r e du t r i a n g l e " " "
r e t u r n b a s e ∗ h a u t e u r /2
On nomme ce fichier aires.py. On a ainsi créer un module appelé aires. Puis on sort de ce fichier
et on se met dans un nouveau fichier vierge de l’éditeur. Puis toujours dans l’éditeur, on tape :
import a i r e s
# On a p p e l l e a i n s i l e module a i r e s
p r i n t ( a i r e s . disque (10) )
p r i n t ( a i r e s . rectangle (30 ,4) )
I n [ 1 ] : r u n f i l e ( ’C : / U s e r s / damin / . s p y d e r −py3 / u n t i t l e d 0 . py ’ , w d i r= ’
C : / U s e r s / damin / . s p y d e r −py3 ’ )
Reloaded modules : a i r e s
314.159
120
Le point entre aires et disques signifie que l’on se refère au nom disque qui est défini dans le
module aires.
On accède à la spécification d’une fonction avec la fonction help.
In [ 2 ] : help ( a i r e s . disque )
Help on f u n c t i o n d i s q u e i n module a i r e s :
disque ( rayon )
" r a y o n de t y p e f l o a t e s t l e r a y o n d ’ un d i s q u e
In [ 3 ] : di r ( a i r e s )
Out [ 3 ] :
[ ’ __builtins__ ’ ,
’ __cached__ ’ ,
’ __doc__ ’ ,
’ __file__ ’ ,
’ __loader__ ’ ,
’__name__ ’ ,
’ __package__ ’ ,
’ __spec__ ’ ,
’ aires ’ ,
’ disque ’ ,
’ pi ’ ,
’ rectangle ’ ,
’ triangle ’ ]
58 CHAPITRE 5
pa.fonction pour aller chercher fonction du module package.
from package import * : permet de charger toutes les fonctions de package et pour aller chercher
fonction, on ne tapera plus pa ou infopackage devant.
from package import fonction : ne charge que fonction et pas le reste du module package.
Par extension, from package import fonction1 , fonction2 , fonction3 : chargera les trois
fonctions citées de package et rien d’autre.
Parfois la fonction qui nous intéresse est dans un sous-package d’un module principal package
On tape import package.sous-package as sp ou from package.sous-package import fonction
par exemple pour l’utiliser.
Comment s’informer sur le contenu d’un module ou sur une fonction d’un module ?
Comme on a vu plus haut sur l’exemple 01, dir liste les modules ou fonctions déjà chargés à un
moment donné.
dir(package) liste les fonctions et constantes du module package.
infohelp(package) renvoie des informations sur les fonctions du module package
help(package.fonction) renvoie des informations sur fonction du module package.
Donnons maintenant les modules incontournables auxquels on en ajoute quelques uns qui sont
intéressants pour que le candidat aux concours soit plus efficace et plus rapide.
1. La bibliothèque numpy
La bibliothèque numpy permet de faire du calcul scientifique et de manipuler des tableaux. C’est
la library que l’on utilisera le plus. Son alias usuel est np.
Le module de numpy utilisé principalement est linalg, consacré à tout ce qui est calcul matriciel.
On l’importe avec : import numpy.linalg as alg et donc son alias usuel est alg
10−20 x + y = 1
Exemple 02 Utilisons numpy pour résoudre : .
x+y = 2
I n [ 1 ] : i m p o r t numpy a s np ; i m p o r t numpy . l i n a l g a s a l g
I n [ 2 ] : A = np . a r r a y ( [ [ 1 0 ∗ ∗ ( − 2 0 ) , 1 ] , [ 1 , 1 ] ] )
I n [ 3 ] : B = np . a r r a y ( [ [ 1 ] , [ 2 ] ] )
I n [ 4 ] : a l g . s o l v e (A , B)
Out [ 4 ] :
array ( [ [ 1 . ] , [ 1 . ] ] )
Notons aussi le module polynomial, utile comme son nom l’indique, pour le calcul polynomial. On
l’importe avec from numpy.polynomial import Polynomial et donc son alias usuel est Polynomial.
I n [ 9 ] : h e l p ( math . h y p o t )
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
F i l e "<i p y t h o n −i n p u t −9−f28b798b5134 >" , l i n e 1 , i n <module>
h e l p ( math . h y p o t )
NameError : name ’ math ’ i s n o t d e f i n e d
I n [ 1 0 ] : # Normal i l n ’ y a p a s l e module math . Je s u i s IDIOT !
I n [ 1 1 ] : i m p o r t math
I n [ 1 2 ] : h e l p ( math . h y p o t )
Help on b u i l t −i n f u n c t i o n h y p o t i n module math :
hypot ( . . . )
h y p o t ( ∗ c o o r d i n a t e s ) −> v a l u e
M u l t i d i m e n s i o n a l E u c l i d e a n d i s t a n c e from t h e o r i g i n t o a
point .
Roughly e q u i v a l e n t to :
s q r t ( sum ( x ∗∗2 f o r x i n c o o r d i n a t e s ) )
For a two d i m e n s i o n a l p o i n t ( x , y ) , g i v e s t h e h y p o t e n u s e
u s i n g t h e P y t h a g o r e a n t h eo re m : s q r t ( x∗x + y∗y ) .
60 CHAPITRE 5
x + my + z = 1
Exemple 04. Utilisons sympy pour résoudre (m ∈ R) : x + y + mz = 0 .
7x + (4 + m)y + (3 + 2m)z = −1
In [ 1 ] : from sympy i m p o r t ∗
In [ 2 ] : m = s y m b o l s ( ’m ’ ) ; x = s y m b o l s ( ’ x ’ ) ; y = s y m b o l s ( ’ y ’ ) ; z
= symbols ( ’ z ’ )
In [ 3 ] : s y s t = M a t r i x ( [ [ 1 , m, 1 , 1 ] , [ 1 , 1 ,m, 0 ] , [ 7 , 4 +m,3+2∗m, − 1 ] ] )
In [ 4 ] : solve_linear_system ( syst , x , y , z )
Out [ 4 ] :
{ z : (m−2) / ( 2 ∗m∗ (m−1) ) , x : −(m+2) / ( 2 ∗m) ,
y : ( 3 ∗m−2) / ( 2 ∗m∗ (m−1) ) }
−(m + 2) 3m − 2 m−2
x= ,y= ,z= .
2m 2m(m − 1) 2m(m − 1)
Z 1
Exemple 05 On veut calculer e−x dx en utilisant integrate de sympy
0
I n [ 5 ] : from sympy i m p o r t ∗
I n [ 6 ] : x = s y m b o l s ( ’ x ’ ) ; i n t e g r a t e ( exp (−x ) , ( x , 0 , 1 ) )
Out [ 6 ] :
− exp ( −1)+1
5. La bibilothèque scipy
La bibliothèque scipy permet elle aussi de faire du calcul scientifique. On utilise principalement
deux de ses modules. On les importe en utilisant leurs alias. On tape import scipy.optimize as resol
et import scipy.integrate as integr
Z 1
Exemple 05 bis On veut calculer e−x dx en utilisant quad de scipy.integrate défini par
0
son alias integr
I n [ 7 ] : i m p o r t math a s mt ; i m p o r t s c i p y . i n t e g r a t e a s i n t e g r
I n [ 8 ] : d e f f ( t ) : r e t u r n mt . exp (− t )
I n [ 9 ] : i n t e g r . quad ( f , 0 , 1 )
Out [ 9 ] :
( 0 . 6 3 2 1 2 0 5 5 8 8 2 8 5 5 7 8 , 7 . 0 1 7 9 4 7 9 8 7 5 0 3 8 5 6 e −15)
On remarque que l’on obtient deux flottants, le premier correspond à une valeur approchée de
−e−1 + 1 et le second une majoration de l’erreur commise en prenant cette valeur approchée à la
place de −e−1 + 1.
Ainsi avec sympy on a de l’intégration formelle c’est-à-dire que l’on trouve la valeur exacte (si bien
entendu c’est possible) et avec scipy, on a de l’intégration numérique.
I n [ 1 ] : from t u r t l e i m p o r t ∗
On commence par appeler le module turtle puis on commence par faire un premier côté de
longueur longcot (on prendra 200 pour valeur numérique). C’est la fonction forward(longcot).
Puis on tourne de 72 degrés vers la gauche. C’est la commande left(72). Pourquoi 72 ? Car
72 ∗ 5 = 360. On fait cela 5 fois et on obtient le pentagone voulu qui se place dans une fenêtre de
Python Turtle Graphics.
Donnons deux autres commandes classiques (pas utiles pour le pentagone). Par exemple right(30)
va déplacer le curseur de 30 degrés vers la droite, backward(150) va faire reculer le curseur de
150. Il y a plein d’autres fonctions (pour créer de la couleur, augmenter ou dimimuer l’épaisseur
du trait, pour cacher la tortue ou la montrer etc.)
7. La bibliothèque matplotlib
La bibliothèque matplotlib permet de faire du graphisme (tracé de courbes en particulier). C’est la
bibliothèque la plus importante à connaître avec numpy. On importe son module principal important
pyplot avec l’instruction : import matplotlib.pyplot as plt et l’alias est donc plt.
Exemple 07. Écrire les lignes Python qui permettent de tracer la ligne de segments brisés passant
par les points (k, f (k)), où k varie de 1 à 20. Appliquer et afficher avec f : x 7→ arctan x.
In [4] : i m p o r t m a t p l o t l i b . p y p l o t a s p l t ; i m p o r t numpy a s np
In [5] : d e f f ( x ) : r e t u r n ( np . a r c t a n ( x ) )
In [6] : X = [ k f o r k in range (1 ,21) ]
In [7] : Y = [ f ( k ) f o r k in range (1 ,21) ]
In [8] : p l t . p l o t ( X , Y , c o l o r = ’ 0 ’ ) ; p l t . show ( )
62 CHAPITRE 5
1.6
1.5
1.4
1.3
1.2
1.1
1.0
0.9
0.8
0.7
0 5 10 15 20
8. La bibliothèque random
La bibliothèque random permet en fait de générer des nombres aléatoires. On l’importe en totalité
avec : import random as rd pour utiliser ses fonctions directement accessibles.
• rd.randint(a,b) permet de choisir un entier au hasard dans [[a, b − 1]].
• rd.random( ) renvoie un réel dans [0, 1[.
Exemple 08. Création d’une variable de Bernoulli de paramètre p.
Écrire une fonction lancer(p) qui renvoie True avec une probabilité p ∈]0, 1[ et False avec une
probabilité q = 1 − p. On utilisera la fonction rd.random( ) et faire quelques essais.
In [ 1 6 ] : i m p o r t random a s r d
In [ 1 7 ] : def lancer (p) :
...: r e t u r n r d . random ( )<p
...:
In [ 1 8 ] : lancer (0.9) , lancer (0.9999) , lancer (0.0001)
Out [ 1 8 ] : ( True , True , F a l s e )
In [ 1 9 ] : lancer (0.4) , lancer (0.4) , lancer (0.4)
Out [ 1 9 ] : ( True , True , True )
In [ 2 0 ] : lancer (0.4) , lancer (0.4) , lancer (0.4)
Out [ 2 0 ] : ( False , F a l s e , True )
Il faut savoir que numpy en tant que bibliothéque possède un module random que l’on nommera donc
numpy.random qui n’est pas exactement le même module que random ici. Le module numpy.random
de numpy permet d’aller plus loin. Ainsi, la fonction randint de numpy.random possède un troisième
argument qui permet la répétition.
I n [ 2 1 ] : i m p o r t numpy . random a s r d
In [ 2 2 ] : rd . r a n d i n t (0 ,2 ,4)
Out [ 2 2 ] : a r r a y ( [ 0 , 1 , 1 , 1 ] )
Ce module numpy.random possède aussi des fonctions simulant les lois de probabilité classiques :
rd.binomial(n,p), rd.poisson(p) etc.). Ce sera à approfondir en TSI2.
In [23]: i m p o r t numpy a s np ; i m p o r t m a t p l o t l i b . p y p l o t a s p l t
In [24]: from m p l _ t o o l k i t s . mplot3d i m p o r t Axes3D
In [25]: d e f f ( x , y ) : r e t u r n x ∗∗2 −y ∗∗2
In [26]: X = np . a r a n g e ( − 2 , 2 , 0 . 0 1 5 ) ; Y = np . a r a n g e ( − 2 , 2 , 0 . 0 1 5 ) ;
In [27]: X , Y = np . m e s h g r i d (X , Y) ; ax = Axes3D ( p l t . f i g u r e ( ) )
In [28]: Z = f (X , Y) ; ax . p l o t _ s u r f a c e (X , Y , Z ) ; p l t . show ( )
−1
−2
−3
−4
2.0
1.5
1.0
0.5
−2.0
−1.5 0.0
−1.0 −0.5
−0.5
0.0 −1.0
0.5
1.0 −1.5
1.5
−2.0
2.0
64 CHAPITRE 5
In [ 1 ] : def Fibo1 ( n ) :
i f n = = 0 or n = = 1 :
return 1
else :
u , v = 0 , 1
f o r j i n r a n g e ( n−1) :
u , v = v , u+v
return v
# On f a i t f o n c t i o n n e r .
In [ 2 ] : [ Fibo1 ( i ) f o r i i n range (1 ,15) ]
Out [ 2 ] :
[1 ,2 ,3 ,5 ,8 ,13 ,21 ,34 ,55 ,89 ,144 ,233 ,377 ,610]
In [ 3 ] : def Fibo2 ( n ) :
if n < = 1 :
return 1
else :
r e t u r n ( F i b o 2 ( n−1)+F i b o 2 ( n−2) )
# On f a i t e n c o r e une f o i s f o n c t i o n n e r .
In [ 4 ] : [ Fibo2 ( i ) f o r i i n range (1 ,15) ]
Out [ 4 ]
[1 ,2 ,3 ,5 ,8 ,13 ,21 ,34 ,55 ,89 ,144 ,233 ,377 ,610]
Rien à dire, c’est pareil niveau résultat. Mais niveau temps d’exécution c’est pas pareil.
On commence à charger perf_counter avec pc pour alias. On visualise la valeur trouvée pour 20
avec print mais ce n’est pas obligatoire. Puis on tape t = pc() puis on tape le code d’execution
ici Fibo1(20) pour le premier et on tape ensuite print(pc()-t) qui va afficher le temps mis pour
l’execution.
I n [ 5 ] : from t i m e i m p o r t p e r f _ c o u n t e r a s pc
In [ 6 ] : p r i n t ( Fibo1 (20) )
I n [ 7 ] : t = pc ( ) ; F i b o 1 ( 2 0 ) ; p r i n t ( pc ( ) − t )
Out [ 7 ]
10946
0.00014680592257036197
In [ 8 ] : p r i n t ( Fibo2 (20) )
I n [ 9 ] : t = pc ( ) ; F i b o 2 ( 2 0 ) ; p r i n t ( pc ( ) − t )
Out [ 9 ] :
10946
0.0184203504243996
Fibo2(20) met 126 fois plus de temps que Fibo1(20). Essayer avec 200 à la place de 20 et ce sera
pire !
In [ 1 7 ] : import decimal
In [ 1 8 ] : D = decimal . Decimal
I n [ 1 9 ] : d e c i m a l . g e t c o n t e x t ( ) . p r e c = 40
In [ 2 0 ] : p r i n t (1/7)
0.14285714285714285
I n [ 2 1 ] : p r i n t (D( 1 ) /D( 7 ) )
0.1428571428571428571428571428571428571429
I n [ 2 6 ] : i m p o r t math a s mt
I n [ 2 7 ] : p r i n t ( mt . p i )
3.141592653589793
I n [ 2 8 ] : p r i n t ( mt . e )
2.718281828459045
I n [ 2 9 ] : p r i n t (D( mt . p i ) )
3.141592653589793115997963468544185161590576171875
I n [ 3 0 ] : p r i n t (D( mt . e ) )
2.718281828459045090795598298427648842334747314453125
Et maintenant, sur Internet, on va chercher les décimales de π jusqu’à 50 décimales par exemple.
Et on voit qu’après la 15ème décimale, print(D(mt.pi)) renvoie un résultat faux. Il faut savoir
que le module math ne connaît les constantes usuelles dont π et e qu’avec 15 décimales. Et decimal
retourne donc un résultat faux si l’on veut mieux.
66 CHAPITRE 5
Chapitre 6
Analysis of an algorithm
67
Objectifs
Les incontournables :
I savoir reconnaître et utiliser un type d’instruction ;
I aborder l’effet de bord ;
I percevoir l’utilité de commentaires pour mieux comprendre un bloc d’instructions ou
un choix de programmation ;
I savoir décrypter et gérer un message d’erreur ;
I être capable de repérer des cas simples à tester ;
I distinguer et traduire les cas limites dans un jeu de tests ;
I connaître quelques ordres de grandeurs de complexité d’algorithmes classiques ;
I distinguer et étudier les notions de complexité en temps et de complexité en espace.
Et plus si affinités :
68 CHAPITRE 6
Cours
Introduction
Après avoir écrit des programmes et réfléchi au rôle de code, il est important d’étudier le contenu
avec précision. On doit aussi analyser ce contenu et vérifier que le résultat obtenu lors de l’exécution
est celui attendu. Il est primordial que le programme fonctionne correctement. Sinon, on doit le
déboguer. Par ailleurs, il est intéressant de se pencher sur la complexité d’un algorithme ce qui
permet de les classer niveau performance.
ANALYSIS OF AN ALGORITHM 69
In [ 1 ] : x = 1
In [ 2 ] : assert x = 1
F i l e "<i p y t h o n −i n p u t −4−d 9 3 c 3 e 0 5 1 7 e c >" , l i n e 1
a s s e r t x=1
^
SyntaxError : i n v a l i d syntax
I n [ 3 ] : a s s e r t x == 1
Explication : écrire assert x=1 provoque une erreur de syntaxe même si l’on a tapé avant x=1.
Par contre assert x==1 est une bonne syntaxe, en fait il renvoie alors True sans l’afficher.
Exemple 02 Manipulation d’une expression suivant if.
In [ 1 0 ] : x =3
In [ 1 1 ] : i f x%2 == 1 :
...: x=x+1
In [ 1 2 ] : x
Out [ 1 2 ] : 4
In [ 1 3 ] : x=5
In [ 1 4 ] : i f x%2 :
...: x=x+1
In [ 1 5 ] : x
Out [ 1 5 ] : 6
Explication : On remarque que l’instruction x%2 == 1 et l’instruction x%2 après if sont similaires.
En effet, le reste de la division euclidienne par 2 donne 0 ou 1. Tout nombre nul est interprété
comme False et la boucle if ne fonctionnera que si x%2 vaut 1 et alors considérée comme vraie.
Il faut savoir que les mots if, elif, while, assert doivent être suivis d’une expression. Cette
expression n’a pas forcément une valeur booléenne mais quelle que soit sa valeur, elle est interprétée
comme telle. Ainsi par exemple :
AssertionError
70 CHAPITRE 6
In [ 1 8 ] : type ( p r i n t ( " ! ! ! " ) )
!!!
Out [ 1 8 ] : NoneType
In [ 2 ] : def ajoute01 ( l i s t e , x ) :
...: l i s t e . append ( x )
In [ 3 ] : def ajoute02 ( l i s t e , x ) :
...: liste = liste + [x]
...: return l i s t e
In [ 4 ] : l i s t e = [1 ,2 ,3 ,4]
In [ 5 ] : ajoute01 ( l i s t e ,5)
In [ 6 ] : l i s t e
Out [ 6 ] : [ 1 , 2 , 3 , 4 , 5 ]
In [ 7 ] : l i s t e = [1 ,2 ,3 ,4]
In [ 8 ] : ajoute02 ( l i s t e ,5)
Out [ 8 ] : [ 1 , 2 , 3 , 4 , 5 ]
In [ 9 ] : l i s t e
Out [ 9 ] : [ 1 , 2 , 3 , 4 ]
On remarque qu’après l’action de ajoute01, liste a été modifié (ici 5 a été ajouté en fin de liste).
C’est append qui modifie la liste initiale. Il y a donc un effet de bord pour ajoute01.
Par contre l’action de ajoute02 ne modifie pas liste quand on l’appelle. En fait, dans ajoute02,
on crée une variable locale liste qui n’est pas liste hors procédure. Et comme toute variable
locale, elle est oubliée après l’exécution de la procédure.
Exemple 04. Donnons un exemple un peu plus subtil. Nous allons créer deux fonctions qui
multiplie x aux éléments d’une liste liste.
ANALYSIS OF AN ALGORITHM 71
In [ 1 0 ] : def multiplie01 ( liste , x) :
...: res = l i s t e
...: f o r i in range ( len ( r e s ) ) :
...: res [ i ] = x ∗ res [ i ]
...: return res
In [ 1 1 ] : def multiplie02 ( l i s t e , x ) :
...: res = l i s t e
...: return [ x∗ r e s [ i ] f o r i in range ( len ( r e s ) ) ]
Dans multiplie01, liste qui n’est jamais une variable locale est récupérée par la variable locale
res dont le contenu est modifié par la procédure. Et donc liste se retrouve modifiée.
Il y a effet de bord.
Par contre dans multiplie02, bien que res récupère aussi liste, cette variable res n’est pas
modifiée car on retourne une nouvelle liste créée à partir de res.
Illustrons-le avec liste, où on a affecté [1,2,3,4] au départ.
On multiplie par 5 par les deux procèdures.
In [ 1 2 ] : multiplie01 ( l i s t e ,5)
Out [ 1 2 ] : [ 5 , 1 0 , 1 5 , 2 0 ]
In [ 1 3 ] : l i s t e
Out [ 1 3 ] : [ 5 , 1 0 , 1 5 , 2 0 ]
In [ 1 4 ] : l i s t e = [1 ,2 ,3 ,4]
In [ 1 5 ] : multiplie02 ( l i s t e ,5)
Out [ 1 5 ] : [ 5 , 1 0 , 1 5 , 2 0 ]
In [ 1 6 ] : l i s t e
Out [ 1 6 ] : [ 1 , 2 , 3 , 4 ]
d e f nom_de_la_procedure ( a r g u m e n t s ) :
" " " c o r p s du d o c s t r i n g : i n f o r m a t i o n s s u r l a f o n c t i o n , non
o b l i g a t o i r e s m a i s recommandees " " "
c o r p s de l a p r o c e d u r e
72 CHAPITRE 6
Attention, le docstring est destiné à l’utilisateur. Il n’est pas utilisé par l’interpréteur Python.
On peut récupérer le docstring d’une fonction ou d’une procédure avec help
Exemple 04 bis. Reprenons multiplie02 en lui mettant un docstring.
In [ 1 ] : def multiplie02 ( l i s t e , x ) :
...: " " " Pas d ’ e f f e t de b o r d . C h o u e t t e e e e e e e ! ! ! ! ! " " "
...: res = l i s t e
...: return [ x ∗ r e s [ i ] f o r i in range ( len ( r e s ) ) ]
In [ 2 ] : help ( multiplie02 )
Help on f u n c t i o n m u l t i p l i e 0 2 i n module __main__ :
multiplie02 ( liste , x)
Pas d ’ e f f e t de b o r d . C h o u e t t e e e e e e e ! ! ! ! !
I n [ 3 ] : h e l p ( divmod )
Help on b u i l t −i n f u n c t i o n divmod i n module b u i l t i n s :
divmod ( x , y , / )
R e t u r n t h e t u p l e ( x // y , x%y ) . I n v a r i a n t : d i v ∗ y + mod == x .
Analysons ce qui a été affiché. La fonction help est allé chercher le docstring de divmod. La
fonction a deux arguments x et y et renvoie un couple composé du quotient et du reste de la
division euclidienne de x par y. L’égalité div*y+mod == x signifie que si l’on rentre dans div
(respectivement mod) le premier élément (respectivement le second élément) du couple, x s’obtient
en faisant div*y+mod ce qui est bien la division euclidienne de x par y.
In [ 4 ] : x = 7.2; y = 3
I n [ 5 ] : d i v , mod = divmod ( x , y )
In [ 6 ] : div
Out [ 6 ] :
2.0
I n [ 7 ] : mod
Out [ 7 ] :
1.2000000000000002
I n [ 8 ] : d i v ∗ y + mod == x
Out [ 8 ] :
True
On peut remarquer que x et y ne sont pas obligatoirement entiers pour faire la division euclidienne.
ANALYSIS OF AN ALGORITHM 73
Exemple 06. Je désire connaître mieux hypot du module math
I n [ 1 2 ] : i m p o r t math
I n [ 1 3 ] : h e l p ( math . h y p o t )
hypot ( . . . )
h y p o t ( ∗ c o o r d i n a t e s ) −> v a l u e
M u l t i d i m e n s i o n a l E u c l i d e a n d i s t a n c e from t h e o r i g i n t o a
point .
Roughly e q u i v a l e n t to :
s q r t ( sum ( x ∗∗2 f o r x i n c o o r d i n a t e s ) )
For a two d i m e n s i o n a l p o i n t ( x , y ) , g i v e s t h e h y p o t e n u s e
u s i n g t h e P y t h a g o r e a n t h eo r em : s q r t ( x∗x + y∗y ) .
For example , t h e h y p o t e n u s e o f a 3/4/5 r i g h t t r i a n g l e i s :
>>> h y p o t ( 3 . 0 , 4 . 0 )
5.0
On remarque que le docstring est plus ou moins complet selon la fonction appelée.
Python est plus prolifique pour math.hypot que pour divmod.
2. Annotations et commentaires
Un programme doit être lu et relu facilement par l’auteur mais aussi par quelqu’un qui dćouvre le
programme. Aux concours notamment les annotations et commentaires ont vraiment leur place. Si
le candidat doit fabriquer sa procédure et qu’elle dépasse quelques lignes de codes, il faut mettre
des annotations pour expliquer ce que fait telle ligne de code ou telle boucle. Souvent dans les
sujets il y a des procédures à trous où le candidat doit rajouter les lignes ou les morceaux de ligne
de code manquants. Dans ces procédures, il y a souvent des annotations dont le rôle est de guider
pour remplir ce qui manque. Le docstring (voir le paragraphe précédent) joue aussi ce rôle.
Un commentaire est toujours précédé de # et comme pour un docstring, un commentaire n’est pas
utilisé par l’interprétateur Python. Remarquons qu’un commentaire peut être seul sur une ligne
ou se placer après du code sur la même ligne que ce code.
Exemple 07
Nous allons créer une procédure Swap_first_last d’argument liste qui permute le premier et
le dernier élément d’une liste et mettons-y un docstring assez complet et des annotations pour
expliquer les lignes de codes.
74 CHAPITRE 6
In [ 1 4 ] : def Swap_first_last ( l i s t e ) :
...: " " " l i s t e e s t de t y p e l i s t
...: l a p r o c e d u r e permute l e p r e m i e r e t l e d e r n i e r
e l e m e n t e t r e n v o i e une n o u v e l l e l i s t e
...: Swap_first_last ([1 ,2 ,3 ,4]) renvoie [4 ,2 ,3 ,1] """
...: n = l e n ( l i s t e ) # n e s t l a l o n g u e u r de l i s t e
...: # On f a i t une c o p i e de l i s t e :
...: copie = l i s t e [ : ]
...: # on permute l e s deux e l e m e n t s e x t r e m e s de l i s t e :
...: c o p i e [ 0 ] , c o p i e [ n −1] = c o p i e [ n −1] , c o p i e [ 0 ]
...: return copie
In [ 1 5 ] : l i s t e = [ −5 ,8 ,7 ,1 ,2 ,4]
In [ 1 6 ] : Swap_first_last ( l i s t e )
Out [ 1 6 ] :
[ 4 , 8 , 7 , 1 , 2 , −5]
In [ 1 7 ] : liste
Out [ 1 7 ] :
[ −5 , 8 , 7 , 1 , 2 , 4 ]
Assertion
Pour l’instant, on s’est intéressé dans une procédure à comment l’expliquer, faire comprendre ce
qu’elle fait, quelles variables on utilise etc. On va maintenant rajouter des instructions qui vont
arrêter le programme en cas de mauvaise utilisation.
On utilise une assertion qui est l’affirmation qu’une proposition est vraie. La fonction clé qui va
être utile, vous l’avez peut-être deviné, c’est la fonction assert que l’on commence à connaître.
On rappelle que l’on utilise assert suivi d’une expression dont la valeur est interprétée comme
une valeur booléenne. Comme on a vu plus haut, si l’expression a la valeur True, il ne se passe
rien. Sinon, le programme est interrompu et un message d’erreur s’affiche AssertionError
Exemple 08. Etablissons un programme qui renvoie l’inverse d’un flottant. L’idée c’est qu’il faut
signaler quand un très mauvais élève veut trouver l’inverse de 0.
ANALYSIS OF AN ALGORITHM 75
In [ 1 9 ] : def inverse (x) :
...: " " " x e s t un nombre non n u l de t y p e i n t ou f l o a t e t
cette f o n c t i o n r e n v o i e l ’ i n v e r s e de x " " "
...: a s s e r t x != 0
...: r e t u r n 1/ x
I n [ 2 0 ] : i n v e r s e ( −3)
Out [ 2 0 ] :
−0.3333333333333333
In [ 2 1 ] : i n v e r s e (0)
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
AssertionError
In [ 2 2 ] : def new_inverse ( x ) :
...: r e t u r n 1/ x
In [ 2 3 ] : new_inverse (0)
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
Z e r o D i v i s i o n E r r o r : d i v i s i o n by z e r o
Finalement, pas grand chose de plus ! Et ici l’erreur commise est bien expliquée.
Exemple 09. Reprendre la fonction maximum créée au chapitre 3 page 39 en y rajoutant un docs-
tring disant que L doit etre non vide et ce qu’elle renvoie et en y rajoutant aussi un assert qui
interrompt le programme si L est vide. On nommera new_maximum cette fonction.
76 CHAPITRE 6
I n [ 6 ] : d e f new_maximum ( L ) :
...: " " " L e s t une l i s t e de nombres non v i d e q u i r e n v o i e
l e maximum de l a l i s t e L " " "
...: a s s e r t L != [ ]
...: maxi = L [ 0 ]
...: f o r i in range (1 , len (L) ) :
...: i f L [ i ] > maxi :
...: maxi = L [ i ]
...: r e t u r n maxi
I n [ 7 ] : new_maximum ( [ 1 , 7 , 0 , − 8 , 7 , 1 0 , 2 ] )
Out [ 7 ] :
10
I n [ 8 ] : new_maximum ( [ ] )
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
AssertionError
# Et j u s t e p o u r l e f u n :
I n [ 1 0 ] : h e l p ( new_maximum )
Help on f u n c t i o n new_maximum i n module __main__ :
new_maximum ( L )
L e s t une l i s t e de nombres non v i d e q u i r e n v o i e l e maximum de
la l i s t e L
In [ 1 1 ] : def f o n c t i o n ( dico , k ) :
" " " d i c o e s t un d i c t i o n n a i r e
k e s t une c l e de d i c o " " "
assert k in dico
c o r p s de l a p r o c e d u r e
On contrôle ici si la valeur passée en second argument est bien une clé du dictionnaire mis en
premier argument. Si tel n’est pas le cas, le programme s’interrompt et Assertion Error s’affiche.
ANALYSIS OF AN ALGORITHM 77
Tests d’un programme
1.Introduction
Même si l’on soit clair dans le docstring, que l’on mette des commentaires aux endroits stratégiques
du programme et que l’on borde aussi avec desassert pour éviter de rentrer n’importe quoi en
argument, il peut se passer des choses étranges dans l’exécution du programme qui peut très bien
ne pas nous sauter aux yeux de suite. Il y a plusieurs sortes de bugs.
• Une erreur survient lors de certains tests et pas avec d’autres, c’est un bug intermittent. Ce
cas est un peu vicieux comme on va le voir avec l’exemple en dessous;
• une erreur survient pour chaque test, c’est un bug permanent; on a certainement tapé
un mauvais code quelque part, par exemple on a écrit une variable locale avec une faute
d’orthographe, mettre un = alors que c’est un ==, etc.;
• le programme s’arrête de manière prématurée ou ne s’arrête pas, le bug est visible.
Là c’est soit encore une erreur de frappe, soit un souci dans la conception de l’algorithme.
√
Exemple 10. Nous allons construire deux √ fonctions, la première Strange01(x,y) retourne xy
√
et la seconde Strange02(x,y) retourne x. y. Nous utiliserons la puissance 0.5 pour la racine
carrée. On peut utiliser aussi sqrt de numpy mais quand c’est possible, c’est mieux sans package.
In [ 1 1 ] : def Strange01 (x , y ) :
...: r e t u r n ( x ∗ y ) ∗∗ 0 . 5
In [ 1 2 ] : def Strange02 (x , y ) :
...: r e t u r n ( x ∗∗ 0 . 5 ) ∗ ( y ∗∗ 0 . 5 )
I n [ 1 3 ] : S t r a n g e 0 2 ( 1 e152 , 1 e152 ) / S t r a n g e 0 1 ( 1 e152 , 1 e152 )
Out [ 1 3 ] : 1 . 0
I n [ 1 4 ] : S t r a n g e 0 2 ( 1 e155 , 1 e155 ) / S t r a n g e 0 1 ( 1 e155 , 1 e155 )
Out [ 1 4 ] : 0 . 0
# J u s t e p o u r l a r e m a r q u e de l ’ e n o n c e :
I n [ 1 5 ] : i m p o r t numpy a s np
I n [ 1 6 ] : np . s q r t ( 9 )
Out [ 1 6 ] : 3 . 0
√ √ √
Comme x et y sont positifs, xy = x y et normalement les deux fonctions donnent le même
résultat. Et pourtant, c’est le cas pour x = y = 10152 et ce n’est pas le cas pour x = y = 10155 .
Est-ce un problème d’arrondi. Voyons avec le module decimal vu en fin de chapitre 5.
In [ 1 7 ] : import decimal
In [ 1 8 ] : D = decimal . Decimal
I n [ 1 9 ] : d e c i m a l . g e t c o n t e x t ( ) . p r e c = 40
I n [ 2 0 ] : D( S t r a n g e 0 2 ( 1 e155 , 1 e155 ) ) /D( S t r a n g e 0 1 ( 1 e155 , 1 e155 ) )
Out [ 2 0 ] : D e c i m a l ( ’ 0E−1000038 ’ )
# Ce n ’ e s t p a s bon . Augmentons l a p r e c i s i o n
I n [ 2 1 ] : d e c i m a l . g e t c o n t e x t ( ) . p r e c = 800
I n [ 2 2 ] : D( S t r a n g e 0 2 ( 1 e155 , 1 e155 ) ) /D( S t r a n g e 0 1 ( 1 e155 , 1 e155 ) )
Out [ 2 2 ] : D e c i m a l ( ’ 0E−1000798 ’ )
78 CHAPITRE 6
Donc le problème reste compliqué. Bref, évitons les nombres très, très grands (ou petits) !
2. Construction d’un jeu de tests
Construire un jeu de tests consiste à définir un ensemble de données qui vont être utilisées pour
vérifier que le programme produit bien les résultats attendus acec ces données. Ces vérifications
peuvent se faire de plusieurs manières. On peut utiliser print pour afficher quelques réponses et
vérifier qu’elles sont correctes. Pour un nombre conséquent de tests, il est pratique d’utiliser aussi
des assertions. Un message d’erreur est affiché seulement pour les cas qui posent problème.
On distinguera plusieurs types de tests :
• Tester quelques cas simples typiques (pour une utilisation basique du programme);
• tester des valeurs extrêmes, des cas limites, des cas interdits;
• tester un nombre important de données (choisies de façon aléatoire par exemple);
• tester des cas qui pourraient nécessiter un temps d’exécution important afin d’évaluer
l’efficacité du programme.
Une idée pour effectuer ces tests, c’est de partitionner le domaine d’entrée. Par exemple si l’on
désire calculer le PGCD de deux entiers m et n, c’est-à-dire le plus grand diviseur commun (ainsi
5 est le PGCD de 15 et de 10), on fait un programme personnel LEPGCD d’arguments m et n qui
retourne le PGCD de m et de n. Puis on peut tester avec un cas où m > n puis un autre avec m=n
puis un cas avec m est un multiple de n etc.
Si l’on a créée une fonction avec une liste à l’entrée, on teste naturellement le cas d’une liste vide
et le cas d’une liste à un élément ou le cas d’une liste avec un élément qui se répete un certain
nombre de fois, etc.
Exemple 07 bis. Reprenons la fonction Swap_first_last qui inverse le premier et dernier élément
d’une liste.
In [ 1 4 ] : def Swap_first_last ( l i s t e ) :
...: " " " l i s t e e s t de t y p e l i s t
...: l a p r o c e d u r e permute l e p r e m i e r e t l e d e r n i e r
e l e m e n t e t r e n v o i e une n o u v e l l e l i s t e
...: Swap_first_last ([1 ,2 ,3 ,4]) renvoie [4 ,2 ,3 ,1] """
...: n = l e n ( l i s t e ) # n e s t l a l o n g u e u r de l i s t e
...: # On f a i t une c o p i e de l i s t e :
...: copie = l i s t e [ : ]
...: # on permute l e s deux e l e m e n t s e x t r e m e s de l i s t e :
...: c o p i e [ 0 ] , c o p i e [ n −1] = c o p i e [ n −1] , c o p i e [ 0 ]
...: return copie
On essaye des cas différents. Si assert ne renvoie rien, c’est que l’égalité est True.
I n [ 2 ] : a s s e r t S w a p _ f i r s t _ l a s t ( [ 1 , 2 , 3 , 4 ] ) == [ 4 , 2 , 3 , 1 ]
I n [ 4 ] : a s s e r t S w a p _ f i r s t _ l a s t ( [ 1 ] ) == [ 1 ]
ANALYSIS OF AN ALGORITHM 79
Par contre, si l’on tape :
I n [ 5 ] : a s s e r t S w a p _ f i r s t _ l a s t ( [ ] ) == [ ]
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
I n d e x E r r o r : l i s t i n d e x out of range
La fonction Swap_first_last ne traite pas le cas d’une liste vide. Changeons le programme.
In [ 6 ] : def New_Swap_first_last ( l i s t e ) :
...: " " " l i s t e e s t de t y p e l i s t
...: l a p r o c e d u r e permute l e p r e m i e r e t l e d e r n i e r
e l e m e n t e t r e n v o i e une n o u v e l l e l i s t e
...: Swap_first_last ([1 ,2 ,3 ,4]) renvoie [4 ,2 ,3 ,1] """
...: i f l i s t e == [ ] : r e t u r n [ ]
...: n = l e n ( l i s t e ) # n e s t l a l o n g u e u r de l i s t e
...: # On f a i t une c o p i e de l i s t e :
...: copie = l i s t e [ : ]
...: # on permute l e s deux e l e m e n t s e x t r e m e s de l i s t e :
...: c o p i e [ 0 ] , c o p i e [ n −1] = c o p i e [ n −1] , c o p i e [ 0 ]
...: return copie
In [ 7 ] : New_Swap_first_last ( [ ] )
Out [ 7 ] : []
Cela marche !
Exemple 11. Une fonction prend en argument deux listes de même longueur. La deuxième liste
est modifiée et contient à la fin les mêmes éléments que la premirer liste aux mêmes places s’ils sont
positifs ou nuls et des zéros sinon. Nous allons faire deux versions et nous rendre compte qu’une
des deux ne marche pas toujours.
Dans la première version ESSAI01, on crée une boucle dans laquelle on remplace les éléments de
liste2 de l’indice 0 à len(liste1)-1 par ceux de liste1 de même indice si cet élément de liste1
est positif. Sinon on y met 0. On retourne enfin liste2 transformé.
80 CHAPITRE 6
I n [ 1 ] : d e f ESSAI01 ( l i s t e 1 , l i s t e 2 ) :
...: f o r i in range ( len ( l i s t e 1 ) ) :
...: i f l i s t e 1 [ i ] >= 0 :
...: liste2 [ i ] = liste1 [ i ]
...: else :
...: liste2 [ i ] = 0
...: return l i s t e 2
Dans la seconde procédure ESSAI02, on commence par remplacer tous les éléments de liste2
par des 0. Puis on remplace ces 0 par les éléments de liste1 correspondants à leur indice si ces
éléments de liste1 sont positifs.
In [ 8 ] : def ESSAI02 ( l i s t e 1 , l i s t e 2 ) :
...: f o r i in range ( len ( l i s t e 2 ) ) :
...: liste2 [ i ] = 0
...: f o r i in range ( len ( l i s t e 2 ) ) :
...: i f l i s t e 1 [ i ] >= 0 :
...: liste2 [ i ] = liste1 [ i ]
...: return l i s t e 2
I n [ 1 0 ] : l i s t e 1 = [2 , −3 ,5 , −1]
In [ 1 1 ] : l i s t e 2 = [1 ,2 ,3 ,4]
I n [ 1 2 ] : ESSAI01 ( l i s t e 1 , l i s t e 2 )
Out [ 1 2 ] : [ 2 , 0 , 5 , 0 ]
I n [ 1 3 ] : ESSAI02 ( l i s t e 1 , l i s t e 2 )
Out [ 1 3 ] : [ 2 , 0 , 5 , 0 ]
I n [ 1 6 ] : ESSAI01 ( l i s t e 1 , l i s t e 1 )
Out [ 1 6 ] : [ 2 , 0 , 5 , 0 ]
I n [ 1 7 ] : ESSAI02 ( l i s t e 1 , l i s t e 1 )
Out [ 1 7 ] : [ 0 , 0 , 0 , 0 ]
L’explication c’est que liste1 est devenu liste2 et au bout de la première boucle de ESSAI02,
liste1 ne contient plus que des 0. Puis on reremplit liste2 des 0 de liste1 dans la deuxième
boucle car liste1[i] >= 0 est toujours vraie.
ANALYSIS OF AN ALGORITHM 81
Complexité d’un algorithme
1. Introduction
Un algortithme, en dehors du fait qu’il doit être correct, doit satisfaire à des deux impératifs en
terme de consommation de ressources :
• Le temps d’exécution d’une suite d’instructions est la somme des temps d’execution de
chaque instruction.
• Le temps d’exécution d’une instruction conditionnelle du type if text : instructions 1
suivi de else : instructions 2 est inférieur ou égal au maximum du temps d’exécution
de instructions 1 et instructions 2 plus le temps d’exécution du test.
• Le temps d’exécution d’une boucle for i in range(p) : instructions est infop fois le
temps d’exécution de instructions si ce temps est constant plus p (le nombre d’affectations
pour la variable i. Si le temps d’exécution de instruction dépend de la valeur de p, l’étude
se ramène au cas par cas.
Enfin, pour une boucle while l’étude se ramène aussi au cas par cas.
L’évaluation du temps d’execution d’un algorithme se réduit ainsi à une évaluation en fonction
d’un nombre n (entier représentant la taille des données en entrée), du nombre total d’opérations
élémentaires noté un . Le niveau de complexité correspond au type de croissance de la suite (un ).
Suivant les valeurs de l’entrée, un peut prendre des valeurs très différentes. Si, par exemple, nous
parcourons une liste à l’aide d’une boucle, à la recherche d’un élément, celui-ci peut se trouver en
premier et nous sortons de la boucle, c’est le cas le plus favorable.
Il peut se trouver à la fin de la liste, c’est le pire des cas.
2. Niveaux de complexité
Considérons deux suites (un ) et (vn ). On suppose qu’aucune des deux suites ne s’annulent à partir
d’un certain rang de n.
• Notion de grand O
un
Si le rapport est borné à partir d’un certain rang de n, alors un = O(vn ).
vn
(On dit que un est un grand O de vn quand n tend vers +∞). On peut l’écrire :
82 CHAPITRE 6
∃ K ∈ R+ , ∃ N ∈ N, ∀n > N, |un | 6 K|un |.
un n + 2024 ln n 1 2024 ln n
Par exemple, si l’on pose un = n + 2024 ln n et vn = 2n, = = + .
vn 2n 2 2n
ln n 2024 ln n
Comme lim = 0, il existe N ∈ N tel que < 1 pour n > N.
n→+∞ n 2n
un 3
∀n > N, 6 ⇒ un = O(vn ).
vn 2
On peut remarquer que le cas le plus courant pour avoir un = O(vn ) est de montrer que :
un
lim = l,
n→+∞ vn
ANALYSIS OF AN ALGORITHM 83
In [ 3 ] : def Programmons01 ( n , k ) :
...: a = 0
...: f o r i in range (n) :
...: f o r j in range ( k ) :
...: a += i ∗ j
...: return a
Par exemple Programmons01(5,3) retourne 30. On suppose ici que k est fixé. Il y a une opération
d’affectation au départ. Puis il y a n passages dans la boucle externe. À chaque passage dans cette
boucle, on passe dans la boucle interne qui fait k multiplications puis k additions et k affectations.
Au total, on a un = 1 + 3kn opérations. On a alors un = O(n).
Par rapport à n, la complexité est linéaire.
In [ 5 ] : def Programmons02 ( n ) :
...: a = 0
...: f o r i in range (n) :
...: f o r j in range (n) :
...: a += i ∗ j
...: return a
Par exemple Programmons02(5) retourne 100. Il y a une opération d’affectation au départ. Puis il
y a n passages dans la boucle externe. À chaque passage dans cette boucle, on passe dans la boucle
interne qui fait n multiplications puis n additions et n affectations.
Au total, on a un = 1 + n.3n = 1 + 3n2 opérations.
On a alors un = O(n2 ). Par rapport à n, la complexité est quadratique.
In [ 8 ] : def Programmons03 ( n ) :
...: a = 0
...: f o r i in range (n) :
...: f o r j in range ( i ) :
...: a += i ∗ j
...: return a
Par exemple Programmons03(5) retourne 35. Il y a une opération d’affectation au départ. Puis il
y a n passages dans la boucle externe. À chaque passage dans cette boucle, on passe dans la boucle
interne qui fait i multiplications puis i additions et i affectations. Au total, on a :
n
X 3
un = 1 + 3i = + + n(n + 1)
i=1
2
84 CHAPITRE 6
Exercice 01. On admet que le nombre de chiffres dans l’écriture décimale de n est blog10 (n) + 1c.
On considère le programme suivant :
In [ 1 ] : c = 0
In [ 2 ] : while n > 0 :
...: c = c + 1
...: n = n // 10
1. Faire fonctionner ce programme à la main pour n = 10008. Combien y-a-t-il de tours dans
la boucle ?
2. Déterminer la complexité par rapport à n.
Exercice 02.
1. Écrire un programme appelé Somme01(t) effectuant simplement avec deux boucles imbriquées
le calcul de la somme
n−1
X n−1 X 2
S= (t[i] − t[j])
i=0 j=0
I n [ 1 ] : wn = 0 ; sn = 0
In [ 2 ] : for j in r a n g e ( n−1) :
sn = sn + t [ j ]
wn = wn + t [ j +1]∗ s n
ANALYSIS OF AN ALGORITHM 85
86 CHAPITRE 6
Chapitre 7
Sorting recursionless
87
Objectifs
Les incontournables :
I savoir
88 CHAPITRE 7
Cours
Le tri de données constitue l’un des problèmes fondamentaux de l’algorithmique. On considère une
liste de données, auxquelles sont attachées des clés. On cherche à trier ces donnéesen fonction des
clés (par exemple, trier une liste d’élèves par ordre alphabétique, ou par ordre de moyennes...).
Nous nous placerons pour simplifier dans le cas ù la clé est la donnée elle-même.
Programmation
Commençons par écrire une fonction qui détermine l’indice du plus petit élément d’une liste entre
les positions i et j.
In [ 1 ] : def cherche_ind_min ( l , i , j ) :
...: " " " r e n v o i e l ’ i n d i c e du p l u s p e t i t e l e m e n t de l a s o u s −
l i s t e l [ i . . j ] """
...: imin = i
...: f o r k i n r a n g e ( i +1, j +1) :
...: i f l [ k ] < l [ imin ] :
...: imin = k
...: return imin
In [ 2 ] : cherche_ind_min ([ −3 ,7 ,11 ,0 ,4 ,7 ,0 ,5 ,8 ,1] ,1 ,4)
Out [ 2 ] : 3
In [ 3 ] : cherche_ind_min ([ −3 ,7 ,11 ,0 ,4 ,7 ,0 ,5 ,8 ,1] ,0 ,9)
Out [ 3 ] : 0
SORTING RECURSIONLESS 89
In [ 5 ] : def t r i _ s e l e c t i o n ( l ) :
...: " " " t r i e l a l i s t e l p a r l ’ a l g o r i t h m e du t r i s e l e c t i o n ,
la fonction modifie la l i s t e l """
...: n = len ( l )
...: f o r i i n r a n g e ( n−1) :
...: i m i n = c h e r c h e _ i n d _ m i n ( l , i , n−1)
...: l [ i ] , l [ imin ] = l [ imin ] , l [ i ]
...: return l
In [ 6 ] : t r i _ s e l e c t i o n ([ −3 ,7 ,11 ,0 ,4 ,7 ,0 ,5 ,8 ,1])
Out [ 6 ] : [ −3 , 0 , 0 , 1 , 4 , 5 , 7 , 7 , 8 , 1 1 ]
Rappelons que, lors de l’écriture d’un algorithme, on doit être en mesure de justifier sa terminaison.
C’est ici évident car on a une boucle inconditionnelle (boucle f or) qui se termine toujours (contrai-
rement à une boucle while).
Remarque : Lorsque les données à trier sont distinctes des clés utilisées pour trier la liste (par
exemple, un élève n’est pas égal à sa moyenne), on peut s’intéresser à ce qui arrive à deux éléments
ayant la même clé (deux élèves ayant la même moyenne) : après le tri, ces deux éléments sont-ils
dans la même position relative l’un par rapport à l’autre qu’avant le tri ? Lorsque c’est le cas, on
dit que le tri est stable. Le tri par sélection n’est pas stable : par exemple si les données sont A,
B et C, et que les clés attachées sont 1,,1 et 0, (ce que l’on notera par A1 , B1 et C0 ), le tri par
sélection part de [A1 , B1 , C0 ] qui devient [C0, B1, A1] car le minimum de (A1, B1, C0) est C0 qui
permute avec A1.
Complexité
Calculons la complexité de cet algorithme en nous intéressant au nombre de comparaisons effec-
tuées.
− la fonction cherche_ind_min appelée avec les arguments i et j, effectue j − i comparaisons.
Quand elle est appelée entre i et n − 1, elle en effectue n − i − 1.
− chaque passage dans la boucle indexée par i de la fonction tri_selection effectue donc n − i − 1
comparaisons. Comme i varie de 0 à n − 2, il y a au total :
n−2 n−1
X X n(n − 1)
C(n) = (n − i − 1) = k= comparaisons.
i=0
2
k=1
90 CHAPITRE 7
1. Écrire une fonction distance2 qui prend en paramètre une liste de deux nombres nommée point
qui représente un point du plan, (point est la liste des coordonnées d’un point P ), et renvoie le
carré de la distance de ce point à 0. On pourra utiliser sqrt de numpy et le code x,y=point.
Voyons cet exemple :
In [ 1 4 ] : x , y = [4 ,5]
In [ 1 5 ] : x
Out [ 1 5 ] : 4
In [ 1 6 ] : y
Out [ 1 6 ] : 5
2. Écrire une fonction compare qui prend en paramètres deux mistes p1 et p2 représentant deux
points P1 et P2 et qui renvoie −1 si P1 est plus proche de 0 que P1 et 1 si P2 est plus proche de 0
que P1 ,, et 0 si les deux points sont équidistants de 0.
3. On écrit une fonction tri_points qui prend en paramètre une liste composée de listes de deux
nombres représantant des points du plan et qui trie cette liste suivant la distance entre les points
et O. On adapte le tri selection. Le code est le suivant :
In [ 1 ] : def tri_points ( l i s t e ) :
...: f o r i i n r a n g e ( l e n ( l i s t e ) −1) :
...: i_mini = i
...: mini = l i s t e [ i ]
...: f o r j i n r a n g e ( i +1, l e n ( l i s t e ) ) :
...: i f compare ( l i s t e [ j ] , m i n i ) == −1:
...: i_mini = j
...: mini =l i s t e [ j ]
...: l i s t e [ i ] , l i s t e [ i_mini ] = l i s t e [ i_mini ] , l i s t e [ i ]
...: return l i s t e
SORTING RECURSIONLESS 91
2.
In [ 1 7 ] : d e f compare ( p1 , p2 ) :
...: d1 = d i s t a n c e 2 ( p1 )
...: d2 = d i s t a n c e 2 ( p2 )
...: i f d1<d2 :
...: r e t u r n −1
...: e l i f d2<d2
...: return 1
...: else :
...: return 0
In [ 1 8 ] : compare ( [ 7 , 8 ] , [ 2 , − 7 ] )
Out [ 1 8 ] : 1
In [ 1 9 ] : compare ( [ − 7 , 1 ] , [ 2 , − 7 ] )
Out [ 1 9 ] : −1
3.
In [ 2 4 ] : compare ( [ 0 , 7 ] , [ 3 , 5 ] ) , compare ( [ 3 , 5 ] , [ 2 , 1 ] ) ,
Out [ 2 4 ] : (1 ,1)
In [ 2 5 ] : compare ( [ 2 , 1 ] , [ − 2 , 0 ] ) , compare ( [ 0 , 7 ] , [ − 2 , 0 ] )
Out [ 2 5 ] : (1 , 1)
In [ 2 6 ] : tri_points ([[3 ,5] ,[2 ,1] ,[0 ,7] ,[ −2 ,0]])
Out [ 2 6 ] : [[ −2 , 0 ] , [ 2 , 1 ] , [ 0 , 7 ] , [ 3 , 5 ] ]
Programmation
92 CHAPITRE 7
In [ 1 ] : def t r i _ i n s e r t i o n ( l ) :
...: " " " t r i e l a l i s t e l p a r a l g o r i t h m e du t r i s e l e c t i o n ,
la fonction modifie la l i s t e l """
...: n = len ( l )
...: f o r k in range (1 , n) :
...: a_placer = l [ k ]
...: i = k−1
...: w h i l e i >= 0 and a _ p l a c e r < l [ i ] :
...: l [ i +1] = l [ i ]
...: i = i −1
...: l [ i +1] = a _ p l a c e r
...: return l
In [ 2 ] : t r i _ i n s e r t i o n ([ −1 , −5 ,4 , −7 ,1 ,10 ,8 ,0])
Out [ 2 ] : [ −7 , −5, −1, 0 , 1 , 4 , 8 , 1 0 ]
Cmin (n) = n − 1.
SORTING RECURSIONLESS 93
C’est encore une complexité quadratique (comme pour le tri par sélection).
Exercice 02. Trier A, B, C, D de clès respectives 1, 3, 8, 1 à la main par le tri insertion.
On détaillera les différentes affectations et on pourra noter la liste [A1 , B3 , C8 , D1 ].
Exemple. Nous allons comparer le temps d’exécution du tri par insertion, par selection et par
l’attribut prédéfini sort en utilisant le module time.
I n [ 3 ] : from t i m e i m p o r t p e r f _ c o u n t e r a s pc
In [ 4 ] : l = [2 ,1 ,4 ,0 ,8 ,4 , −4 ,7 ,5 ,8 ,7 ,10 ,0 , −4 , −5 , −8 ,4 ,11 ,7 ,9]
I n [ 5 ] : t = pc ( ) ; p r i n t ( t r i _ s e l e c t i o n ( l ) ) ; p r i n t ( pc ( ) − t )
[ −8 , −5 , −4 , −4 ,0 , 0 , 1 , 2 , 4 , 4 , 4 , 5 , 7 , 7 , 7 , 8 , 8 , 9 , 1 0 , 1 1 ]
0.0007508000001053006
I n [ 1 0 ] : t = pc ( ) ; p r i n t ( t r i _ s e l e c t i o n ( new_l ) ) ; p r i n t ( pc ( )−t )
[ −8 , −5 , −4 , −4 ,0 ,0 ,1 , 2 , 4 , 4 , 4 , 5 , 7 , 7 , 7 , 8 , 8 , 9 , 1 0 , 1 1 ]
0.00032749999991210643
# on v o i t que l ’ o r d r e de g r a n d e u r e s t l e meme p o u r l e t r i
s e l e c t i o n et l e t r i i n s e r t i o n .
I n [ 1 1 ] : new2_l =
[2 ,1 ,4 ,0 ,8 ,4 , −4 ,7 ,5 ,8 ,7 ,10 ,0 , −4 , −5 , −8 ,4 ,11 ,7 ,9]
I n [ 1 2 ] : t = pc ( ) ; p r i n t ( new2_l . s o r t ( ) ) ; p r i n t ( pc ( ) − t )
None
0.0016777000000729458
I n [ 1 3 ] : new2_l
Out [ 1 3 ] : [ − 8 , − 5 , − 4 , − 4 , 0 , 0 , 1 , 2 , 4 , 4 , 4 , 5 , 7 , 7 , 7 , 8 , 8 , 9 , 1 0 , 1 1 ]
I n [ 1 4 ] : new2_l . s o r t ( )
In [ 1 5 ] : 0.0016777/0.00075
Out [ 1 5 ] : 2 . 2 3 6 9 3 3 3 3 3 3 3 3 3 3 3 4
# un peu p l u s r a p i d e a v e c l a f o n c t i o n s o r t
94 CHAPITRE 7
Arbres binaires
B C
D E F G
Figure 1
Cet arbre est formé de trois noeuds internes A, B et C, et de quatre feuilles D, E, F et G. Le
noeud A est la racine de l’arbre ; le sous-arbre pointé par la flèche AB st le fils gauche du noeud
A ; le sous-arbre pointé par la flèche AC est son fils droit. Ces deux sous-arbres ont pour père le
noeud A.
Définition : La hauteur d’un arbre est la longueur (ie nombre de flèches) maximale d’un chemin
allant de la racine à une feuille.
Quelle est la hauteur de l’arbre de l’exemple précédent ?
Exercice 03. Représenter deux arbres de hauteur 4, le premier ayant 4 + 1 feuilles et le second 24
feuilles.
Proposition
Un arbre de hauteur n a donc au moins n + 1 feuilles (cas où chaque fils gauche est une feuille par
exemple) et au plus 2n feuilles (cas où tous les noeuds sauf ceux du bas, ont 2 fils).
Preuve : représenter les cas extremes en s’inpirant de l’exercice précédent.
Arbre de décision
On désire faire un choix dans un ensemble E de cardinal n 6= 0. Un arbre de décision associé à ce
choix est un arbre binaire tel que :
• la racine est étiquettée par l’ensemble E
• chaque feuille est étiquettée par un singleton inclus dans E
SORTING RECURSIONLESS 95
• chaque noeud qui n’est point une feuille est étiqueté par un sous-ensemble E1 de E et ses deux
fils par des sous-ensembles E2 et E3 de E1 tels que E1 = E2 ∪ E3 . Attention, E2 et E3 ne sont pas
nécessairement disjoints.
• On adjoint à chaque noeud un test booléen et les deux flèches issues de ce noeud portent les
labels T ou F pour T rue ou F alse.
Exercice 04. Faire un arbre de décision pour la recherche de min(a, b, c), c’est-à-dire associé au
choix du plus petit parmi les nombres a, b et c.
Proposition
Un arbre de décision associé à un ensemble de cardinal n doit posséder n feuilles au moins ; sa
hauteur h vérifie : h > log2 (n).
Utilisons maintenant un arbre de décision pour le problème du tri d’une liste l de taille n. En
supposant les éléments deux à deux distincts, il y a n! listes différentes contenant ces éléments
donc n! feuilles. Chacune de ces feuilles est constituée d’une permutation de la liste l. Trier la
liste revient à trouver, parmi les n! permutations de l, quelle est celle qui est triée. Notre arbre
de décision a pour ensemble de référence l’ensemble E des permutations de l ; les tests associés à
chaque noeud sont les tests comparant deux éléments du tableau. La hauteur minimale de l’arbre
de décision est donc supérieure ou égale à
n
X
log2 (n!) = log2 (k).
k=2
Et en sommant :
n Z
X k n
X n Z
X k+1
ln t dt 6 ln k 6 ln t dt.
k=2 k−1 k=2 k=2 k
C’est-à-dire :
Z n Z n+1
ln t dt 6 ln(n!) 6 ln t dt.
1 2
Il reste à intégrer :
Comme le nombre de comparaisons dans le pire des cas est égal à la hauteur de l’arbre de décision,
nous avons démontré le théorème.
96 CHAPITRE 7
Tris sans comparaison
Les tris présentés auparavant sont des tris qui utilisent les comparaisons. Il existe d’autres types
de tris par exemple par comptage, par paquets, par base. Présentons ici le tri par comptage.
On dispose d’une liste d’entiers naturels qui sont tous inférieurs à un entier naturel non num m
qui est de l’ordre de n qui est la taille de la liste.
On commence par écrire une fonction comptage, d’arguments une liste entiers et un entier m,
renvoyant une liste de longueur m+1 telle que pour tout ’k de 0 à m, l’élément d’indice k a pour
valeur le nombre d’occurrences de l’entier k dans la liste entiers. Pour cela, on crée une liste
composée de 0 et de longueur m + 1. Chaque élément de cette liste sert de compteur.
Commençons par une première version nommée comptage
# SOLUTION :
I n [ 1 5 ] : comptage ( [ 1 , 2 , 4 , 5 , 4 , 1 , 0 , 1 , 0 , 0 , 7 , 1 , 4 , 4 , 7 , 2 ] , 1 7 )
Out [ 1 5 ] : [ 3 , 4 , 2 , 0 , 4 , 1 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]
I n [ 1 6 ] : comptage ( [ 1 , 2 , 4 , 5 , 4 , 1 , 0 , 1 , 0 , 0 , 7 , 1 , 4 , 4 , 7 , 2 ] , 7 )
Out [ 1 6 ] : [ 3 , 4 , 2 , 0 , 4 , 1 , 0 , 2 ]
I n [ 1 7 ] : comptage ( [ 1 , 2 , 4 , 5 , 4 , 1 , 0 , 1 , 0 , 0 , 7 , 1 , 4 , 4 , 7 , 2 ] , 3 )
Out [ 1 7 ] : [ 3 , 4 , 2 , 0 ]
Cet algorithme contient deux boucles imbriquées et son coût est de l’ordre m×n et donc quadratique
en n car m = O(n). Voici donc une version plus efficace, dont le coût en fonction de la longueur n
de la liste est linéaire. On la note new_comptage.
In [ 5 ] : d e f new_comptage ( e n t i e r s ,m) :
...: c o m p t e u r s = (m+1) ∗ [ 0 ]
...: for k in entiers :
...: compteurs [ k ] = compteurs [ k ] + 1
...: r e t u r n compteurs
SORTING RECURSIONLESS 97
Les valeurs des éléments de la liste entiers sont représentés par les indices de la liste compteurs.
On en déduit une fonction tri, d’arguments une liste entiers et un entier m, renvoyant la liste
tridans l’ordre croissant.
Exercice 06 Appliquer à la main new_comptage à la liste [1,2,4,5,4,1,0,1,0,0,7,1,4,4,7,2]
avec m=3 puis m=7 puis m=17 et m=22. Qu’obtient-on ?
# SOLUTION :
I n [ 1 8 ] : new_comptage ( [ 1 , 2 , 4 , 5 , 4 , 1 , 0 , 1 , 0 , 0 , 7 , 1 , 4 , 4 , 7 , 2 ] , 1 7 )
Out [ 1 8 ] : [ 3 , 4 , 2 , 0 , 4 , 1 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]
I n [ 1 9 ] : new_comptage ( [ 1 , 2 , 4 , 5 , 4 , 1 , 0 , 1 , 0 , 0 , 7 , 1 , 4 , 4 , 7 , 2 ] , 7 )
Out [ 1 9 ] : [ 3 , 4 , 2 , 0 , 4 , 1 , 0 , 2 ]
I n [ 2 0 ] : new_comptage ( [ 1 , 2 , 4 , 5 , 4 , 1 , 0 , 1 , 0 , 0 , 7 , 1 , 4 , 4 , 7 , 2 ] , 3 )
T r a c e b a c k ( most r e c e n t c a l l l a s t ) :
I n d e x E r r o r : l i s t i n d e x out of range
# que s e p a s s e t− i l s i l ’ on p r e n d d e s n e g a t i f s ?
I n [ 9 ] : new_comptage ( [ − 1 , 2 , 4 , 5 , 4 , 1 , 0 , 1 , 0 , 0 , 7 , − 1 , 4 , 4 , 7 , 2 ] , 2 2 )
Out [ 9 ] : [ 3 , 2 , 2 , 0 , 4 , 1 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 2]
I n [ 1 0 ] : d e f t r i ( e n t i e r s ,m) :
...: c p t s = new_comptage ( e n t i e r s , m)
...: triee = []
...: f o r i i n r a n g e (m+1) :
...: t r i e e = t r i e e + cpts [ i ] ∗ [ i ]
...: return triee
...:
98 CHAPITRE 7
In [ 2 1 ] : t r i ([1 ,2 ,4 ,5 ,4 ,1 ,0 ,1 ,0 ,0 ,7 ,1 ,4 ,4 ,7 ,2] ,17)
Out [ 2 1 ] : [ 0 , 0 , 0 , 1 , 1 , 1 , 1 , 2 , 2 , 4 , 4 , 4 , 4 , 5 , 7 , 7 ]
I n d e x E r r o r : l i s t i n d e x out of range
SORTING RECURSIONLESS 99
100 CHAPITRE 7
Chapitre 8
Algorithm of Gauss
101
Objectifs
Les incontournables :
I savoir
102 CHAPITRE 8
Cours
Il s’agit de créer une fonction Python qui permet de résoudre un système linéaire avec la méthode
de Gauss. Mais auparavant, on va faire fonctionner la syntaxe autour des matrices puis on va créer
les opérations élémentaires classiques sur les lignes et colonnes de matrices.
Pour la culture, parlons de Gauß
Nom de naissance Johann Carl Friedrich Gauß
Naissance 30 avril 1777 Brunswick (Principauté de Brunswick-Wolfenbüttel)
Décès 23 février 1855 (à 77 ans) Göttingen (Royaume de Hanovre)
Nationalité : Allemand
Domaines : Astronomie, mathématiques, physique
Lieu de travail : Université de Göttingen
Diplôme : Université de Helmstedt
I n [ 1 ] : i m p o r t numpy a s np ; i m p o r t numpy . l i n a l g a s a l g
Dans la suite, soit A ∈ Mn,p (R), dont les lignes sont les listes L0 , ..., Ln−1 , toutes de même taille
p et les colonnes sont les listes C0 , ..., Cp−1 toutes de même taille n.
Attention, en Math, les indices partent conventionnellement de 1 mais en Python de
0 donc ici tous nos indices démarreront à 0 pour ne pas faire des mélanges.
I Pour définir la matrice A ∈ Mn,p (R), sous numpy, on tape un code (en rentrant les listes
de ligne) de la forme -1A = np.array([L_0,...,L_n ]).
I La commande A.shape donne la taille (n, p) de A. La commande A.size renvoie n × p,
np.size(A,0) (resp. np.size(A,1) renvoie n (resp. p).
I Le coefficient de A à l’intersection de la ligne Li et colonne Cj est A[i,j].
I Le code A[i, :] (ou aussi A[i]) est la ligne Li (tableau à une dimension) de A.
I Le code A[:, j] est la colonne Cj (tableau à une dimension) de A.
I Le code A[i:j, k:l] renvoie la sous-matrice de la ligne Li à la ligne Lj−1 et de la colonne
Ck à la colonne Cl−1 .
I Le code p.zeros((n,p)) renvoie la matrice nulle de Mn,p (R) et np.eye(n) renvoie In , la
matrice identité d’ordre n.
I Le code np.ones((n,p)) renvoie la matrice Attila (composée que de 1) de Mn,p (R)
I Le code np.diag(L) renvoie la matrice carrée diagonale dont les coefficients de la diag-
onale principale sont les éléments de la liste L dans l’ordre.
Si i et j sont deux entiers distincts dans [[0, p − 1]], on a les opérations sur les colonnes :
Ci ← Ci + λCj , Ci ← λCi , Ci ↔ Cj .
Comment écrire en langage Python les opérations élémentaires classiques sur les lignes
de matrices
Il s’agit de créer les fonctions Li ← Li + xLj , Li ← xLi et Li ↔ Lj .
104 CHAPITRE 8
I Pour effectuer la transvection Li ← Li + xLj sur une matrice A, on tapera :
# VERSION LONGUE
I n [ 2 3 ] : d e f o l d _ t r a n s v e c l i g n e (A , i , j , x ) :
...: p = np . s i z e (A , 1 )
...: f o r m in range (p) :
...: A [ i ,m] = A [ i ,m] + x ∗A [ j ,m]
...: return A
...:
# VERSION COURTE
I n [ 2 6 ] : d e f t r a n s v e c l i g n e (A , i , j , x ) :
...: A [ i , : ] = A [ i , : ] + x ∗A [ j , : ]
...: return A
1 −1 0
Exercice 02 : Appliquer L1 ← L1 −L2 à A = −2 4 1 d’abord avec old_transvecligne
0 3 −5
puis transvecligne. Attention, la matrice A après l’action de old_transvecligne sera
transformée. Vérifier à la main.
I Pour effectuer la dilatation Li ← xLi sur A, on tape (version courte directe) :
I n [ 2 9 ] : d e f d i l a t l i g n e (A , i , x ) :
...: A[ i , : ] = x ∗ A[ i , : ]
...: return A
# Par exemple , d i l a t o n s L1 de l a m a t r i c e A t t i l a
I n [ 3 0 ] : d i l a t l i g n e ( np . o n e s ( ( 3 , 5 ) ) , 1 , 2 0 2 4 )
Out [ 3 0 ] :
a r r a y ( [ [ 1 . 0 0 0 e +00 , 1 . 0 0 0 e +00 , 1 . 0 0 0 e +00 , 1 . 0 0 0 e +00 , 1 . 0 0 0 e +00] ,
[ 2 . 0 2 4 e +03 , 2 . 0 2 4 e +03 , 2 . 0 2 4 e +03 , 2 . 0 2 4 e +03 , 2 . 0 2 4 e +03] ,
[ 1 . 0 0 0 e +00 , 1 . 0 0 0 e +00 , 1 . 0 0 0 e +00 , 1 . 0 0 0 e +00 , 1 . 0 0 0 e + 0 0 ] ] )
# VERSION LONGUE
I n [ 3 4 ] : d e f o l d _ p e r m u t l i g n e (A , i , j ) :
...: p = np . s i z e (A , 1 )
...: f o r m in range (p) :
...: temp=A [ i ,m ] ; A [ i ,m]=A [ j ,m ] ; A [ j ,m]= temp
...: return A
# VERSION COURTE
I n [ 3 5 ] : d e f p e r m u t l i g n e (A , i , j ) :
...: A [ i , : ] , A [ j , : ] = np . copy (A [ j , : ] ) , np . copy (A [ i , : ] )
...: return A
I n [ 3 6 ] : A = np . a r r a y ( [ [ 1 , − 1 , 0 ] , [ − 2 , 4 , 1 ] , [ 0 , 3 , − 5 ] ] )
I n [ 3 7 ] : o l d _ p e r m u t l i g n e (A , 0 , 2 )
Out [ 3 7 ] :
a r r a y ( [ [ 0 , 3 , −5] ,
[ −2 , 4 , 1 ] ,
[ 1 , −1, 0 ] ] )
I n [ 3 8 ] : p e r m u t l i g n e (A , 1 , 2 )
Out [ 3 8 ] :
a r r a y ( [ [ 0 , 3 , −5] ,
[ 1 , −1, 0 ] ,
[ −2 , 4 , 1 ] ] )
Exercice 03. Écrire les fonctions Python qui correspondent aux trois opérations sur les
colonnes que l’on notera transveccolonne, dilatcolonne et permutcolonne. On adaptera
les versions courtes des fonctions
sur les lignes
écrites plus haut. Appliquer alors à trans-
1 −1 3
former la matrice : A = 0 1 2 en I3 en utilisant un certain nombre des six
−1 −2 0
fonctions Python, de la façon dont cela vous semble nécessaire.
Pour effectuer la transvection Ci ← Ci + kCj sur A, on tape :
I n [ 3 9 ] : d e f t r a n s v e c c o l o n n e (A , i , j , k ) :
A [ : , i ] + = k ∗A [ : , j ]
return A
I n [ 4 0 ] : d e f d i l a t c o l o n n e (A , i , x ) :
A[: , i ] = x ∗ A[: , i ]
return A
I n [ 4 1 ] : d e f p e r m u t c o l o n n e (A , i , j ) :
A [ : , i ] , A [ : , j ] = np . copy ( A [ : , j ] ) , np . copy (A [ : , i ] )
return A
106 CHAPITRE 8
Application à l’algorithme de Gauss-Jordan pour inverser une matrice
Cette méthode permet aussi à la fois de prouver l’inversibilité et de trouver l’inverse. Ma-
triciellement, les opérations élémentaires sur les lignes correspondent à la multiplication à
gauche par un certain nombre de matrices Qi ∈ GLp (K) de la matrice A pour obtenir
Qk Qk−1 ...Q1 A = Ip , ce qui montre déjà que A est inversible (car elle possède un inverse à
gauche) puis en multipliant à droite chacun des membres de cette égalité par A−1 , on obtient
A−1 = Qk Qk−1 ...Q1 . Cela justifie le fait que A−1 se retrouve après opérations élémentaires
sur les lignes dans la partie droite de la matrice à p lignes et 2p colonnes obtenue.
on écrit d’abord la matrice à p lignes et 2p colonnes schématisée par A Ip , le
symbole | étant juste une barrière virtuelle qui permet de distinguer les deux parties
importantes de la matrice;
on transforme cette matrice par opérations élémentaires sur les lignes (sans se soucier
de la barrière virtuelle) pour aboutir à la matrice schématisée par Ip A−1 .
2 2 3
Exercice 04 : inverser avec Python A = 1 1 4 . On commencera par concaténer
1 −2 1
A et I3 et on utilisera les fonctions Pythons qui font les opérations élémentaires sur les lignes.
À la fin, on déconcaténera.
10−20 x + y
= 1
.
x+y = 2
I n [ 4 1 ] : A = np . a r r a y ( [ [ 1 0 ∗ ∗ ( − 2 0 ) , 1 ] , [ 1 , 1 ] ] )
I n [ 4 2 ] : B = np . a r r a y ( [ [ 1 ] , [ 2 ] ] )
I n [ 4 3 ] : a l g . s o l v e (A , B)
Out [ 4 2 ] :
array ( [ [ 1 . ] , [ 1 . ] ] )
108 CHAPITRE 8
I n [ 1 ] : d e f s y s t L i n (A , B) :
# on f a i t d e s c o p i e s de A e t de B
A1 = np . copy (A) ; B1 = np . copy (B)
# on c o n c a t e n e e n s e m b l e A1 e t B1 d a n s D
D = np . c o n c a t e n a t e ( ( A1 , B1 ) , a x i s =1)
p r i n t (D)
n = np . s i z e ( A1 , 0 )
# On t r a n s f o r m e D en une m a t r i c e t r i a n g sup
f o r j i n r a n g e ( n−1) :
f o r i i n r a n g e ( j +1,n ) :
p r i n t ( ’ l e p i v o t e s t : ’ ,D[ j , j ] )
c = D[ i , j ] /D[ j , j ]
p r i n t ( ’ on e n l e v e a l a ’ , i , ’ eme l i g n e ’ , c , ’ f o i s l a ’ , j , ’
eme l i g n e ’ )
D = t r a n s v e c l i g n e (D, i , j ,− c )
p r i n t (D)
# on t r a n s f o r m e D ( s a u f d e r n i e r e c o l ) en m a t r i c e d i a g
f o r j i n r a n g e ( n −1 ,0 , −1) :
f o r i i n r a n g e ( j −1,−1,−1) :
c = D[ i , j ] /D[ j , j ]
p r i n t ( ’ on e n l e v e a l a ’ , i , ’ eme l i g n e ’ , c , ’ f o i s l a ’ , j , ’
eme l i g n e ’ )
D = t r a n s v e c l i g n e (D, i , j ,− c )
p r i n t (D)
# On t r a n s f o r m e l a d e r n i e r e c o l o n n e de D en m a t r i c e l i g n e
NewB1 = np . a r r a y ( [ D [ : , n ] ] )
# On d i v i s e l e s l i g n e s de NewB1 p a r l e s p i v o t s s u c c e s s i f s
f o r s in range (n) :
S o l = d i l a t c o l o n n e ( NewB1 , s , 1 . / D[ s , s ] )
# On r e t o u r n e a l o r s l e s s o l u t i o n s du s y s t e m e
return Sol
Warning : Attention, on rentre les coefficients des lignes de A et B sous forme de flottants
(donc en rajoutant un .). En effet, sinon, il y aura des arrondis dans les divisions qui
conduiront à un résultat erroné.
# PASSONS A EXEMPLE 02
I n [ 2 ] : A = np . a r r a y ( [ [ 1 . , − 1 . , 0 . ] , [ − 2 . , 4 . , 1 . ] , [ 0 . , 3 . , − 5 . ] ] )
I n [ 3 ] : B = np . a r r a y ( [ [ 1 . ] , [ 4 . ] , [ 0 . ] ] )
I n [ 4 ] : s y s t L i n (A , B)
# on a t t a q u e l a d e u x i e m e d o u b l e b o u c l e c e l l e de l a remontada
# l a m a t r i c e newB1 e s t :
[ [ 3 . 3 0 7 6 9 2 3 1 4 . 6 1 5 3 8 4 6 2 −9. ]]
# p u i s on r e t o u r n e s o l
array ([[3.30769231 , 2.30769231 , 1.38461538]])
110 CHAPITRE 8
Intéressons-nous maintenant à la complexité algorithmique de la méthode du pivot
de Gauss en posant n la taille de la matrice A.
A l’intérieur des deux premières boucles imbriquées, on a une division et 2 appels à la fonction
transvecligne, ce qui fait 2n+1 opérations au plus. Comme les deux boucles imbriquées
sont un O(n2 ), on a donc une complexité en O(n3 ).
A l’intérieur des deux autres boucles imbriquées, on a encore une division et 2 appels à
transvecligne ce qui fait 2n+1 opérations au plus. Comme les deux boucles imbriquées
sont un O(n2 ), on a donc encore une complexité en O(n3 ). Et on a un appel à dilatligne
dans la boucle extérieure, ce qui fait un O(n2 ).
Donc en sommant O(n3 ) + O(n3 ) + O(n2 ), on a une complixité totale de O(n3 ).
Pour votre culture, l’algorithme de Strassen, qui est en O(n2.807 ) a une meilleure complexité
algorithmique asymptotique.
Programme du pivot de Gauss amélioré
Commençons par illustrer avec un nouveau système.
x + 3y + 2z − 5t = 1
x − 4y − 2z + 6t = −2
Exercice 05. Tester systLin sur le système suivant : .
3x + y − 2z + t
= 3
−2x + y − 4z + 3t = 2
Que remarque t-on ?
On remarque que le dernier pivot de la première double boucle est un 0. Et donc on divise
par 0. Il apparaît ensuite le code nan qui signifie : not a number ce qui pour Python est une
forme polie de dire que c’est une valeur illégale. Puis apparaît aussi des inf qui signifie plus
clairement des nombres infinis.
Revenons au cas général. Pour minimiser les erreurs d’arrondi et s’affranchir d’une situation
de pivot nul, il faut déterminer le plus grand pivot possible en valeur absolue sur la partie
de colonne considérée puis permuter les lignes. C’est la recherche partielle du pivot. Pour
commencer donnons une procédure qui donne l’indice du plus grand élément d’une liste en
valeur absolue.
I n [ 1 ] : de f indice_max_abs ( L ) :
...: " " " p r e n d en argument une l i s t e ou un t a b l e a u e t r e n v o i e
i n d i c e de p l u s g r a n d e l e m e n t de L en v a l e u r a b s o l u e " " "
...: maxi = a b s ( L [ 0 ] )
...: index = 0
...: f o r i in range ( len (L) ) :
...: i f a b s ( L [ i ] ) > maxi :
...: maxi = a b s ( L [ i ] )
...: index = i
...: return index
I n [ 2 ] : indice_max_abs ([ −1 ,2 ,3 , −4 ,1])
Out [ 2 ] :
3
Nous allons donc créer la fonction Python nommée NEW_systLin qui correspondra à la fonc-
tion systLin mais en y ajoutant la recherche du pivot le plus grand en valeur absolue sur
chaque colonne dans la descente vers un système triangulaire.
I n [ 4 1 ] : d e f NEW_systLin (A , B) :
# on f a i t d e s c o p i e s de A e t de B
A1 = np . copy (A) ; B1 = np . copy (B)
# on c o n c a t e n e e n s e m b l e A1 e t B1 d a n s D
D = np . c o n c a t e n a t e ( ( A1 , B1 ) , a x i s =1)
n = np . s i z e ( A1 , 0 ) ; p r i n t (D)
# On t r a n s f o r m e D en une m a t r i c e t r i a n g sup
p r i n t ( "On t r a n s f o r m e en s y s t e m e t r i a n g sup : " )
f o r j i n r a n g e ( n−1) :
p r i n t ( "On p a s s e a l a c o l o n n e C" , j )
i n d e x = i n d i c e _ m a x _ a b s (D[ j : n , j ] ) + j
p r i n t ( " i n d i c e l i g n e du c o e f f l e p l u s g r a n d : " , i n d e x )
D = p e r m u t l i g n e (D, j , i n d e x ) ; p r i n t (D)
f o r i i n r a n g e ( j +1,n ) :
p r i n t ( ’ l e p i v o t e s t : ’ ,D[ j , j ] )
c = D[ i , j ] /D[ j , j ]
p r i n t ( ’ on e n l e v e a l a ’ , i , ’ eme l i g n e ’ , c , ’ f o i s l a ’ , j
, ’ eme l i g n e ’ )
D = t r a n s v e c l i g n e (D, i , j ,− c )
p r i n t (D)
# on t r a n s f o r m e D ( s a u f d e r n i e r e c o l ) en m a t r i c e d i a g
p r i n t ( "On t r a n s f o r m e en s y s t e m e d i a g o n a l : " )
f o r j i n r a n g e ( n −1 ,0 , −1) :
f o r i i n r a n g e ( j −1,−1,−1) :
c = D[ i , j ] /D[ j , j ]
p r i n t ( ’ on e n l e v e a l a ’ , i , ’ eme l i g n e ’ , c , ’ f o i s l a ’ , j
, ’ eme l i g n e ’ )
D = t r a n s v e c l i g n e (D, i , j ,− c )
p r i n t (D)
# On t r a n s f o r m e l a d e r n i e r e c o l o n n e de D en m a t r i c e l i g n e
NewB1 = np . a r r a y ( [ D [ : , n ] ] ) ; p r i n t ( NewB1 )
# On d i v i s e l e s l i g n e s de NewB1 p a r l e s p i v o t s s u c c e s s i f s
f o r s in range (n) :
S o l = d i l a t c o l o n n e ( NewB1 , s , 1 . / D[ s , s ] )
# On r e t o u r n e a l o r s l e s s o l u t i o n s du s y s t e m e
return Sol
112 CHAPITRE 8
I n [ 4 0 ] : A = np . a r r a y ( [ [ 1 . , − 1 . , 0 . ] , [ − 2 . , 4 . , 1 . ] , [ 0 . , 3 . , − 5 . ] ] )
I n [ 4 1 ] : B = np . a r r a y ( [ [ 1 . ] , [ 4 . ] , [ 0 . ] ] )
I n [ 4 2 ] : NEW_systLin (A , B)
[ [ 1 . −1. 0 . 1.]
[ −2. 4 . 1 . 4.]
[ 0 . 3 . −5. 0 . ] ]
On t r a n s f o r m e en s y s t e m e t r i a n g sup :
On p a s s e a l a c o l o n n e C 0
i n d i c e l i g n e du c o e f f l e p l u s g r a n d : 1
[[ −2. 4. 1. 4.]
[ 1 . −1. 0 . 1.]
[ 0 . 3 . −5. 0 . ] ]
l e p i v o t e s t : −2.0
on e n l e v e a l a 1 eme l i g n e −0.5 f o i s l a 0 eme l i g n e
[[ −2. 4. 1. 4. ]
[ 0. 1. 0.5 3. ]
[ 0. 3 . −5. 0. ] ]
l e p i v o t e s t : −2.0
on e n l e v e a l a 2 eme l i g n e −0.0 f o i s l a 0 eme l i g n e
[[ −2. 4. 1. 4. ]
[ 0. 1. 0.5 3. ]
[ 0. 3 . −5. 0. ] ]
On p a s s e a l a c o l o n n e C 1
i n d i c e l i g n e du c o e f f l e p l u s g r a n d : 2
[[ −2. 4. 1. 4. ]
[ 0. 3 . −5. 0. ]
[ 0. 1. 0.5 3. ] ]
l e pivot est : 3.0
on e n l e v e a l a 2 eme l i g n e 0 . 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 f o i s l a 1 eme l i g n e
[[ −2. 4. 1. 4. ]
[ 0. 3. −5. 0. ]
[ 0. 0. 2.16666667 3. ]]
On t r a n s f o r m e en s y s t e m e d i a g o n a l :
on e n l e v e a l a 1 eme l i g n e −2.307692307692308 f o i s l a 2 eme l i g n e
[[ −2. 4. 1. 4. ]
[ 0. 3. 0. 6.92307692]
[ 0. 0. 2.16666667 3. ]]
on e n l e v e a l a 0 eme l i g n e 0 . 4 6 1 5 3 8 4 6 1 5 3 8 4 6 1 5 6 f o i s l a 2 eme l i g n e
[[ −2. 4. 0. 2.61538462]
[ 0. 3. 0. 6.92307692]
[ 0. 0. 2.16666667 3. ]]
on e n l e v e a l a 0 eme l i g n e 1 . 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 f o i s l a 1 eme l i g n e
[[ −2. 0. 0. −6.61538462]
[ 0. 3. 0. 6.92307692]
[ 0. 0. 2.16666667 3. ]]
[[ −6.61538462 6.92307692 3. ]]
Out [ 4 2 ] : a r r a y ( [ [ 3 . 3 0 7 6 9 2 3 1 , 2 . 3 0 7 6 9 2 3 1 , 1 . 3 8 4 6 1 5 3 8 ] ] )
# CORRECTION EXERCICE 01
I n [ 2 ] : A = np . a r r a y ( [ [ 1 , − 1 , 0 ] , [ − 2 , 4 , 1 ] , [ 0 , 3 , − 5 ] ] )
In [ 3 ] : A
Out [ 3 ] : a r r a y ( [ [ 1 , −1, 0 ] ,
[ −2 , 4 , 1 ] ,
[ 0 , 3 , −5]])
I n [ 4 ] : B = np . a r r a y ( [ [ 1 , 0 ] , [ 1 , 3 ] , [ − 1 , 2 ] ] )
In [ 1 5 ] : A[ 2 , : ] ; A[ : , 1 ] ;
Out [ 1 5 ] : a r r a y ( [ 0 , 3 , −5]) a r r a y ([ −1 , 4 , 3 ] )
In [ 2 1 ] : A[ 0 : 1 , 0 : 1 ]
Out [ 2 1 ] : a r r a y ( [ [ 1 ] ] )
In [ 2 2 ] : A[ 0 : 2 , 0 : 2 ]
Out [ 2 2 ] : a r r a y ( [ [ 1 , −1] , [ −2 , 4 ] ] )
I n [ 7 ] : C = np . c o n c a t e n a t e ( ( B , np . z e r o s ( ( 3 , 1 ) ) ) , a x i s = 1 )
In [ 8 ] : C
Out [ 8 ] : a r r a y ( [ [ 1 . , 0 . , 0.] ,
[ 1. , 3. , 0.] ,
[ −1. , 2 . , 0.]])
I n [ 1 0 ] : A+C
Out [ 1 0 ] : a r r a y ( [ [ 2 . , −1. , 0 . ] ,
[ −1. , 7 . , 1.] ,
[ −1. , 5 . , −5.]])
I n [ 1 1 ] : A . d o t (C)
Out [ 1 1 ] : a r r a y ( [ [ 0 . , −3. , 0 . ] , [ 1 . , 1 4 . , 0 . ] , [ 8 . , −1. , 0 . ] ] )
I n [ 1 2 ] : a l g . i n v (A)
Out [ 1 2 ] : a r r a y ( [ [ 1 . 7 6 9 2 3 0 7 7 , 0 . 3 8 4 6 1 5 3 8 , 0 . 0 7 6 9 2 3 0 8 ] ,
[ 0.76923077 , 0.38461538 , 0.07692308] ,
[ 0.46153846 , 0.23076923 , −0.15384615]])
I n [ 1 3 ] : a l g . i n v (C)
# CA GUEULE !
I n [ 1 4 ] : a l g . m a t r i x _ p o w e r (A , 7 )
Out [ 1 4 ] : a r r a y ( [ [ 6 9 2 9 , −14365 , 676] ,
[ −28730 , 47996 , 18421] ,
[ 4056 , 55263 , −116441]])
In [ 1 8 ] : def f ( x ) :
...: r e t u r n np . exp ( 2 ∗ x )
I n [ 2 0 ] : f (A)
Out [ 2 0 ] : a r r a y ( [ [ 7 . 3 8 9 0 5 6 1 0 e +00 , 1 . 3 5 3 3 5 2 8 3 e −01 , 1 . 0 0 0 0 0 0 0 0 e +00] ,
[ 1 . 8 3 1 5 6 3 8 9 e −02 , 2 . 9 8 0 9 5 7 9 9 e +03 , 7 . 3 8 9 0 5 6 1 0 e +00] ,
[ 1 . 0 0 0 0 0 0 0 0 e +00 , 4 . 0 3 4 2 8 7 9 3 e +02 , 4 . 5 3 9 9 9 2 9 8 e − 0 5 ] ] )
114 CHAPITRE 8
# SOLUTION EXERCICE 02
In [ 2 4 ] : A
Out [ 2 4 ] :
a r r a y ( [ [ 1 , −1, 0 ] ,
[ −2 , 4 , 1 ] ,
[ 0 , 3 , −5]])
I n [ 2 5 ] : t r a n s v e c l i g n e (A, 1 , 2 , − 1 )
Out [ 2 5 ] :
a r r a y ( [ [ 1 , −1, 0 ] ,
[ −2 , 1 , 6 ] ,
[ 0 , 3 , −5]])
In [ 2 7 ] : A
Out [ 2 7 ] :
a r r a y ( [ [ 1 , −1, 0 ] ,
[ −2 , 1 , 6 ] ,
[ 0 , 3 , −5]])
I n [ 2 8 ] : n e w _ t r a n s v e c l i g n e (A, 1 , 2 , − 1 )
Out [ 2 8 ] :
a r r a y ( [ [ 1 , −1, 0 ] ,
[ −2 , −2, 1 1 ] ,
[ 0 , 3 , −5]])
# SOLUTION EXERCICE 03
I n [ 4 2 ] : A = np . a r r a y ( [ [ 1 . , − 1 . , 3 . ] , [ 0 . , 1 . , 2 . ] , [ − 1 . , − 2 . , 0 . ] ] )
I n [ 4 3 ] : t r a n s v e c c o l o n n e (A , 1 , 0 , 1 ) , t r a n s v e c c o l o n n e (A, 2 , 0 , − 3 )
I n [ 4 4 ] : t r a n s v e c c o l o n n e (A, 2 , 1 , − 2 ) , d i l a t c o l o n n e (A, 2 , 1 / 9 )
I n [ 4 5 ] : t r a n s v e c c o l o n n e (A , 1 , 2 , 3 ) , t r a n s v e c c o l o n n e (A , 0 , 2 , 1 )
Out [ 4 5 ] :
array ([[1 ,0 ,0] ,[0 ,1 ,0] ,[0 ,0 ,1]])
# C0 <−> C1
I n [ 1 0 ] : p e r m u t l i g n e (C , 0 , 1 )
Out [ 1 0 ] : a r r a y ( [ [ 1 . , 1 . , 4 . , 0 . , 1 . , 0 . ] ,
[ 2. , 2. , 3. , 1. , 0. , 0.] ,
[ 1 . , −2. , 1 . , 0 . , 0 . , 1 . ] ] )
# L1 <− L1 − 2 L0 e t L2 <− L2 − L0
I n [ 1 1 ] : t r a n s v e c l i g n e (C, 1 , 0 , − 2 ) ; t r a n s v e c l i g n e (C, 2 , 0 , − 1 )
Out [ 1 1 ] : a r r a y ( [ [ 1 . , 1 . , 4 . , 0 . , 1 . , 0 . ] ,
[ 0 . , 0 . , −5. , 1 . , −2. , 0 . ] ,
[ 0 . , −3. , −3. , 0 . , −1. , 1 . ] ] )
# C1 <−> C2
I n [ 1 2 ] : p e r m u t l i g n e (C , 1 , 2 )
Out [ 1 2 ] : a r r a y ( [ [ 1 . , 1 . , 4 . , 0 . , 1 . , 0 . ] ,
[ 0 . , −3. , −3. , 0 . , −1. , 1 . ] ,
[ 0 . , 0 . , −5. , 1 . , −2. , 0 . ] ] )
# L1 <− −1/3 L1 e t L2 <− −1/5 L2
I n [ 1 3 ] : d i l a t l i g n e (C,1 , −1/3) ; d i l a t l i g n e (C,2 , −1/5)
Out [ 1 3 ] : a r r a y ( [ [ 1 . , 1 . , 4 . , 0 . , 1 . , 0 . ] ,
[ − 0 . , 1 . , 1 . , −0. , 0 . 3 3 3 3 3 3 3 3 , − 0 . 3 3 3 3 3 3 3 3 ] ,
[ −0. , −0. , 1 . , −0.2 , 0 . 4 , −0. ]])
# L1 <− L1 − L2 e t L0 <− L0 − 4 L2
I n [ 1 4 ] : t r a n s v e c l i g n e (C, 1 , 2 , − 1 ) ; t r a n s v e c l i g n e (C, 0 , 2 , − 4 )
Out [ 1 4 ] : a r r a y ( [ [ 1 . , 1 . , 0 . , 0 . 8 , −0.6 , 0 . ] ,
[ 0 . , 1 . , 0 . , 0 . 2 , −0.06666667 , − 0 . 3 3 3 3 3 3 3 3 ] ,
[ −0. , −0. , 1 . , −0.2 , 0 . 4 , −0. ] ] )
# L0 <− L0 − L1
I n [ 1 5 ] : t r a n s v e c l i g n e (C, 0 , 1 , − 1 )
Out [ 1 5 ] : a r r a y ( [ [ 1 . , 0 . , 0 . , 0 . 6 , −0.53333333 , 0 . 3 3 3 3 3 3 3 3 ] ,
[ 0 . , 1 . , 0 . , 0 . 2 , −0.06666667 , − 0 . 3 3 3 3 3 3 3 3 ] ,
[ −0. , −0. , 1 . , −0.2 , 0 . 4 , −0. ] ] )
116 CHAPITRE 8
# I l reste a deconcatener
In [ 1 7 ] : C[ 0 : 3 , 3 : 6 ]
Out [ 1 7 ] :
array ( [ [ 0.6 , −0.53333333 , 0 . 3 3 3 3 3 3 3 3 ] ,
[ 0.2 , −0.06666667 , − 0 . 3 3 3 3 3 3 3 3 ] ,
[ −0.2 , 0.4 , −0. ]])
# on r e m a r q u e :
I n [ 1 8 ] : −8/15 ; −1/15
Out [ 1 8 ] : −0.5333333333333333 −0.06666666666666667
# EXERCICE 05 CORRECTION
I n [ 2 3 ] : B = np . a r r a y ( [ [ 1 . ] , [ − 2 . ] , [ 3 . ] , [ 2 . ] ] )
I n [ 2 4 ] : A = np . a r r a y
([[1. ,3. ,2. , −5.] ,[1. , −4. , −2. ,6.] ,[3. ,1. , −2. ,1.] ,[ −2. ,1. , −4. ,3.]])
I n [ 2 5 ] : s y s t L i n (A , B)
[ [ 1 . 3 . 2 . −5. 1 . ]
[ 1 . −4. −2. 6 . −2.]
[ 3 . 1 . −2. 1 . 3.]
[ −2. 1 . −4. 3 . 2.]]
l e pivot est : 1.0
on e n l e v e l a 1 me l i g n e 1 . 0 f o i s l a 0 me l i g n e
[ [ 1 . 3 . 2 . −5. 1 . ]
[ 0 . −7. −4. 1 1 . −3.]
[ 3 . 1 . −2. 1 . 3.]
[ −2. 1 . −4. 3 . 2.]]
l e pivot est : 1.0
on e n l e v e l a 2 me l i g n e 3 . 0 f o i s l a 0 me l i g n e
[ [ 1 . 3 . 2 . −5. 1 . ]
[ 0 . −7. −4. 1 1 . −3.]
[ 0 . −8. −8. 1 6 . 0.]
[ −2. 1 . −4. 3 . 2.]]
l e pivot est : 1.0
on e n l e v e l a 3 me l i g n e −2.0 f o i s l a 0 me l i g n e
[ [ 1 . 3 . 2 . −5. 1 . ]
[ 0 . −7. −4. 1 1 . −3.]
[ 0 . −8. −8. 1 6 . 0.]
[ 0 . 7 . 0 . −7. 4 . ] ]
l e p i v o t e s t : −7.0
118 CHAPITRE 8
# ON TERMINE
on e n l e v e l a 0 me l i g n e nan f o i s l a 1 me l i g n e
[ [ nan nan nan nan nan ]
[ nan nan nan nan nan ]
[ nan nan nan nan i n f ]
[ 0. 0. 0. 0. −3.]]
[ [ nan nan i n f − 3 . ] ]
<i p y t h o n −i n p u t −19−620 e4523503b > : 2 1 : RuntimeWarning : d i v i d e by z e r o
encountered in double_scalars
c = D[ i , j ] /D[ j , j ]
<i p y t h o n −i n p u t −2−263 c 5 d f f a f 1 e > : 2 : RuntimeWarning : i n v a l i d v a l u e
encountered in multiply
A [ i , : ] = A [ i , : ] + x ∗A [ j , : ]
<i p y t h o n −i n p u t −19−620 e4523503b > : 2 9 : RuntimeWarning : d i v i d e by z e r o
encountered in double_scalars
S o l = d i l a t c o l o n n e ( NewB1 , s , 1 . / D[ s , s ] )
Out [ 2 5 ] : a r r a y ( [ [ nan , nan , nan , − i n f ] ] )
# EXERCICE 06 CORRECTION
I n [ 4 7 ] : A = np . a r r a y
([[1. ,3. ,2. , −5.] ,[1. , −4. , −2. ,6.] ,[3. ,1. , −2. ,1.] ,[ −2. ,1. , −4. ,3.]])
I n [ 4 8 ] : B = np . a r r a y ( [ [ 1 . ] , [ − 2 . ] , [ 3 . ] , [ 2 . ] ] )
I n [ 4 4 ] : NEW_systLin (A , B)
[ [ 1 . 3 . 2 . −5. 1 . ]
[ 1 . −4. −2. 6 . −2.]
[ 3 . 1 . −2. 1 . 3.]
[ −2. 1 . −4. 3 . 2.]]
On t r a n s f o r m e en s y s t e m e t r i a n g sup :
On p a s s e a l a c o l o n n e C 0
i n d i c e l i g n e du c o e f f l e p l u s g r a n d : 2
[ [ 3 . 1 . −2. 1 . 3.]
[ 1 . −4. −2. 6 . −2.]
[ 1 . 3 . 2 . −5. 1 . ]
[ −2. 1 . −4. 3 . 2.]]
l e pivot est : 3.0
on e n l e v e a l a 1 eme l i g n e 0 . 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 f o i s l a 0 eme l i g n e
[ [ 3. 1. −2. 1. 3. ]
[ 0. −4.33333333 −1.33333333 5 . 6 6 6 6 6 6 6 7 −3. ]
[ 1. 3. 2. −5. 1. ]
[ −2. 1. −4. 3. 2. ]]
120 CHAPITRE 8
on e n l e v e a l a 3 eme l i g n e −0.3157894736842105 f o i s l a 2 eme l i g n e
[ [ 3 . 0 0 0 0 0 0 0 0 e+00 1 . 0 0 0 0 0 0 0 0 e+00 −2.00000000 e+00 1 . 0 0 0 0 0 0 0 0 e+00
3 . 0 0 0 0 0 0 0 0 e +00]
[ 0 . 0 0 0 0 0 0 0 0 e+00 −4.33333333 e+00 −1.33333333 e+00 5 . 6 6 6 6 6 6 6 7 e+00
−3.00000000 e +00]
[ 0 . 0 0 0 0 0 0 0 0 e+00 2 . 2 2 0 4 4 6 0 5 e −16 −5.84615385 e+00 5 . 8 4 6 1 5 3 8 5 e+00
2 . 8 4 6 1 5 3 8 5 e +00]
[ 0 . 0 0 0 0 0 0 0 0 e+00 7 . 0 1 1 9 3 4 8 9 e −17 −2.22044605 e −16 6 . 6 6 1 3 3 8 1 5 e −16
−9.47368421 e − 0 1 ] ]
On t r a n s f o r m e en s y s t e m e d i a g o n a l :
on e n l e v e a l a 2 eme l i g n e 8 7 7 6 2 4 5 4 2 7 6 9 6 3 5 1 . 0 f o i s l a 3 eme l i g n e
[ [ 3 . 0 0 0 0 0 0 0 0 e+00 1 . 0 0 0 0 0 0 0 0 e+00 −2.00000000 e+00 1 . 0 0 0 0 0 0 0 0 e+00
3 . 0 0 0 0 0 0 0 0 e +00]
[ 0 . 0 0 0 0 0 0 0 0 e+00 −4.33333333 e+00 −1.33333333 e+00 5 . 6 6 6 6 6 6 6 7 e+00
−3.00000000 e +00]
[ 0 . 0 0 0 0 0 0 0 0 e+00 −6.15384615 e −01 −3.89743590 e+00 0 . 0 0 0 0 0 0 0 0 e+00
8 . 3 1 4 3 3 7 7 7 e +15]
[ 0 . 0 0 0 0 0 0 0 0 e+00 7 . 0 1 1 9 3 4 8 9 e −17 −2.22044605 e −16 6 . 6 6 1 3 3 8 1 5 e −16
−9.47368421 e − 0 1 ] ]
on e n l e v e a l a 1 eme l i g n e 8 5 0 6 7 9 9 2 9 6 1 4 4 2 7 1 . 0 f o i s l a 3 eme l i g n e
[ [ 3 . 0 0 0 0 0 0 0 0 e+00 1 . 0 0 0 0 0 0 0 0 e+00 −2.00000000 e+00 1 . 0 0 0 0 0 0 0 0 e+00
3 . 0 0 0 0 0 0 0 0 e +00]
[ 0 . 0 0 0 0 0 0 0 0 e+00 −4.92982456 e+00 5 . 5 5 5 5 5 5 5 6 e −01 0 . 0 0 0 0 0 0 0 0 e+00
8 . 0 5 9 0 7 3 0 2 e +15]
[ 0 . 0 0 0 0 0 0 0 0 e+00 −6.15384615 e −01 −3.89743590 e+00 0 . 0 0 0 0 0 0 0 0 e+00
8 . 3 1 4 3 3 7 7 7 e +15]
[ 0 . 0 0 0 0 0 0 0 0 e+00 7 . 0 1 1 9 3 4 8 9 e −17 −2.22044605 e −16 6 . 6 6 1 3 3 8 1 5 e −16
−9.47368421 e − 0 1 ] ]
on e n l e v e a l a 0 eme l i g n e 1 5 0 1 1 9 9 8 7 5 7 9 0 1 6 5 . 2 f o i s l a 3 eme l i g n e
[ [ 3 . 0 0 0 0 0 0 0 0 e+00 8 . 9 4 7 3 6 8 4 2 e −01 −1.66666667 e+00 0 . 0 0 0 0 0 0 0 0 e+00
1 . 4 2 2 1 8 9 3 6 e +15]
[ 0 . 0 0 0 0 0 0 0 0 e+00 −4.92982456 e+00 5 . 5 5 5 5 5 5 5 6 e −01 0 . 0 0 0 0 0 0 0 0 e+00
8 . 0 5 9 0 7 3 0 2 e +15]
[ 0 . 0 0 0 0 0 0 0 0 e+00 −6.15384615 e −01 −3.89743590 e+00 0 . 0 0 0 0 0 0 0 0 e+00
8 . 3 1 4 3 3 7 7 7 e +15]
[ 0 . 0 0 0 0 0 0 0 0 e+00 7 . 0 1 1 9 3 4 8 9 e −17 −2.22044605 e −16 6 . 6 6 1 3 3 8 1 5 e −16
−9.47368421 e − 0 1 ] ]
On peut interpréter ces solutions très grandes. En effet si l’on tape alg.det(A), on obtient
2.6850316841703656e-14 qui est très proche de 0 et donc le système est quasi non inversible.
122 CHAPITRE 8
ALGORITHM OF GAUSS 123