Beruflich Dokumente
Kultur Dokumente
Michel Quercia
Corrections
La version (( livre )) diusee par Vuibert comporte quelques erreurs, decouvertes
apres impression, et qui sont corrigees dans cette version electronique.
..............................................................
Cours et exercices
Chapitre
1-1
1-2
1-3
1-4
1-5
1 M
ethodes de programmation . . . . . . . . . . . . . . . . . . . . . . .
Description dun algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
It
eration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
R
ecursivit
e .................................................
Diviser pour r
egner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
9
11
14
17
20
Chapitre
2-1
2-2
2-3
2-4
2-5
2-6
2 Structure de liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
D
enitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Repr
esentation en m
emoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Parcours dune liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Recherche dun
el
ement dans une liste . . . . . . . . . . . . . . . . . . . . .
Insertion et suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
24
25
27
28
29
32
Chapitre
3-1
3-2
3-3
3-4
3-5
3-6
3-7
3-8
3 Listes tri
ees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Insertion dans une liste tri
ee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Recherche dans une liste tri
ee . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Fusion de listes tri
ees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tri dune liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tri a
bulles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tri par fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tri rapide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
34
35
37
39
41
42
46
50
Chapitre
4-1
4-2
4-3
4-4
4 Evaluation
dune formule . . . . . . . . . . . . . . . . . . . . . . . . . . .
Structure de pile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Repr
esentation lin
eaire dune formule . . . . . . . . . . . . . . . . . . . . .
Evaluation
dune formule postxe . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
53
55
56
58
Chapitre
5-1
5-2
5-3
5-4
5-5
5 Logique bool
eenne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Propositions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Circuits logiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Synth
ese des fonctions bool
eennes . . . . . . . . . . . . . . . . . . . . . . . . .
Manipulation des formules logiques . . . . . . . . . . . . . . . . . . . . . . . .
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
60
63
65
69
73
Chapitre
6-1
6-2
6-3
6-4
6 Complexit
e des algorithmes . . . . . . . . . . . . . . . . . . . . . . . .
G
en
eralit
es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Equation
de r
ecurrence T (n) = aT (n 1) + f(n) . . . . . . . . . . .
R
ecurrence diviser pour r
egner . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
76
76
79
82
84
Chapitre
7-1
7-2
7-3
7-4
7-5
7 Arbres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
D
enitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Repr
esentation en m
emoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Parcours dun arbre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
D
enombrements sur les arbres binaires . . . . . . . . . . . . . . . . . . . .
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
87
87
90
94
99
104
Chapitre
8-1
8-2
8-3
8-4
Chapitre
9-1
9-2
9-3
9-4
9-5
Chapitre
10-1
10-2
10-3
10-4
10 Langages r
eguliers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
D
enitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Op
erations sur les langages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Appartenance dun mot a
un langage r
egulier . . . . . . . . . . . . . 135
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Chapitre
11-1
11-2
11-3
11-4
11-5
11-6
11-7
Probl`
emes
Tri par distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Interpolation de Lagrange et multiplication rapide . . . . . . . . . . . . . . . . . . . .
Plus longue sous-sequence commune
...................................
Arbres de priorite equilibres
...........................................
Compilation dune expression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Recherche dune cha^ne de caracteres dans un texte . . . . . . . . . . . . . . . . . . . . .
158
159
161
163
166
167
Travaux pratiques
Chemins dans Z2
......................................................
Files dattente et suite de Hamming
...................................
Recherche de contradictions par la methode des consensus . . . . . . . . . . . . . .
Modelisation dun tableur
.............................................
Analyse syntaxique
....................................................
171
174
176
182
184
1
2
3
4
5
6
7
8
9
10
11
Methodes de programmation . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Structure de liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Listes triees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Evaluation
dune formule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Logique booleenne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Complexite des algorithmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Arbres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Arbres binaires de recherche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Manipulation dexpressions formelles . . . . . . . . . . . . . . . . . . . . .
Langages reguliers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Automates nis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
190
199
205
213
216
227
230
238
240
247
250
260
261
266
272
274
276
282
283
287
289
290
Annexes
Bibliographie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Aide memoire de caml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
295
296
300
Pr
eface
Pr
eface
ce systeme qui est actuellement utilise dans la majorite des classes preparatoires
aux grandes ecoles pour lenseignement de loption informatique. Caml-Light est
distribue gracieusement par lINRIA via son site Internet :
http://pauillac.inria.fr/caml/index-fra.html
Cours et exercices
Chapitre 1
M
ethodes de programmation
1-1
b + 00
b
0
si > 0 alors x =
,x =
2a
2a
sinon ERREUR
n
La description est nie (il ny a pas de points de suspension), elle est non ambigue
dans la mesure o
u lon sait realiser les operations mathematiques (+, , , /, )
et o
u loperation ERREUR est connue.
Le programme (en caml) :
10
M
ethodes de programmation
let degr
e_2(a,b,c) =
if a = 0.
then failwith "
equation incorrecte"
else let delta = b **. 2. -. 4. *. a *. c in
if delta >= 0.
then ((-. b +. sqrt(delta))/.(2. *. a),
(-. b -. sqrt(delta))/.(2. *. a))
else failwith "discriminant n
egatif"
;;
Les symboles +., -., *., /. et **. designent en caml les operations usuelles sur les
nombres reels : addition, soustraction, multiplication, division et exponentiation.
les operations entre nombres entiers sont notees +, -, *, / (division entiere) et mod
(reste). Il ny a pas delevation a une puissance entiere predenie en caml.
La version
suivante est un peu plus ecace car elle economise la repetition
des calculs de et de 2a :
let degr
e_2(a,b,c) =
if a = 0.
then failwith "
equation incorrecte"
else let delta = b **. 2. -. 4. *. a *. c in
if delta >= 0.
then let d = sqrt(delta) and deux_a = 2. *. a in
((d -. b)/.deux_a, (-. d -. b)/.deux_a)
else failwith "discriminant n
egatif"
;;
1-2 It
eration
11
1-2
It
eration
Lit
eration consiste a repeter plusieurs fois un sous-algorithme. Le nombre
de repetitions peut ^etre deni lors de la redaction de lalgorithme, mais on peut
aussi indiquer a quelle condition literation doit se poursuivre ou non. Dans ce
cas il est necessaire de sassurer que la condition darr^et sera remplie au bout
dun nombre ni de tours de boucle pour garantir que lalgorithme comporte un
nombre ni detapes (condition de terminaison).
Exemple, calcul de xn :
(* calcule x^n pour x et n entiers, n >= 1 *)
let puissance(x,n) =
let p = ref x in
for i = 2 to n do p := !p * x done;
!p
;;
p = ref x signie que p fait r
ef
erence a un nombre entier variable et valant initialement x. Ce nombre est designe par !p dans la suite de la fonction puissance
et linstruction p := !p * x a pour eet de modier la valeur de lentier auquel
p fait r
eference. En langage machine on dit que p est un pointeur vers une zone
memoire et que cette zone memoire doit ^etre interpretee comme la representation
machine dun nombre entier.
M
ethodes de programmation
12
1-2 It
eration
13
ce qui denit f comme une fonction a un argument de sorte que f(x) equivaut a
valeur p x. On peut ainsi ne pas sp
ecier le polyn^
ome p a chaque calcul si lon
doit en faire plusieurs avec le m^eme polyn^
ome.
Demontrons que cet algorithme calcule eectivement le nombre P(x) : pour
cela on montre par recurrence sur k que, a lentree dans la boucle, on a les relations :
()
!xk = xk1,
et a la sortie :
()
!xk = xk ,
!vk = a0 + a1 x + . .. + ak xk
M
ethodes de programmation
14
1-3
R
ecursivit
e
R
ecursivit
e simple
Un algorithme est dit r
ecursif lorsquil intervient dans sa description, cesta-dire lorsquil est deni en fonction de lui m^eme. Tres souvent un algorithme
recursif est lie a une relation de recurrence permettant de calculer la valeur dune
fonction pour un argument n a laide des valeurs de cette fonction pour des arguments inferieurs a n. Reprenons lexemple du calcul de xn vu precedemment ; on
peut denir xn par recurrence a partir des relations :
x0 = 1,
xn = x xn1 si n > 1.
ou plus elegamment :
let rec puissance(x,n) = match n with
| 0 -> 1
| _ -> x * puissance(x,n-1)
;;
1-3 R
ecursivit
e
15
par if n <= 0. Dans ce cas lalgorithme ne boucle plus mais il ne fournit pas pour
autant un resultat correct lorsque n < 0.
Les fonctions veriant une relation de recurrence de la forme :
f(0) = f0 ,
se pr^etent aussi facilement a un codage iteratif que recursif. Les performances des
programmes correspondants sont generalement comparables en termes de temps
dexecution, mais une programmation recursive produit autant de calculs en suspens que le nombre detapes necessaires pour arriver au cas de base, cest-
a-dire n
dans cet exemple. La quantite de memoire necessaire pour executer lalgorithme
recursif est donc proportionnelle a n ce qui peut ^etre g^enant si n est grand, alors
quelle est constante pour lalgorithme iteratif.
R
ecursivit
e double
(* calcule le coefficient du bin^
ome C(n,p), n >= p >= 0 *)
let rec binome(n,p) =
if p = 0 or p = n then 1
else binome(n-1,p) + binome(n-1,p-1)
;;
Lalgorithme de calcul de Cp
eduit la relation de Pascal avec deux cas
n est d
de base regroupes : C0n = Cn
=
1.
Montrons
que cet algorithme termine et fournit
n
le resultat correct dans tous les cas o
un>p>0:
{ On remarque dabord que si 0 < p < n alors 0 < p 6 n1 et 0 6 p1 < n1
donc si le cas de base nest pas atteint les deux appels recursifs de binome ont
des arguments convenables.
{ Ensuite, on demontre par recurrence sur n la propriete suivante :
si 0 6 p 6 n alors binome(n, p) termine et retourne le coecient Cp
n.
Cest evident si n = 0 puisqualors p = 0, et si cest vrai pour un entier n 1
alors ca lest aussi pour n car pour p = 0 ou p = n on obtient le resultat
correct Cp
n = 1, et si 0 < p < n alors la formule :
binome(n-1,p) + binome(n-1,p-1)
M
ethodes de programmation
16
trace "binome";; binome(5,3);;
The function binome is now traced.
- : unit = ()
#binome <-- 5, 3
binome <-- 4, 2
binome <-- 3, 1
binome <-- 2, 0
binome --> 1
binome <-- 2, 1
binome <-- 1, 0
binome --> 1
binome <-- 1, 1
binome --> 1
binome --> 2
binome --> 3
binome <-- 3, 2
binome <-- 2, 1
binome <-- 1, 0
binome --> 1
binome <-- 1, 1
binome --> 1
binome --> 2
binome <-- 2,
binome --> 1
binome --> 3
binome --> 6
binome <-- 4,
binome <-- 3,
binome <-- 2,
binome <-- 1,
binome --> 1
binome <-- 1,
binome --> 1
binome --> 2
binome <-- 2,
binome --> 1
binome --> 3
binome <-- 3,
binome --> 1
binome --> 4
binome --> 10
- : int = 10
3
2
1
0
1
Figure 1 : calcul r
ecursif de Cp
n
fois... Tout se passe comme si la machine navait (( aucune memoire )) et refaisait
sans cesse les m^emes calculs, ce qui est eectivement le cas car le programme
nindique pas quil faut memoriser les calculs intermediaires. La programmation
ecace dune fonction doublement recursive necessite de coder la memorisation des
valeurs devant servir plusieurs fois, par exemple dans un vecteur. Lexercice 1-7
propose une meilleure programmation du calcul de Cp
n.
R
ecursivit
e mutuelle
Deux algorithmes sont dits mutuellement r
ecursifs lorsque chacun des deux
fait appel a lautre. Par exemple :
let rec pair(x) = match x with
| 0 -> true
| _ -> impair(x-1)
and impair(x) = match x with
| 0 -> false
| _ -> pair(x-1)
;;
1-4
17
Diviser pour r
egner
x1 = 1,
x2k = (xk )2 ,
x2k+1 = x x2k.
Ici n = 2k ou 2k + 1 et n0 = k n/2.
let rec
| 0 ->
| 1 ->
| _ ->
;;
La dierence entre puissance telle quelle est denie en 1-2 ou en 1-3 et puiss_2
se fait sentir des que n depasse la dizaine :
puissance(x,10) -> x x x x x x x x x x : 9 multiplications
puiss_2(x,10) -> (x (x2 )2 )2 :
4 multiplications
puiss_2(x,100) -> ((x (((x x2 )2)2 )2 )2 )2 :
8 multiplications
M
ethodes de programmation
18
*)
*)
*)
Le temps dexecution de ce programme est (p + 1)(q + 1) multiplications (( elementaires )) et autant dadditions, soit de lordre de 2n2 operations pour deux
polyn^
omes de degre n. Un algorithme de type (( diviser pour regner )) a ete presente par Knuth en 1969 : on suppose que les polyn^
omes P et Q sont de degres
au plus n 1, on note k = bn/2c, ` = n k = dn/2e o
u buc et due designent les
parties entieres inferieure et superieure dun reel u, et on decompose les polyn^
omes
P et Q de la maniere suivante :
P(x) = (a0 + .. . + ak1 xk1) + xk (ak + .. . + an1x`1) = P0 + xk P1 ;
Q(x) = (b0 + .. . + bk1 xk1) + xk (bk + . .. + bn1 x`1) = Q0 + xk Q1 .
On a alors :
R(x) = (P0 + xk P1)(Q0 + xk Q1 )
= P0 Q0 + xk (P0Q1 + P1 Q0 ) + x2kP1 Q1
= P0 Q0 + xk ((P0 + P1 )(Q0 + Q1 ) P0Q0 P1 Q1 ) + x2k P1Q1 .
Cette formule fait appara^tre trois multiplications de polyn^
omes de degre au plus
k 1, ou ` 1, deux additions de polyn^
omes de degre au plus ` 1 et trois
additions de polyn^
omes de degre au plus 2` 2 (le calcul de P0 Q0 + x2kP1 Q1 peut
^etre eectue sans addition). Elle est implementee dans le programme suivant :
(* multiplication de Knuth des polyn^
omes p et q
(* on suppose que p et q ont m^
eme longueur n
let rec mult_Knuth p q n =
let r = make_vect (2*n-1) 0 in (* r
esultat <- 0
(* cas de base : p et q sont constants
if n = 1 then r.(0) <- p.(0) * q.(0)
*)
*)
*)
*)
p0
p1
q0
q1
=
=
=
=
sub_vect
sub_vect
sub_vect
sub_vect
19
p
p
q
q
0
k
0
k
k
l
k
l in
(* d
ecoupe p,q en 2 *)
0 (* calcule p0+p1,q0+q1 *)
0 in
p1.(i);
q1.(i)
let r0 = mult_Knuth p0 q0 k
and r1 = mult_Knuth p01 q01 l
and r2 = mult_Knuth p1 q1 l in
(* assemble les produits *)
for i = 0 to 2*k-2 do r.(i)
for i = 0 to 2*l-2 do r.(i+2*k)
for i = 0 to 2*k-2 do
r.(i+k) <- r.(i+k) + r1.(i) done;
for i = 2*k-1 to 2*l-2 do
r.(i+k) <- r.(i+k) + r1.(i) done;
end;
r
;;
(* r
ecursion *)
r2.(i)
M
ethodes de programmation
20
n
produit
mult Knuth
produit
mult Knuth
1
1
0
1
1
2 4
8 16
32
64
128
256
o
4 16 64 256 1024 4096 16384 65536
additions
5 28 113 400 1325 4228 13193 40600
o
4 16 64 256 1024 4096 16384 65536
multiplications
3 9 27 81 243 729 2187 6561
1-5
Exercices
Ecrire
un algorithme ou un programme caml permettant de classer trois nombres
en eectuant le moins possible de comparaisons.
Exercice 1-2 : nombres parfaits
Un nombre entier n > 2 est dit parfait sil est egal a la somme de tous ses diviseurs
1-5 Exercices
21
An
sens uniques : %
M
ethodes de programmation
22
;;
Ecrire
un programme it
eratif calculant xn en temps logarithmique par rapport
a n (on suppose ici que le temps dune multiplication est constant).
Exercice 1-11 : exponentiation optimale
Quel est le nombre minimal de multiplications necessaires pour calculer x15 ?
Exercice 1-12 : suite de Fibonacci
La suite de Fibonacci est denie par les relations :
F0 = F1 = 1,
1. Ecrire
un programme recursif calculant Fn pour n > 0.
2. Pour ameliorer le temps dexecution, ecrire un programme recursif calculant
le couple (Fn1, Fn).
3. Demontrer la relation : n, p > 1, Fn+p = FnFp + Fn1Fp1.
4. En deduire un programme de calcul de Fn selon la methode (( diviser pour
regner )).
Exercice 1-13 : une fonction myst
erieuse
let rec
if x
else
else
;;
f(x) =
<= 1 then 1
if x mod 2 = 0 then 2*f(x/2)
1 + f(x+1)
1-5 Exercices
23
1. Ecrire
un programme iteratif calculant ppcm(a0 , . .., an1). Les nombres ai
seront places dans un vecteur transmis en argument a ce programme.
2. Ecrire
de m^eme un programme utilisant la methode (( diviser pour regner ))
et comparer les performances de ces deux programmes.
Exercice 1-15 : multiplication rapide
La multiplication de Karatsuba est construite sur lapplication recursive de la
decomposition du produit (a0 + a1 x)(b0 + b1 x) en trois multiplications :
(a0 + a1 x)(b0 + b1 x) = a0 b0 + ((a0 + a1 )(b0 + b1 ) a0 b0 a1 b1 )x + a1 b1 x2 .
Chercher un algorithme permettant de calculer (a0 + a1 x + a2 x2)(b0 + b1 x + b2 x2)
en cinq multiplications et en deduire un algorithme de multiplication polynomiale
asymptotiquement plus rapide que celui de Karatsuba. Indication : le polyn^
ome
a calculer est de degre au plus 4, donc il peut ^etre deduit de la connaissance de
ses valeurs en 5 points distincts.
Chapitre 2
Structure de liste
2-1
D
efinitions
2-2 Repr
esentation en m
emoire
25
Op
erations usuelles sur les listes
{ Creation et initialisation dune liste.
{ Parcours dune liste pour eectuer un m^eme traitement sur chaque element.
Par exemple imprimer lelement.
{ Recherche dun element particulier dans une liste : cet element est specie
par son indice ou une partie de sa valeur. Par exemple dans la liste des eleves
de la classe on peut chercher le troisieme dans lordre alphabetique, ou celui
dont le nom commence par MARTIN. On peut aussi chercher leleve ayant la
plus forte moyenne generale. Lorsque plusieurs elements de la liste verient
le critere de recherche, on peut les chercher tous ou seulement le premier ou
le dernier.
{ Insertion dun nouvel element : en debut, en n ou au milieu dune liste. Si
la liste ne doit pas contenir de repetition alors linsertion peut ^etre precedee
dune recherche de lelement a inserer pour sassurer quil nest pas dej
a
present dans la liste.
{ Permutation des elements dune liste pour respecter un nouvel ordre de
classement. Par exemple trier les eleves de la classe par moyenne decroissante.
{ Concatenation ou fusion de deux listes L1 et L2 : la concatenation produit
une liste L constituee de tous les elements de L1 puis tous les elements de
L2 ; la fusion produit une liste L0 constituee de tous les elements de L1 et de
L2 classes suivant un certain ordre. Pour la fusion on suppose que L1 et L2
sont dej
a triees suivant lordre choisi.
2-2
Repr
esentation en m
emoire
denit A, B, C, D comme etant des listes a deux elements entiers et L comme etant
une liste de quatre elements couples dentiers. Les listes denies de cette maniere
sont appelees (( n-uplets )) o
u n est la longueur de la liste ; elles sont essentiellement
utilisees pour grouper plusieurs objets participant a un m^eme traitement, par
exemple les deux coordonnees dun point dans un programme de dessin. Les
26
Structure de liste
elements dun n-uplet ne sont pas necessairement de m^eme type. Lacces aux
elements dun n-uplet se fait en indiquant leur position :
let (_,_,x,_) = L in ...
(( consecutivement ))
declare une variable V de type vecteur reel dont les elements sont V.(0) = 1.0,
V.(1) = 2.0, V.(2) = 3.0 et V.(3) = 4.0. La longueur de V est vect length(V) = 4.
En memoire V est represente par un bloc de 5 cellules consecutives :
4
1.0
2.0
3.0
4.0
V.(0)
V.(1)
V.(2)
V.(3)
La premiere cellule contient la longueur du vecteur, les cellules suivantes contiennent les elements places par indice croissant. La longueur dun vecteur nest pas
modiable mais chaque element peut ^etre modie (( sur place )), cest-
a-dire sans
avoir a construire un nouveau vecteur.
Les vecteurs permettent donc de representer des listes de longueur constante,
mais on peut aussi les utiliser pour representer des listes de longueur variable en
ne (( remplissant )) que le debut du vecteur et en conservant dans une variable a
part le nombre delements eectivement presents.
Repr
esentation par une liste chan
ee
Une liste cha^nee est une liste dobjets de m^eme type ranges en memoire
de maniere non necessairement consecutive. A chaque element de la liste autre
que le dernier est associe un pointeur qui contient ladresse memoire de lelement
suivant ; au dernier element est associe un pointeur special marquant la n de la
liste.
let L = [ 3; 1; 4; 1 ];;
hd L
}|
3
objet
pointeur
tl L
}|
27
L
L
L
L
L
=
=
=
=
=
[
3
3
3
3
3;
::
::
::
::
1; 4; 1 ];;
[ 1; 4; 1 ];;
1 :: [ 4; 1 ];;
1 :: 4 :: [ 1 ];;
1 :: 4 :: 1 :: [];;
mais : let M = [ 3; 1 ] :: [ 4; 1 ] est interpretee comme la demande de creation de la liste : [ [ 3; 1 ]; 4; 1 ] ce qui provoque une erreur de typage (liste
heterogene).
2-3
28
Structure de liste
2-4
Recherche dun
el
ement dans une liste
Recherche dun
el
ement par son rang
Etant
donnes une liste L et un entier i on veut conna^tre le i eme element
de L. Cette situation se presente par exemple lorsque L est une table de valeurs
dune fonction f denie sur les entiers de [[1, n]] : lelement cherche est alors la
valeur f(i).
(* recherche dans un vecteur *)
let cherche_vect v i =
if (i <= 0) or (i > vect_length(v))
then failwith "rang incorrect"
else v.(i-1)
;;
(* recherche dans une liste *)
let rec cherche_liste l i =
if (i <= 0) or (l = []) then failwith "rang incorrect"
else if i = 1
then hd l
else cherche_liste (tl l) (i-1)
;;
Etant
donne une liste L on veut savoir sil existe un ou plusieurs elements
de L veriant une certaine propriete et eventuellement conna^tre ces elements.
Considerons par exemple le travail dun compilateur analysant un texte source. Il
tient a jour la liste des identicateurs dej
a declares, et doit acceder a cette liste :
{ lors de la declaration dun nouvel identicateur pour determiner sil ny a
pas double declaration ;
{ lors de la compilation dune expression faisant intervenir une variable pour
verier que cette variable a ete declaree et determiner son type, sa taille et
son adresse en memoire.
Dans cet exemple la propriete a verier est legalite du nom de lidenticateur
avec le nom analyse. En principe lidenticateur cherche gure au plus une fois
dans la liste des identicateurs declares, mais il peut ^etre present plusieurs fois si
le compilateur supporte la notion de port
ee locale des identicateurs, auquel cas
la recherche doit retourner lidenticateur le plus recemment declare ayant le nom
29
analyse. On peut supposer que la liste des identicateurs est organisee de sorte
que les declarations les plus recentes gurent en debut de liste, donc la recherche
doit sarr^eter sur le premier element convenant en partant du debut de la liste.
(* Recherche si le vecteur v contient un objet convenant, et
(* renvoie le premier objet convenant sil existe, sinon
(* d
eclenche lexception "non trouv
e".
(* "convient" est une fonction bool
eenne disant si un objet
(* convient.
let cherche_vect convient v =
let i = ref 0 in
while (!i < vect_length(v)) & not(convient(v.(!i))) do
i := !i+1
done;
if !i < vect_length(v) then v.(!i)
else failwith "non trouv
e"
;;
*)
*)
*)
*)
*)
2-5
Insertion et suppression
Inserer un objet x dans une liste L = (a0 , .. ., an1) consiste a construire une
nouvelle liste L0 contenant lobjet x et tous les elements de L. Il existe plusieurs
types dinsertion :
{ insertion en debut de liste :
L0 = (x, a0 , .. ., an1) ;
{ insertion en n de liste :
L0 = (a0 , .. ., an1, x) ;
{ insertion apres le i-eme element : L0 = (a0 , .. ., ai1, x, ai, . . ., an1).
La suppression dun objet est loperation inverse. Lorsque lordre de classement des elements dans L est sans importance on choisit generalement linsertion
et la suppression en debut ou en n de liste car ces positions sont les plus accessibles. Par contre si L est une liste triee et si lon veut que L0 soit aussi triee, alors
il faut chercher dans L deux elements consecutifs encadrant x et linserer entre ces
30
Structure de liste
elements. La suppression dans une liste triee, quant a elle, ne modie pas le caractere trie. Par ailleurs si L ne doit pas comporter de repetitions il faut sassurer
que x
/ L avant de proceder a une insertion, en employant lune des methodes de
recherche vues precedemment.
Insertion et suppression a
` une extr
emit
e de la liste
let ins`
ere_d
ebut_vect v x =
let n = vect_length(v)
in
let w = make_vect (n+1) x in
for i = 0 to n-1 do w.(i+1) <- v.(i) done;
w
;;
let supprime_d
ebut_vect v =
let n = vect_length(v) in
if n = 0 then failwith "vecteur vide"
else if n = 1 then [||]
else begin
let w = make_vect (n-1) v.(1) in
for i = 2 to n-1 do w.(i-1) <- v.(i) done;
w
end
;;
(* ins`
ere_fin_vect et supprime_fin_vect sont analogues *)
let ins`
ere_d
ebut_liste l x = x :: l;;
let supprime_d
ebut_liste l = match l with
| []
-> failwith "liste vide"
| _::suite -> suite
;;
let rec ins`
ere_fin_liste l x = match l with
| []
-> [x]
| a::suite -> a :: (ins`
ere_fin_liste suite x)
;;
let rec supprime_fin_liste l = match l with
| []
-> failwith "liste vide"
| [_]
-> []
| a::suite -> a :: (supprime_fin_liste suite)
;;
31
32
Structure de liste
2-6
Exercices
Ecrire
une fonction maximum qui renvoie le plus grand element dun vecteur entier.
M^eme question avec une liste cha^nee.
Exercice 2-2 : it
eration sur une liste
La fonctionnelle caml standard do_list prend en argument une fonction f et une
liste l = [a0; . ..; an1] et calcule dans cet ordre les expressions f(a0 ), f(a1 ), .. . ,
sans utiliser de deuxieme vecteur, le vecteur initial etant alors perdu. Ecrire
un programme realisant une telle rotation.
3. Le professeur Tournesol a presente le programme suivant :
let rotation v k =
(* fait tourner v de k positions vers la gauche *)
let n = vect_length v
and compte = ref 0
and i0 = ref 0 in
while !compte < n do
let temp = v.(!i0)
and i = ref !i0
and j = ref((!i0 + k) mod n) in
while !j <> !i0 do
v.(!i) <- v.(!j);
i := !j;
j := (!i + k) mod n;
compte := !compte + 1
done;
v.(!i) <- temp;
2-6 Exercices
33
compte := !compte + 1;
i0 := !i0 + 1
done
;;
Malheureusement, il a oublie de rediger les commentaires permettant de comprendre son programme. Pourriez vous laider ? Indication : le faire tourner
a
la main sur quelques exemples, etudier le cas particulier o
u k est un diviseur de n, puis le cas general. Voyez vous un inter^et a ce programme ?
Exercice 2-5 : recherche dun
el
ement dans une liste
Un pr
edicat est une fonction retournant un resultat booleen, true si le ou les ar
guments passes verient un certain critere, false sinon. Etant
donnes un predicat
fa
un argument et une liste cha^nee l on veut determiner si l contient au moins
un element satisfaisant le critere deni par f, et le cas echeant retourner le dernier
cest-
a-dire sil existe i tel que B = (ai , . .., ai+p1 ). Ecrire
des fonctions caml
cherche_sous_liste et cherche_sous_vect qui r
epondent a cette question pour des
listes cha^nees ou pour des vecteurs et renvoient le rang de la premiere apparition
de B dans A sil y en a une.
Exercice 2-7 : listes a
` double entr
ee
Une liste a double entree est une structure de donnees permettant de representer
une liste L = (a0 , . . ., an1) et deectuer en temps constant les operations dinsertion en t^ete et en queue et lextraction du premier ou du dernier element de la
liste. Les listes a double entree ne sont pas predenies en caml mais elles peuvent
^etre implementees par des vecteurs circulaires cest-
a-dire des vecteurs dont les
deux extremites sont conceptuellement (( reliees )). Une liste occupe un segment
de ce vecteur deni par son indice de debut et son indice de n, ou mieux, par
son indice de debut et sa longueur eective (on peut ainsi distinguer une liste vide
dune liste pleine).
...... .......... ........
...... .......... ........
......
..... ....... ......
partie occupee
}|
lg
d
ebut
partie occupee
z }| {
fin
......
..... ............. .......... ..
.... .......... ........ ..
.. ..... .... .
fin
partie occupee
}|
lg
d
ebut
Chapitre 3
Listes tri
ees
3-1
Soit L une liste triee par ordre croissant pour une relation de comparaison 4.
On veut inserer un objet x (( a la bonne place )) dans L pour que la nouvelle liste
soit encore triee. Lidee est de chercher x dans L pour determiner a quelle place il
doit ^etre insere, puis de proceder a linsertion. On suppose disposer dune fonction
compare telle que compare a b renvoie lun des r
esultats PLUSGRAND lorsque a b,
PLUSPETIT lorsque a b et EQUIV lorsque a b o
u PLUSGRAND, PLUSPETIT et EQUIV
sont des constantes symboliques introduites par la denition suivante :
35
(* r
esultat dune comparaison *)
type cmp_res = PLUSGRAND | PLUSPETIT | EQUIV;;
(* insertion dans un vecteur tri
e *)
let ins`
ere_vect compare v x =
let n = vect_length(v)
in
let w = make_vect (n+1) x in
(* recopie les e
l
ements de v inf
erieurs a
` x *)
let i = ref(0) in
while (!i < n) & (compare v.(!i) x = PLUSPETIT) do
w.(!i) <- v.(!i);
i := !i + 1
done;
(* recopie la fin de v (x est d
ej`
a en place) *)
while !i < n do
w.(!i+1) <- v.(!i);
i := !i + 1
done;
w
;;
(* insertion dans une liste cha^
n
ee tri
ee *)
let rec ins`
ere_liste compare l x = match l with
| []
-> [x]
| a::suite -> match compare a x with
| PLUSPETIT -> a :: (ins`
ere_liste compare suite x)
| _
-> x :: l
;;
3-2
Considerons le probleme de la recherche dun objet x dans une liste L triee par
valeurs croissantes pour une relation dordre total 4. Lalgorithme de recherche
vu au chapitre precedent peut ^etre modie pour interrompre la recherche des que
lon rencontre un element ai de L tel que ai x. En eet dans ce cas x ne peut
pas gurer dans L apres ai puisque L est triee par valeurs croissantes, donc on
est s^
ur que x
/ L. Cette amelioration ne diminue que le temps des recherches
infructueuses : pour une liste aleatoire de longueur n, le temps moyen dune
recherche infructueuse passe de n comparaisons pour une liste quelconque a n/2
Listes tri
ees
36
comparaisons pour une liste triee. Une autre amelioration consiste a rechercher
x dans L par dichotomie : on divise L = (a0 , . .., an1) en deux sous-listes
L1 = (a0 , . . ., ai1), L2 = (ai+1 , .. ., an1) separees par un element ai puis on
compare x a ai :
{ si ai x, soit x
/ L, soit x L2 ;
{ si ai x, soit x
/ L, soit x L1 ;
{ si ai x, alors x L et on la trouve.
Dans les deux premiers cas on itere la methode de dichotomie a la sous-liste L1 ou
L2 qui a ete determinee.
(* Recherche si lobjet x figure dans le vecteur tri
e v.
(* Si oui, renvoie un indice de x dans v,
(* sinon l`
eve lexception "non trouv
e".
(* "compare" est la fonction d
efinissant la relation dordre.
let dichotomie compare v x =
let a = ref 0
and b = ref (vect_length(v)-1)
and trouv
e = ref false in
*)
*)
*)
*)
37
b (c + 1) = (b a 1)/2 < b a.
{ Quand la boucle est terminee, si trouve vaut true alors x a ete trouve
(troisieme cas du match) et son indice est a tandis que si trouve vaut false
alors on a a > b donc il nexiste aucun element de v dindice compris entre
a et b dans cet ordre et en particulier x
/ v.
Remarque : si v comporte plusieurs elements egaux a x alors dichotomie en trouve
un, mais on ne sait pas si cest le premier, le dernier ou un autre.
Temps dex
ecution : notons n la longueur de v et ak , bk les valeurs de a, b
au debut de la keme iteration de la boucle while : on a b1 a1 + 1 = n et tant
que la boucle continue : bk+1 ak+1 + 1 6 (bk ak + 1)/2 dapres les calculs
precedents. Donc par recurrence on a bk ak + 1 6 n/2k1 sil y a au moins
k iterations, mais bk ak + 1 > 1 donc 2k1 6 n cest-
a-dire k 6 log2(n) + 1.
Ainsi, le nombre de comparaisons eectuees, qui est egal au nombre diterations,
est au plus egal a blog 2(n) + 1c que x appartienne a v ou non. Ce minorant est
dailleurs atteint si x est strictement plus grand que le dernier element de v car
on a alors par recurrence ak = b(n + 1)(1 21k)c et bk = n 1 au debut de la
keme iteration, donc ak 6 bn 1/nc = bk tant que 2k1 6 n.
Lorsque n est grand on a log2 (n) + 1 = o(n) donc la methode de recherche
dichotomique est bien plus ecace que la recherche dans une liste non triee. Voici
par exemple quelques valeurs du nombre maximal de comparaisons eectuees en
fonction de n :
n
blog2 (n) + 1c
3-3
Etant
donnees deux listes L1 = (a0 , . .., an1) et L2 = (b0 , .. ., bp1 ) dobjets
de m^eme type triees par ordre croissant pour une relation de comparaison 4, on
veut constituer la liste L formee de tous les elements de L1 et L2 , triee elle aussi
par ordre croissant. Loperation passant de (L1 , L2) a L est appelee fusion de L1
et L2 dans L. La fusion appara^t dans certains algorithmes de tri, mais aussi dans
le cas de mise a jour de chiers tries : par exemple on peut vouloir fusionner les
listes des eleves de deux classes pour obtenir la liste de tous les eleves de ces deux
classes.
Listes tri
ees
38
(* indice de v1 *)
(* indice de v2 *)
(* indice de v *)
Preuve du programme
On demontre par une recurrence immediate la propriete :
a
lentr
ee de la premi
ere boucle while, les
el
ements v1.(0 .. !i 1) et
v2.(0 .. !j 1) sont les !k plus petits
el
ements de v1 v2 et ont
et
e plac
es
dans le bon ordre dans v.(0 .. !k 1).
La boucle sarr^ete quand !i > vect length(v1) ou !j > vect length(v2) ce
qui se produit en un nombre ni detapes car lune des quantites !i ou !j augmente
dune unite a chaque iteration. A la n de la boucle un au moins des vecteurs v1
ou v2 a ete transfere entierement dans v (et un seulement si v1 et v2 ne sont pas
initialement vides, car la boucle ne place dans v quun seul element a la fois). Les
deux boucles while suivantes recopient sil y a lieu la n de lautre vecteur a la n
de v (au plus une de ces deux boucles est eectivement executee).
39
Temps dex
ecution
La premiere boucle while eectue une comparaison entre un objet de v1 et
un objet de v2 a chaque fois quelle place un objet dans v. Les deux autres boucles
neectuant pas de comparaisons, le nombre total de comparaisons eectuees,
Ncomp, verie :
min(`1 , `2) 6 Ncomp 6 `1 + `2 1
o
u `1 et `2 designent les longueurs des vecteurs v1 et v2 . Ces deux bornes peuvent
^etre atteintes : Ncomp = min(`1 , `2) lorsque le plus court des deux vecteurs vient
entierement avant lautre dans v, et Ncomp = `1 + `2 1 lorsque le dernier element
dun vecteur est strictement compris entre les deux derniers elements de lautre.
Nombre de transferts : un transfert est la copie dun objet dun vecteur dans un
autre. Comme chaque element de v est place par un seul transfert, le nombre total
de transferts eectues est Ntransf = `1 + `2 .
Le temps dexecution dune iteration de la premiere boucle while est la somme
des temps dune comparaison, dun transfert et de la gestion des variables i, j, k.
En caml le temps dun transfert est constant puisque le transfert se resume a
une copie de pointeur. Ainsi, en supposant que compare a un temps dexecution
borne, on voit que le temps de fusion de deux vecteurs de longueurs `1 et `2 est
O(`1 + `2 ).
Fusion de listes chan
ees
(* fusionne les listes l1 et l2.
*)
(* "compare" est la fonction de comparaison. *)
let rec fusion_liste compare l1 l2 = match (l1,l2) with
| ([], _) -> l2
| (_, []) -> l1
| ((a::suite1),(b::suite2)) -> match compare a b with
| PLUSGRAND -> b :: (fusion_liste compare l1 suite2)
| _
-> a :: (fusion_liste compare suite1 l2)
;;
3-4
Listes tri
ees
40
bulles
3-5 Tri a
3-5
41
Tri `
a bulles
On parcourt la liste a trier en examinant si chaque couple delements consecutifs, (ai , ai+1 ), est dans le bon ordre (ai 4 ai+1 ) ou est mal classe (ai ai+1 ).
Dans ce dernier cas on echange les elements du couple et le processus est repete
tant quil reste des couples mal classes.
(* trie le vecteur v par ordre croissant *)
(* compare est la fonction de comparaison *)
let tri_bulles compare v =
let fini = ref false in
while not !fini do
fini := true;
(* esp
erons *)
for i = 0 to vect_length(v)-2 do
if (compare v.(i) v.(i+1)) = PLUSGRAND
then begin
(* un couple est mal class
e, e
change les e
l
ements *)
let x = v.(i) in
v.(i)
<- v.(i+1);
v.(i+1) <- x;
fini := false
(* il faut refaire une passe *)
end
done (* for i *)
done
;;
Preuve de lalgorithme : notons Ninv le nombre de couples (i, j) tels que i < j
et ai aj (Ninv est le nombre dinversions du vecteur v) et examinons une
iteration de la boucle while :
{ sil existe un indice i tel que ai ai+1 alors ces elements sont echanges et
fini est mis a
false donc le nombre dinversions diminue dune unite et le
test de n de boucle sera negatif ;
{ si pour tout i on a ai 4 ai+1 alors v est trie et fini garde la valeur true tout
au long de la boucle, donc cette iteration est la derniere.
Donc lalgorithme ne sarr^ete que lorsque le vecteur est trie, et il sarr^ete necessairement puisque Ninv diminue strictement a chaque iteration tant que le vecteur
nest pas trie.
On peut prouver larr^et dune autre maniere en veriant par recurrence que,
a la n de la keme iteration de la boucle while, les k derniers elements de v
sont les k elements les plus grands et sont places dans lordre croissant. Il en
resulte que le nombre diterations est majore par la longueur de v. Par ailleurs,
Listes tri
ees
42
3-6
On divise la liste L = (a0 , .. ., an1) que lon veut trier en deux demi listes,
L1 = (a0 , . . ., ap1) et L2 = (ap , .. ., an1) que lon trie separement recursivement,
puis on fusionne les deux listes triees obtenues L01 et L02.
Tri par fusion pour un vecteur
(* fusionne les sous-vecteurs tri
es v1(a..c) et v1(c+1..b) *)
(* dans v2(a..b). On suppose a <= c < b.
*)
let fusion compare v1 v2 a c b =
...
(* adapter ici le code de fusion_vect donn
e en section 3-3 *)
;;
(* Trie par ordre croissant v1(a..b) a
` laide du vecteur *)
(* auxiliaire v2. Si vers_v1 = true, le r
esultat est plac
e *)
(* dans v1(a..b), sinon dans v2(a..b). On suppose a <= b. *)
let rec tri_partiel compare v1 v2 a b vers_v1 =
if a < b then begin
let c = (a+b)/2 in
tri_partiel compare v1 v2
a
c (not vers_v1);
tri_partiel compare v1 v2 (c+1) b (not vers_v1);
43
et
n dn/2e = bn/2c.
Ces longueurs sont strictement inferieures a n car n > 2, donc, dapres lhypothese
de recurrence, les appels recursifs trient v1(a .. c) et v1 (c + 1 .. b) en placant le
resultat dans v2 ou dans v1 selon que vers v1 = true ou vers v1 = false. La
fusion les deux sous-vecteurs obtenus fournit alors le resultat attendu : un sousvecteur trie et place dans le vecteur designe par lindicateur vers_v1. Ceci acheve
la demonstration de validite.
Temps dex
ecution. Le temps necessaire pour trier un vecteur v est de la forme :
T = Ncomp + Ntransf + Nrec
Listes tri
ees
44
etape v
v0
1 31415 xxxxx
acb
024
31415 xxxxx
012
31415 xxxxx
001
31415 xxxxx
31415 3xxxx
10
31415 31xxx
001
6
7
13415 31xxx
13415 31xxx
2 2
012
true
13415 134xx
334
false
11
12
13
13415 134xx
13415 134xx
13415 134xx
3 3
4 4
334
true
true
13415 13415
024
11345
a faire
2: tri_partiel
3: tri_partiel
4: fusion v v
false
5: tri_partiel
6: tri_partiel
7: fusion v v
true
8: tri_partiel
9: tri_partiel
10: fusion v v
false v0(0) v(0)
vers_v1
true
false
v
v
0
v
v
0
v
v
0
v 0
v 3
2 4
v 0
v 2
1 2
v 0
v 1
0 1
2 false
4 false
1 true
2 true
0 false
1 false
v0(1) v(1)
Ntransf (1) = 1,
Nrec (1) = 1.
45
Listes tri
ees
46
3-7
Tri rapide
Le tri rapide, aussi appele tri de Hoare, tri par segmentation, ou quicksort, consiste a reorganiser une liste L = (a0 , . . ., an1) en trois sous-listes :
L1 = (b0 , . .., bp1 ),
L2 = (a0 ),
L3 = (c0 , .. ., cq1)
dont la concatenation est une permutation de L et telles que tous les elements de
L1 sont inferieurs ou equivalents a a0 et tous les elements de L3 sont superieurs
ou equivalents a a0 . Pour trier L, il reste a trier separement L1 et L3 ce que lon
fait recursivement.
(* e
change les e
l
ements dindices i et j dans v *)
let e
change v i j = let x = v.(i) in v.(i) <- v.(j); v.(j) <- x;;
(* On suppose a < b et on note x = v.(a).
(* R
eorganise v(a..b) de sorte quen sortie tous les e
l
ements
(* dindice < c soient inf
erieurs a
` x, tous ceux dindice > c
(* soient plus grands que x et v(c) = x.
(* Retourne c en r
esultat.
let segmentation compare v a b =
let i = ref(a+1) and j = ref(b) and x = v.(a) in
while !i <= !j do
(* ici, tous les e
l
ements de v(a+1..i-1) sont <= x
(*
et tous les e
l
ements de v(j+1..b) sont >= x
(* avance i et recule j tant que cette propri
et
e
(* reste vraie et que lon a i <= j.
while (!i <= !j) & (compare x v.(!i)) <> PLUSPETIT
do i := !i+1 done;
while (!j > !i) & (compare x v.(!j)) <> PLUSGRAND
do j := !j-1 done;
(* e
change les e
l
ements trouv
es *)
if !i < !j then begin
e
change v !i !j;
i := !i+1;
j := !j-1;
end
else if !i = !j then j := !j-1;
done; (* while !i <= !j *)
*)
*)
*)
*)
*)
*)
*)
*)
*)
47
Nech 6
Listes tri
ees
48
action
v
[|1
[|1
1
1
5|]
done
[|4
5|]
c=0
[|4
5|]
1
1
5|]
segmentation(0, 7)
while !i <= !j
[|4
[|4
segmentation(1, 7)
while !i <= !j
4
4
2
2
1
1
5|]
5|]
done
e
change(1, 6)
[|3
1|]
[|5|]
[|3
1|]
e
change(3, 5)
4|]
while !i <= !j
4|]
done
4|]
e
change(1, 4)
c=4
[|3
[|3
segmentation(1, 5)
while !i <= !j
c=6
1|]
j
2
ij
1
1
[|3
[|3
1
1
[|2
1|]
[|4|]
[|2
1|]
1|]
done
1|]
e
change(1, 3)
c=3
1
1
[|2
[|2
segmentation(1, 3)
while !i <= !j
[|1
1|]
2[| |] 3
[|1
1|]
1|]
done
1|]
e
change(1, 2)
1[| |] 2
c=2
segmentation(1, 2)
while !i <= !j
ij
1
1
[|1
[|1
[|1|]
49
*)
*)
*)
*)
Listes tri
ees
50
| EQUIV when x > y -> PLUSGRAND
| res
-> res
in
tri_rapide comp p; p
;;
3-8
Exercices
mon^
ome a un coecient a 6= 0. Ecrire
une fonction daddition de deux polyn^
omes
pour cette representation.
Exercice 3-5 : fusion multiple
Etudier
les problemes suivants (on cherchera a minimiser le temps dexecution
compte en nombre maximal de comparaisons eectuees) :
1. Fusion de trois listes triees, L1, L2 , L3 .
2. Fusion de quatre listes triees, L1 , L2 , L3 , L4 .
Exercice 3-6 : tri a
` bulles
Programmer lalgorithme du tri a bulles dans le cas du tri dune liste cha^nee.
3-8 Exercices
51
52
Listes tri
ees
a trier. Ecrire
une fonction iterative eectuant le tri dun vecteur suivant cette
methode. Montrer que la longueur de la liste auxiliaire peut ^etre majoree par
1 + log2 n si lon choisit de trier en premier le plus petit des sous-vecteurs produits
par la phase de segmentation.
Chapitre 4
Evaluation
dune formule
4-1
Structure de pile
Une pile est une liste ne permettant des insertions ou des suppressions qu
a
une seule extremite, appelee sommet de la pile. Empiler un objet sur une pile
P consiste a inserer cet objet au sommet de P, et d
epiler un objet de P consiste
a supprimer de P lobjet place au sommet. Lobjet depile est retourne par la
fonction de depilement pour ^etre traite par le programme.
sommet
de la pile
c
b
a
d
empiler d
d
c
b
a
depiler
c
b
a
Evaluation
dune formule
54
4-2 Repr
esentation lin
eaire dune formule
55
Repr
esentation dune pile par une liste chan
ee
On peut aussi representer une pile par une reference sur liste cha^nee, le
sommet de la pile etant la t^ete de la liste.
type a ch_pile == a list ref;;
(* cr
eation dune pile vide *)
let cr
ee_pile() = ref [];;
(* empile x *)
let empile pile x = pile := x :: !pile;;
(* d
epile le sommet de pile et le retourne comme r
esultat *)
let d
epile pile = match !pile with
| []
-> failwith "pile vide"
| a::suite -> pile := suite; a
;;
(* dit si la pile est vide *)
let est_vide pile = !pile = [];;
4-2
Repr
esentation lin
eaire dune formule
3 + 2 36
6
/ 6
Evaluation
dune formule
56
4-3
Evaluation
dune formule postfixe
Une formule postxe peut ^etre evaluee a laide dune pile par lalgorithme
suivant :
{ initialiser la pile a
vide et parcourir la formule
(( de gauche a droite )) ;
{a
chaque fois que lon trouve une valeur, empiler cette valeur ;
{a
chaque fois que lon trouve un op
erateur unaire f, d
epiler le sommet
de la pile, soit x, et empiler la valeur f[x] ;
{a
chaque fois que lon trouve un op
erateur binaire g, d
epiler les deux
valeurs au sommet de la pile, soit x, y avec x d
epil
ee en premier, et
empiler la valeur g[y, x] ;
{ lorsque le parcours de la formule est termin
e, la pile ne contient plus
quune valeur qui est la valeur de la formule.
Par exemple la formule postxe :
3 2 36 sqrt +
est evaluee selon les etapes :
4-3 Evaluation
dune formule postfixe
pile
formule
[
[
[
[
[
[
[
[
[
3 2 36 sqrt
2 36 sqrt
36 sqrt +
sqrt + 6
+ 6 /
+ 6 /
6 /
/
]
3]
3
3
3
3
15 ]
2.5 ]
2.5 ]
2]
2
36 ]
2
6]
12 ]
57
+ 6 /
+ 6 /
6 /
/
Evaluation
dune formule
58
3.0;
2.0;
36.0;
sqrt;
mult_float;
add_float;
6.0;
div_float ]
4-4
Exercices
4-4 Exercices
59
Exercice 4-3 :
evaluation dune formule pr
efixe
Etudier
le probleme de levaluation dune formule prexe.
Exercice 4-4 :
evaluation dune formule infixe a
` laide de deux piles
Levaluation dune formule inxe non completement parenthesee impose de denir
des regles de priorite de facon a rendre non ambigue les formules du type :
x f
y g z
o
u x, y, z sont des nombres et f, g des operateurs binaires. On adopte ici la convention dassociativite a gauche :
evaluer les op
erations prioritaires en premier ; en cas de priorit
es
egales
evaluer lop
eration de gauche en premier.
On peut alors evaluer une formule inxe a laide de deux piles, une pile de valeurs
et une pile doperateurs de la maniere suivante :
parcourir la formule en pla
cant les valeurs rencontr
ees dans la pile
des valeurs, les op
erateurs et parenth
eses ouvrantes dans la pile des
op
erateurs et en eectuant toutes les op
erations prioritaires empil
ees
lorsquon doit empiler un op
erateur binaire ou une parenth
ese fermante.
Une op
eration unaire est eectu
ee au moment o
u lon doit empiler
largument correspondant. A la n du parcours, eectuer les op
erations
en instance et retourner le sommet de la pile des valeurs.
Coder cet algorithme en caml. On utilisera la declaration suivante pour representer les elements dune formule inxe :
type a lex`
eme =
| VALEUR
of a
| OP_UNAIRE of a -> a
| OP_BINAIRE of int * (a -> a -> a) (* priorit
e, op
eration *)
| PARENTH`
ESE_OUVRANTE
| PARENTH`
ESE_FERMANTE
;;
Ecrire
une fonction compile qui prend en argument une formule inxe f supposee
bien formee et renvoie une formule postxe f0 constituee des m^emes nombres et
des m^emes operateurs et ayant m^eme valeur que f.
Exercice 4-6 : non ambigut
e des formules infixes
Montrer que si lon remplace les valeurs par des variables independantes et si lon
ne fait aucune hypothese sur la commutativite ou lassociativite des operateurs
alors une formule inxe bien formee f admet une unique formule postxe f0
equivalente.
Chapitre 5
Logique bool
eenne
5-1
Propositions
Une proposition est une phrase non ambigue a laquelle on peut attribuer
une valeur de verite : vrai ou faux. Cette valeur peut dependre de parametres
contenus dans la proposition. Par exemple les phrases :
{ Il fait beau aujourdhui.
{ x admet une racine carr
ee enti
ere.
{ est un nombre n
egatif.
sont des propositions, la deuxieme dependant du parametre x. Par contre les
phrases :
{ Cette phrase est fausse.
{ Pourquoi pas ?
nen sont pas.
En logique booleenne on ne sinteresse qu
a la valeur de verite dune proposition et on ignore le sens de la phrase associee. Deux propositions p et q ayant
la m^eme valeur de verite sont dites identiques, ce que lon note : p q. Par
exemple avec :
p : Mercredi vient apr
es Mardi.
q : Mardi vient apr
es Mercredi.
r : No
el est un jour f
eri
e.
s : < 0.
on a p r et q s. Si les propositions p et q dependent de parametres x1 , .. ., xn,
on convient que p q si et seulement si, pour toute valeur de (x1 , .. ., xn),
p(x1 , . .., xn) et q(x1 , . .., xn) ont m^eme valeur de verite. Une proposition est
une tautologie si elle est identique a vrai.
Connecteurs logiques
Etant
donnees deux propositions p et q, on convient que les expressions
suivantes sont aussi des propositions :
5-1 Propositions
61
{ non p : note aussi p ou p. (non p) est vrai lorsque p est faux, faux
lorsque p est vrai.
{ p et q : note aussi pq ou pq. (p et q) est vrai lorsque p et q valent vrai,
(p et q) est faux dans les autres cas. Loperation et est appelee conjonction
ou produit bool
een.
{ p ou q : note aussi p q ou p + q. (p ou q) est vrai lorsque lune au moins
des deux propositions vaut vrai, (p ou q) est faux lorsque les deux valent
faux. Lop
eration ou est appelee disjonction ou somme bool
eenne.
{ p oubien q : note aussi p q. (p oubien q) est vrai lorsquune et une seule
des propositions p, q est vrai. On peut aussi dire que (p oubien q) vaut vrai
si et seulement si p et q ont des valeurs de verites dierentes.
{ p q : (p q) est vrai lorsque p et q ont la m^eme valeur de verite.
Cette notion est dierente de lidentite : p q est un fait tandis que
p q est une proposition qui peut ^etre vraie ou fausse.
{ p = q : (p = q) est une proposition identique a ((non p) ou q), ce qui
se lit : limplication p = q vaut faux si et seulement si p vaut vrai
et q vaut faux ; dans tous les autres cas, en particulier lorsque p vaut
faux, limplication vaut vrai. Remarquons que limplication bool
eenne ainsi
denie ne traduit pas un lien de cause a eet entre p et q mais seulement
une comparaison de leurs valeurs de verite. Par exemple les implications :
(Mercredi vient apr
es Mardi) = (2 + 2 = 4)
(Il neige en Novembre) = (No
el sera en D
ecembre)
valent vrai. De m^eme, etant donne trois propositions p, q, r quelconques et
sans aucun rapport entre elles, la proposition :
(p = q) ou (q = r)
vaut toujours vrai.
Tables de v
erit
e
Soit f(p1 , .. ., pn ) une proposition dependant de parametres p1 , .. . , pn qui
sont des propositions indeterminees. Les propositions p1 , . . . , pn sont appelees :
variables propositionnelles de f. On dit aussi que f est une fonction bool
eenne
de n variables. La table de v
erit
e de f est un tableau donnant la valeur de verite de
f(p1 , .. ., pn ) pour chaque valeur possible du n-uplet (p1 , . .., pn ). Chaque variable
propositionnelle peut prendre la valeur vrai ou faux, donc lensemble des valeurs
possibles pour (p1 , . .., pn) est {vrai, faux}n. En particulier, la table de verite
de f a 2n lignes. Ces lignes sont generalement classees par ordre lexicographique
du n-uplet valeur de (p1 , . .., pn ). Les tables de verite des connecteurs logiques
denis a la section precedente sont :
p
V
F
non p
F
V
Logique bool
eenne
62
p
V
V
F
F
q
V
F
V
F
p et q p ou q p oubien q
V
V
F
F
V
V
F
V
V
F
F
F
p q
V
F
F
V
p = q
V
F
V
V
o
u V et F representent vrai et faux.
Une table de verite peut ^etre utilisee pour denir une fonction booleenne ou
pour verier une identite remarquable, cest-
a-dire une tautologie. Par exemple la
table :
p
V
V
F
F
q
V
F
V
F
p
F
F
V
V
q
F
V
F
V
q = p p = q
V
V
F
F
V
V
V
V
q
0
1
0
1
p et q p ou q p q p = q
0
0
0
1
0
1
1
1
0
1
1
0
1
1
0
1
5-2
63
Circuits logiques
Un circuit logique est un dispositif physique (electronique, mecanique, optique ou autre) muni dentr
ees et de sorties nayant que deux etats stables notes
0 et 1. Les etats des entrees sont imposes par (( lexterieur )), les etats des sorties sont imposes par le circuit en fonction des etats des entrees. Le circuit est
dit combinatoire si les etats des sorties a un instant donne ne dependent que des
etats des entrees a cet instant, et s
equentiel si les etats des sorties dependent aussi
des etats anterieurs des entrees. Les circuits logiques elementaires sont representes
sur la gure 6.
relais : E
S=E
or :
A
B
S= A+B
not:
S=E
nor :
A
B
S= A+B
and :
A
B
S = AB
xor :
A
B
S= AB
nand :
A
B
S = AB
Figure 6 : circuits
el
ementaires
Le relais est utilise pour amplier un signal logique dans un montage comportant beaucoup de circuits, il na pas dutilite au sens logique. Les portes et et
ou sont appel
ees ainsi car elles permettent de bloquer ou laisser passer un signal
logique (cf. gure 7).
S = E : porte passante
1
E
1
S = 0 : porte bloquee
S = 1 : porte bloquee
S = E : porte passante
0
Figure 7 : portes
Les portes nand et nor agissent comme des portes inverseuses : soit la porte est
bloquee, soit elle laisse passer la negation de son entree libre. La porte oubien
transmet ou inverse un signal present sur une entree suivant que lautre entree est
maintenue a 0 ou a 1.
Un circuit logique non elementaire est constitue de circuits elementaires
inter-connectes de sorte que toute entree dun composant est reliee soit a une entree
Logique bool
eenne
64
du circuit complet soit a une sortie dun autre composant, et toute sortie dun
composant est reliee a une sortie du circuit complet ou a une ou plusieurs entrees
dautres composants. On demontre quun circuit est combinatoire si aucune sortie
dun composant nest reliee a une des entrees de ce composant, directement ou
indirectement a travers dautres portes (cest une condition susante seulement).
A B
1 1
1 0
0 1
0 0
1
0
0
0
S
1 0
1 1
1 1
0 0
R S
1 1
1 0
0 1
0 0
Q
x
0
1
1
Q0
x
1
0
1
circuit combinatoire
R
Q0
S
circuit s
equentiel
Le circuit sequentiel ci-dessus est appele bascule RS. Il constitue une memoire
simpliee : on enregistre un 0 en mettant R a 1 et S a 0 puis en ramenant S a 1.
De m^eme, en maintenant S a 1, on enregistre un 1 en mettant R a 0 puis en le
ramenant a 1. Lorsque R = S = 1, le bit memorise est disponible sur Q et son
complement est disponible sur Q0 . Les etats de Q et Q0 dependent donc du passe.
Remarque technique
Par assemblage de circuits elementaires on peut realiser nimporte quelle
fonction booleenne (voir la section suivante). Cependant, lors de la realisation
physique, il faut tenir compte des points suivants :
{ Une sortie ne peut alimenter quun nombre limite dentrees. La sortance
dun circuit est le nombre maximal dentrees qui peuvent ^etre connectees sur
une sortie de ce circuit ; elle est generalement comprise entre 10 et 100 suivant
la technologie employee. Dans un circuit complexe il peut ^etre necessaire
dintercaler des relais amplicateurs sur les sorties tres demandees.
{ Chaque porte a un temps de propagation non nul : lorsquune entree change
de valeur la sortie nest garantie stable quau bout de ce delai de propagation. Le temps de reponse dun assemblage de portes elementaires est donc
proportionnel au plus grand nombre de portes intercalees entre une entree et
une sortie du circuit complet. Ce nombre est appele profondeur du circuit
et on a generalement inter^et a minimiser cette profondeur pour obtenir un
fonctionnement rapide.
5-3 Synth
ese des fonctions bool
eennes
5-3
65
Synth`
ese des fonctions bool
eennes
Repr
esentation et-ou-non
Th
eor`
eme : soit f une fonction bool
eenne des variables p1 , ..., pn . Alors
f peut ^
etre exprim
ee uniquement a
laide des connecteurs et, ou, non, des
variables pi et des propositions constantes vrai et faux.
Cons
equence : toute fonction bool
eenne peut ^
etre r
ealis
ee par assemblage
de portes
el
ementaires and, or et not.
D
emonstration : on procede par recurrence sur n. Pour n = 0, f est une
proposition sans variable, donc f vrai ou f faux. Si le theoreme est verie
pour toute fonction booleenne a n1 variables, considerons une fonction booleenne
f a n variables et les deux fonctions :
g : (p1 , .. ., pn1) 7 f(p1 , . . ., pn1, vrai),
C
0
1
0
1
0
1
0
1
S1
0
0
0
1
0
1
1
1
S0
0
1
1
0
1
0
0
1
Additionneur n-bits
2
Logique bool
eenne
66
S0
BC
C
A
A
A
BC
S1
A
B+C
a 0 b0
c a
s0
b
s1
s0
a 1 b1
c a
s0
b
s1
s1
an1 bn1
c a
s0
b
s1
sn1
sn
y i = a i bi ,
5-3 Synth
ese des fonctions bool
eennes
67
Notons n(a, b, c0 ) = (c0 , . .., cn1) et supposons que n est pair, n = 2p. En
decomposant a = a0 +2p a00 et b = b0 +2p b00, on obtient les relations de recurrence :
fn (a, b) = fp (a0 , b0 ) gp(a00 , b00) + fp (a00 , b00),
gn (a, b) = gp (a0 , b0 ) gp(a00 , b00),
n(a, b, c0 ) = p (a0 , b0, c0 ) @ p (a00 , b00, fp (a0 , b0 ) + c0 gp (a0 , b0)),
o
u @ designe la concatenation des listes. Ces relations permettent de construire un
circuit calculant recursivement les coecients fn (a, b), gn(a, b) et la liste complete
des retenues selon la strategie (( diviser pour regner )) (cf. gure 10). Soient Pn la
profondeur de ce circuit et Kn le nombre de portes quil contient. On a :
P1 = 1,
K1 = 2,
Pn = Pn/2 + 2,
Kn = 2Kn/2 + 5.
Do
u, lorsque n est une puissance de 2, Pn = 1 + 2 log2(n) et Kn = 7n 5.
Il est ainsi possible de calculer la somme de deux nombres de n bits en temps
logarithmique par rapport a n et avec un nombre de portes lineaire en n (voir
lexercice 5-8 pour une minoration de la profondeur dun additionneur n-bits
quelconque).
a0
b0
a00
f0
g0
FG
b00
f00
g00
FG
f
g
FG
c0
c0
c00
Logique bool
eenne
68
S0
S1
69
En intervertissant les r^
oles des connecteurs et et ou on peut aussi representer
une fonction booleenne de n variables comme un produit de sommes de n litteraux
o
u chaque variable appara^t une et une seule fois dans chaque somme. Cette
representation est appelee forme normale conjonctive. Pour obtenir la forme
normale conjonctive de f il sut dappliquer les regles de de Morgan a la negation
de la forme normale disjonctive de f.
5-4
(p et q) et r
sont dierentes par leur forme mais elles representent la m^eme fonction booleenne,
celle qui vaut vrai si et seulement si les propositions p, q et r valent vrai. On
etudie ici les problemes suivants :
{ representation en memoire dune formule logique ;
{ evaluation dune formule lorsque les valeurs de verite des variables de la
formule sont connues ;
{ satisabilite : existe-t-il une distribution de verite pour laquelle cette formule
vaut vrai ?
{ tautologie : la formule etudiee vaut-elle vrai pour toute distribution de
verite ?
{ identite fonctionnelle : deux formules logiques representent-elles la m^eme
fonction booleenne ?
Les trois derniers problemes sont lies. En eet, la formule f est une tautologie si
et seulement si f nest pas satisable, et les formules f et g sont identiques si et
seulement si f g est une tautologie. Un probleme qui nest pas aborde est
celui de la simplication dune formule logique, ou de la recherche dune formule
logique (( la plus simple possible )) representant une fonction booleenne donnee.
Repr
esentation en m
emoire
La notion de formule logique est intrinsequement recursive : une formule
logique est soit une valeur constante vrai ou faux, soit une variable propositionnelle, soit lapplication dun connecteur logique (non, et, ou, oubien, nand, nor,
= , ) a une ou deux formules logiques. On denira donc le type formule en
caml par :
type formule =
| Const of bool
| Var
of string
| Mono of op1 * formule
| Bin
of op2 * formule * formule
and op1 == bool -> bool
and op2 == bool -> bool -> bool
;;
(*
(*
(*
(*
valeur constante
variable
connecteur a
` un argument
connecteur binaire
*)
*)
*)
*)
Logique bool
eenne
70
Les connecteurs logiques sont representes par des fonctions operant sur le type
bool. Les connecteurs usuels peuvent ^
etre denis par :
let
let
let
let
;;
non
et
ou
equiv
=
=
=
=
let
let
let
let
nand
nor
oubien
impl
fun
fun
fun
fun
x
x
x
x
y
y
y
y
true
true true
false false
false false
=
=
=
=
->
->
->
->
false
true
false
true
|
|
|
|
_
-> true;;
_ _ -> false;;
_ _ -> true;;
true true -> true | _ _ -> false
non(et x y);;
non(ou x y);;
non (equiv x y);;
ou (non x) y;;
En interne la formule est representee par un ensemble de cellules reliees par des
pointeurs comme pour les listes cha^nees (cf. gure 12). Pour des raisons de commodite typographique, on prefere decrire les formules par des arbres syntaxiques
tels que celui de la gure 13.
Bin
et
et
Var
Bin
q
Var
Mono non
Var
Figure 12 : repr
esentation
m
emoire dune formule
non
r
Figure 13 :
repr
esentation abstraite
f = match f with
traite_constante(c)
traite_variable(v)
traite_mono(op,g)
traite_bin(op,g,h)
o
u traite_constante, traite_variable, traite_mono et traite_bin sont des actions appropriees au traitement a eectuer. En general les actions traite_mono et
traite_bin proc
edent au parcours des sous-formules g et h.
71
Evaluation
dune formule logique
Pour evaluer une formule logique il faut disposer des valeurs de toutes les
variables apparaissant dans la formule. On peut representer une distribution
de verite par une liste de couples (nom de la variable, valeur ) transmise en
argument a la fonction devaluation. Comme les connecteurs sont directement
representes par des fonctions caml, il sut devaluer recursivement les arguments
dun connecteur puis dappliquer la fonction associee aux valeurs obtenues :
(* Recherche la variable de nom "nom" dans la distribution *)
(* de v
erit
e "distribution" et renvoie sa valeur.
*)
let rec valeur_variable distribution nom = match distribution with
| []
-> failwith "variable inconnue"
| (x,y)::suite -> if x = nom then y else valeur_variable suite nom
;;
(* Evalue la formule f *)
let rec e
value distribution f = match f with
| Const(c)
-> c
| Var(nom)
-> valeur_variable distribution nom
| Mono(op,g) -> op (
evalue distribution g)
| Bin(op,g,h) -> op (
evalue distribution g) (
evalue distribution h)
;;
Complexit
e : le temps necessaire a levaluation de f depend de plusieurs parametres. Chaque variable apparaissant dans f donne lieu a une recherche sequentielle
dans la distribution de verite, necessitant en moyenne n/2 comparaisons. Levaluation dune constante ou dun connecteur prend un temps constant une fois que
les arguments du connecteur sont evalues, donc le temps total devaluation est de
la forme :
T = aN + bVn
o
u a, b sont des constantes, N est le nombre de connecteurs et de constantes dans
la formule, V est le nombre de variables de f comptees avec repetitions et n est
la longueur de la liste distribution. Pour une formule de longueur ` le temps
devaluation est donc O(n`).
Satisfiabilit
e, reconnaissance de tautologies
Etant
donnee une formule logique f dependant de variables p1 , . . ., pn, on
veut determiner une distribution de verite pour p1 , . . ., pn qui rend f vrai. La
methode la plus simple est de (( parcourir )) la table de verite de f jusqu
a trouver
la valeur vrai. Il nest pas necessaire de construire explicitement cette table de
verite, il sut dengendrer lune apres lautre toutes les distributions de verite
pour (p1 , . .., pn ) et devaluer a chaque fois f.
Logique bool
eenne
72
type r
esultat =
| TROUV
E of (string * bool) list
| NONTROUV
E
;;
(* dist. de v
erit
e trouv
ee *)
(* formule non satisfaite *)
*)
*)
*)
Complexit
e : pour une formule f a n variables de longueur `, la recherche
dune distribution de verite satisfaisant f peut necessiter jusqu
a 2n etapes, chacune de ces etapes consistant a construire une distribution de verite dans la liste
vli
ees puis a
evaluer f. Le temps dexecution dune etape est O(n`) donc le
temps necessaire pour constater quune formule a n variables est une tautologie
est O(n2n`) car dans ce cas on parcourt eectivement toute la table de verite.
On peut obtenir un temps O(2n `) si la distribution de verite est stockee dans un
vecteur au lieu dune liste cha^nee, mais m^eme avec cette amelioration la detection
des tautologies est impraticable pour des valeurs de n depassant la vingtaine.
Il existe dautres methodes pour reconna^tre les tautologies, mais elles ont
elles aussi un temps dexecution exponentiel dans le pire des cas : la methode
de Davis et Putnam consiste a simplier la formule a contr^
oler a chaque fois
que lon choisit la valeur de verite dune variable. On utilise pour cela les regles
de simplication des connecteurs et et ou ayant un operande constant ainsi que
des regles similaires pour les autres connecteurs (cf. exercice 5-6). Ceci permet
dobtenir une formule plus courte, ayant au moins une variable de moins que la
formule de depart, la variable que lon vient daecter. Lordre dans lequel on
aecte les variables nest pas indierent : on a inter^et a choisir parmi les variables
encore libres celle qui donnera apres simplication la formule la plus simple en
nombre de variables libres restant. La recherche de la meilleure variable a aecter
complique le code du vericateur et co^
ute du temps, mais semble ^etre la methode
la plus ecace connue a ce jour pour la verication de tautologies.
Une autre methode de verication dune tautologie consiste a mettre la formule f sous forme conjonctive, non necessairement normale, cest-
a-dire a transformer f en un produit de sommes de litteraux. On peut obtenir une telle forme
5-5 Exercices
73
pour f en traduisant tous les connecteurs a laide des connecteurs de base et, ou,
)) tous les et et (( descendre )) tous les non par les regles
de de Morgan et la distributivite de ou sur et. Apres elimination des sommes
contenant un litteral et sa negation, il ne reste plus que des sommes non triviales
qui fournissent les cas o
u f vaut faux. Donc f est une tautologie si et seulement si
la forme conjonctive obtenue pour f est vide apres simplications. Cette methode
a aussi un co^
ut exponentiel dans le pire des cas, car une forme conjonctive a n
variables peut contenir jusqu
a 2n1 facteurs dierents (cf. exercice 5-3). Donc
cette methode est non seulement co^
uteuse en temps, mais aussi en memoire.
non, et en (( faisant remonter
5-5
Exercices
Ecrire
en caml les denitions du type normand et des connecteurs precedents.
Verier que les identites usuelles des connecteurs logiques sont encore valables en Normandie (associativite, commutativite, distributivite). On pourra
eectuer cette verication par programme.
4. Est-ce que toute (( fonction normande )) est exprimable a laide des connecteurs et ou et non ?
Exercice 5-3 : taille dune forme conjonctive
1. Montrer que toute forme conjonctive (conjonction de disjonctions de litteraux, non necessairement normale) qui equivalente a la formule logique
f = p1 p2 .. . pn comporte au moins 2n1 facteurs.
2. Existe-t-il des fonctions booleennes a n variables necessitant encore plus de
facteurs, m^eme apres simplications ?
Logique bool
eenne
74
Ecrire
une fonction simplifie qui simplie une formule logique en evaluant les
operandes constants. Noter que si un seul des operandes dun connecteur binaire
est constant alors la formule peut quand m^eme ^etre simpliee :
p et vrai p,
p et faux faux,
p oubien vrai p,
.. .
S0
E1
E2
S1
5-5 Exercices
75
Chapitre 6
Complexit
e des algorithmes
6-1
G
en
eralit
es
Si lon fait executer ces deux algorithmes par une machine caml, la complexite temporelle de prod1 est T1 = 4n + 2 o
u n est la longueur de v (on a
6-1 G
en
eralit
es
77
Complexit
e des algorithmes
78
T2 =
n
1 X
9n
(a2 k + b2 ) 9k1 10nk + n (a2 n + b2 )
n
10
10
k=1
n
1 X
=
(a2 k + b2 ) 0, 9k1 + 0.9n(a2 n + b2 )
10
k=1
1 X
(a2 k + b2 ) 0, 9k1 = 10a2 + b2 .
10
k=1
La complexite moyenne de prod2 est donc bornee, alors que celle de prod1 est
asymptotiquement proportionnelle a n. Ce phenomene se produit quelle que
soit la distribution de probabilite retenue, pourvu que les elements de v soient
independants et que la probabilite dapparition de zero soit non nulle. Incidemment, on apprend que le rang moyen du premier zero est environ egal a 10 (ou
plus generalement 1/p o
u p est la probabilite dapparition dun zero) lorsque n
est grand, et non n/2.
La complexite spatiale mesure la quantite de memoire necessaire a lexecution
dun algorithme, en comptant les variables temporaires et le resultat, mais pas les
donnees (de m^eme quon ne compte pas le temps dintroduction des donnees dans
la complexite temporelle). Lunite de mesure est le (( mot memoire )), mais cette
unite depend de la machine utilisee et on calcule generalement une complexite
memoire asymptotique. Sur une machine sequentielle o
u il y a un seul processeur
executant une seule instruction par unite de temps, la complexite memoire est
au plus egale a la complexite temporelle puisquil faut au moins une unite de
temps pour (( remplir )) une position memoire. Ceci nest pas vrai sur des machines hautement paralleles disposant dun nombre arbitraire de processeurs. Par
exemple le calcul du produit des elements dun vecteur de longueur n peut ^etre
eectue selon la methode (( diviser pour regner )) avec n/2 processeurs calculant
en m^eme temps les produits de deux termes consecutifs, puis en calculant par la
m^eme methode le produit des n/2 sous-produits obtenus (cf. gure 14).
6-2 Equation
de r
ecurrence T (n) = aT (n 1) + f(n)
79
6-2
Equation
de r
ecurrence T (n) = aT (n 1) + f(n)
Le calcul de la complexite dun algorithme conduit generalement a une relation de recurrence, en particulier si cet algorithme est recursif. On etudie ici le
cas o
u le temps T dexecution dun algorithme pour une donnee de taille n suit
une relation de la forme :
T (n) = aT (n 1) + f(n)
o
u f est une fonction a valeurs entieres donnee. Cela signie que la resolution du
probleme pour une donnee de taille n se ramene a la resolution de a sous-problemes
pour des donnees de taille n1. f(n) represente le temps necessaire pour decouper
le probleme initial en sous-problemes et pour recombiner les resultats de ces sousproblemes.
Exemples
Parcours dune liste de n elements : T (n) = T (n 1) + b o
u b est le temps
necessaire pour traiter un element.
Complexit
e des algorithmes
80
pour n > 1, o
u a N et f, g sont des fonctions de N dans N . On a alors les
proprietes suivantes :
1. Les fonctions T et U sont strictement croissantes.
2. Si T (0) 6 U(0) et si f(n) 6 g(n) pour tout n N alors T (n) 6 U(n)
pour tout n N.
3. Si f(n) = O(g(n)) pour n alors T (n) = O(U(n)) pour n .
En eet, 1 et 2 sont evidentes. Pour 3, puisque f(n) = O(g(n)) et g(n) > 0,
il existe une constante C telle que f(n) 6 Cg(n) pour tout n et, quitte a augmenter C, on peut supposer que T (1) 6 CU(1) (car U(1) = aU(0) + g(1) > 0)
donc T (n) 6 CU(n) pour tout n > 1 par recurrence.
Cette propriete permet de remplacer une equation de recurrence compliquee
par une equation plus simple o
u lon ne garde que le terme dominant du temps
de separation-recombinaison. Par exemple le coecient c peut ^etre ignore dans
6-2 Equation
de r
ecurrence T (n) = aT (n 1) + f(n)
81
Equation
T (n) = T (n 1) + f(n)
Cette equation se resout de maniere immediate :
n
X
f(k).
T (n) = T (0) +
k=1
n
P
f(k).
k=1
esaro)
Th
eor`
eme : (lemme de C
Soient (un) et (vn ) deux suites de r
eels telles que :
un
vn > 0,
` [0, +] et v0 + v1 + ... + vn +.
n
vn n
Alors le rapport
u0 + u1 + ... + un
tend vers ` quand n .
v0 + v1 + ... + vn
Th
eor`
eme : (variante)
Soient (un) et (vn ) deux suites de r
eels telles que :
vn > 0,
k=1
k=1
ce qui sut pour les recurrences usuelles. Ainsi le temps de parcours dune liste
verie : T (n) bn et celui du tri par selection : T (n) 21 bn2 . Dans le cas
Pn
general, k=1 kp peut ^etre estime par comparaison serie-integrale, et lon a :
n
X
k=1
kp
np+1
p+1
pour p > 0 et n .
Equation
T (n) = aT (n 1) + f(n)
On se ramene a une equation du type precedent en posant U(n) = T (n)/a n
ce qui donne :
Complexit
e des algorithmes
82
f(n)
,
an
n
X f(k)
U(n) = U(0) +
,
ak
k=1
n
X
f(k)
.
T (n) = an T (0) +
ak
k=1
U(n) = U(n 1) +
n
X
k=1
2k
= 2n 1.
Dans le cas general on peut obtenir une conclusion plus precise selon la vitesse de
croissance de f :
P
k
{ si la s
erie
k=1 f(k)/a converge (ce qui est en particulier le cas lorsque
f(n) est a
croissance polynomiale) alors T (n) an pour une certaine
constante en g
en
eral non calculable explicitement ;
{ si f(n) an pour n alors T (n) nan ;
b n
{ si f(n) bn pour n avec b > a alors T (n)
b .
ba
6-3
R
ecurrence diviser pour r
egner
Le principe (( diviser pour regner )) conduit generalement a ramener la resolution dun probleme de taille n a celle dun ou plusieurs sous-problemes de taille
approximativement n/2 puis a combiner les resultats. Cest en particulier le cas
pour la recherche par dichotomie dans un vecteur trie, pour le tri par fusion, la
multiplication rapide des polyn^
omes (methodes de Knuth et transformation de
Fourier rapide), et dans une moindre mesure pour le tri (( rapide )) : dans ce
dernier cas, il nest pas garanti que la segmentation produise des sous-vecteurs de
taille approximativement n/2. Les equations de recurrence pour les algorithmes
de type diviser pour regner sont generalement de la forme :
T (n) = aT (bn/2c) + bT (dn/2e) + f(n)
(n > 2)
o
u a et b sont des entiers naturels tels que a + b > 1 et f est une fonction de N
dans N (le cas de base correspond a n = 1 plut^
ot qu
a n = 0).
Cas o`
u n est une puissance de 2
Lorsque n est une puissance de 2, n = 2p , on introduit une fonction auxiliaire
U denie par U(p) = T (2p ) et qui verie donc :
U(p) = (a + b)U(p 1) + f(2p ).
6-3 R
ecurrence diviser pour r
egner
83
On obtient alors :
p
X
T (2p ) = U(p) = (a + b)p U(0) +
f(2k )
.
(a + b)k
k=1
Posons a + b = 2 . Dapres P
la section 6-2, le comportement asymptotique
P
k
k
{ Si la s
erie
converge, ce qui est r
ealis
e entre autres si
k=1 f(2 )/2
Par exemple le tri par fusion verie T (n) = T (bn/2c) + T (dn/2e) + cn + d donc
= 1 et f(n) cn1 ce qui implique : T (n) cn log2 (n) lorsque n est une
puissance de 2. Pour la multiplication polynomiale de Knuth, on a :
T (n) = T (bn/2c) + 2T (dn/2e) + cn + d,
donc = log2(3) 1.58 et f(n) cn1 do
u T (n) nlog2 3 pour un certain > 0.
Cas o`
u n nest pas une puissance de 2
Si f est croissante, on prouve par recurrence que la fonction T est croissante.
Lenonce de recurrence est :
Hn pour 1 6 p 6 q 6 n, on a T (p) 6 T (q).
n = 1 : il ny a rien a demontrer.
n = 2 : il sut de constater que T (2) > T (1) ce qui resulte de lhypothese
a + b > 1.
n 1 = n : par transitivite de la relation 6 et en utilisant Hn1, il sut
de considerer le cas p = n 1 et q = n. Comme n > 3 on a 2 6 p < q donc
on peut appliquer la relation de recurrence a T (p) et T (q) :
T (p) = aT (bp/2c) + bT (dp/2e) + f(p)
T (q) = aT (bq/2c) + bT (dq/2e) + f(q).
Et lon a 1 6 bp/2c 6 bq/2c < n, 1 6 dp/2e 6 dq/2e < n donc dapres Hn1
et la croissance de f, on a bien T (p) 6 T (q).
Lhypothese de croissance de f peut ^etre dicile a prouver si f est compliquee,
mais, comme a la section 6-2, on constate que lon peut remplacer f par une
fonction equivalente sans modier le comportement asymptotique de T (n), et si
lon obtient un equivalent de la forme n alors la croissance de lequivalent est
evidente.
Complexit
e des algorithmes
84
Maintenant que lon sait que T est croissante, il sut dencadrer n par deux
puissances successives de 2 pour obtenir une estimation asymptotique de T (n). Si
2p 6 n < 2p+1 et T (2p ) 2p , alors :
T (2p )
T (n)
T (2p+1 )
6
6
n
2p
2(p+1)
et les deux termes extr^emes convergent pour n vers /2 et 2 donc
le rapport T (n)/n est borne, cest-
a-dire : T (n) = (n ). On obtient une
p
conclusion similaire lorsque T (2 ) p2p , do
u le resultat general :
Th
eor`
eme : Soit T une fonction de N dans N v
eriant une
equation de
r
ecurrence de la forme : T (n) = aT (bn/2c) + bT (dn/2e) + f(n) avec a, b N
et a + b > 1. On note = log2 (a + b).
{ Si f(n) = O(n ) avec < alors T (n) = (n ).
{ Si f(n) = (n ) alors T (n) = (n ln(n)).
{ Si f(n) = (n ) avec > alors T (n) = (n ).
Schematiquement, on peut retenir que T (n) est generalement (n ), sauf si
le temps de separation-recombinaison des sous-problemes est comparable ou superieur a cette borne, auquel cas T (n) est (n ln(n)) (cas comparable) ou (f(n))
(cas superieur).
6-4
Exercices
p1 = a(f h),
p2 = (a + b)h,
p3 = d(e g),
p4 = (c + d)e,
p5 = (a + d)(e + h),
p6 = (a c)(e + f),
p7 = (d b)(g + h).
6-4 Exercices
85
De plus, cet algorithme peut setendre a des matrices n n en eectuant 7 multiplications et 18 additions/soustractions de matrices (n/2) (n/2).
Si lon utilise la methode de Strassen recursivement pour calculer les produits des matrices (n/2) (n/2), quelle complexite atteint-on pour le produit de
deux matrices n n ?
Exercice 6-3 : temps moyen dune comparaison
Pour classer deux cha^nes de caracteres par ordre alphabetique on compare leurs
caracteres de m^eme rang jusqu
a epuiser une cha^ne ou a trouver deux caracteres
dierents. Quel est le nombre moyen de comparaisons de caracteres eectuees
pour comparer deux cha^nes de longueur n en supposant que toutes les cha^nes
un =
u0
un1 un2
+
+ . .. +
1
2
n
pour n > 1.
Complexit
e des algorithmes
86
let u_iter(n) =
let v = make_vect (n+1) 0.0 in
v.(0) <- 1.0;
for p = 1 to n do
for k = 1 to p do
v.(p) <- v.(p) +. v.(p-k)/.float_of_int(k)
done
done;
v.(n)
;;
un = ubn/2c + ubn/3c
pour n > 1.
Chapitre 7
Arbres
7-1
D
efinitions
Arbres g
en
eraux
Un arbre g
en
eral est un ensemble non vide et ni dobjets appeles nffuds
et lies par une (( relation de parente )) :
xF y
x est un ls de y
y est le pere de x ;
x F y
x est un descendant de y
y est un anc^etre (ascendant) de x
x = y ou il existe un chemin : x = x0 F x1 F . .. F xn = y
tel que chaque element est le pere de lelement precedent ;
88
Arbres
{ Une for^
et est un ensemble ni darbres sans nffuds communs ; lensemble
des descendants stricts dun nffud x forme une for^et, vide si le nffud est
terminal. Les arbres de cette for^et sont appeles branches issues de x.
{ Un arbre ordonn
e est un arbre pour lequel lensemble des branches issues
dun nffud est totalement ordonne.
{ Un arbre est
etiquet
e lorsqu
a chaque nffud est associee une information
appelee
etiquette du nffud. Des nffuds distincts peuvent porter la m^eme
etiquette.
Exemples darbres : (cf. gure 15)
{ Larbre dune expression arithmetique ou logique est un arbre dont les nffuds
interieurs sont etiquetes avec les operateurs composant cette expression et les
branches representent les operandes associes. Cest un arbre ordonne.
{ Un systeme de chiers est represente par un arbre dont les nffuds sont
etiquetes avec des noms de chiers ou de repertoires. Les nffuds interieurs
correspondent aux repertoires non vides et les feuilles aux chiers de donnees
et aux repertoires vides.
{ Une taxinomie classe des objets suivant une description hierarchique. Chaque nffud correspond a une sous-classe incluse dans celle du nffud pere.
{ Un arbre de d
ecision modelise la resolution dun probleme par une suite de
tests imbriques.
{ Larbre dappels dune fonction recursive represente le calcul de cette fonction, les feuilles correspondant aux cas de base et les nffuds interieurs aux
cas recursifs.
{ Un arbre dynastique represente les descendants (generalement m^
ales) dun
individu et correspond a la notion usuelle de parente. Un arbre g
en
ealogique
represente les ascendants dun individu. Par derogation un arbre genealogique
a sa racine en bas, mais il ne sagit reellement dun arbre que si lon ne remonte pas trop loin dans le passe sinon un m^eme ascendant risque dappara^tre dans plusieurs branches.
Arbres binaires
Un arbre binaire est un ensemble ni, eventuellement vide, de nffuds lies
par une relation de parente orientee :
x Fd y
x 0 Fg y
x est le ls droit de y
= y est le p
ere de x ;
x0 est le ls gauche de y = y est le p
ere de x0 ;
7-1 D
efinitions
89
sin
C:\
dos
x
y
command.com
windows
win.ini
caml
system
camlc
emacs
win32.dll
syst
eme de chiers
a=0?
oui
non
b=0?
oui
?
non
>0
=0
<0
c=0?
oui
S=R
non
S=
S = {c/b}
S = {(b
)/2a}
S = {b/2a}
S=
arbre de d
ecision pour ax2 + bx + c = 0 sur R
C24
vegetal
C13
a feuilles
a aiguilles
C02 = 1
eur
herbe
C23
C12
C12
C22 = 1
sapin
C01 = 1
taxinomie
C11 = 1
C01 = 1
C11 = 1
90
Arbres
c d
a
b
{z
c d
arbres binaires di
erents
7-2
c d
arbre g
en
eral
Repr
esentation en m
emoire
Repr
esentation des arbres binaires
type a b_arbre =
| B_vide
| B_noeud of a * (a b_arbre) * (a b_arbre)
;;
let e
tiquette(a) = match a with
| B_vide -> failwith "arbre vide"
| B_noeud(e,_,_) -> e
and gauche(a) = match a with
| B_vide -> failwith "arbre vide"
| B_noeud(_,g,_) -> g
and droite(a) = match a with
| B_vide -> failwith "arbre vide"
| B_noeud(_,_,d) -> d
;;
7-2 Repr
esentation en m
emoire
91
B noeud
B_vide,
B_vide,
B_vide,
B_vide,
B_vide),
B_vide)),
B_vide),
B_vide)))
1
2
3 4 6 7
Repr
esentation par un vecteur
Les nffuds dun arbre binaire peuvent ^etre numerotes par profondeur croissante et (( de gauche a droite )) a profondeur egale :
1
2
4
8
3
5
10 11 12 13 14 15
92
Arbres
Repr
esentation des arbres g
en
eraux
type a g_arbre = G_noeud of a * (a g_arbre list);;
let e
tiquette(a) = match a with
| G_noeud(e,_) -> e
and for^
et(a) = match a with
| G_noeud(_,f) -> f
;;
(cf. letude des expressions booleennes, section 5-4). Lavantage dune description specialisee est une meilleure lisibilite du code, linconvenient est que les algorithmes generaux de manipulation et parcours darbres doivent ^etre reecrits a
7-2 Repr
esentation en m
emoire
93
e
Liste
Liste
ls1
ls2
gure 16 : repr
esentation dun nffud dans un arbre g
en
eral
Repr
esentation ascendante
La representation (racine,branches) permet un acces facile aux nffuds de
larbre en partant de la racine, ce qui correspond au mode dacces le plus frequent.
Il ny a aucun moyen avec cette representation de conna^tre le pere dun nffud
a partir du nffud lui m^eme. Dans certains cas pourtant, on peut avoir besoin
de remonter vers la racine, par exemple a partir du nom dune ville retrouver
son departement, sa region, son pays, .. . Les arbres binaires parfaits ranges
dans un vecteur permettent cette remontee. Dans le cas general on adopte une
representation inverse :
type a a_noeud = A_vide | A_noeud of a * (a a_noeud);;
let e
tiquette(n) = match n with
| A_vide -> failwith "noeud vide"
| A_noeud(e,_) -> e
and p`
ere(n) = match n with
| A_vide -> failwith "noeud vide"
| A_noeud(_,p) -> p
;;
france
ilefr
paris
bourg
dijon
auxr
=
=
=
=
=
=
A_noeud("France", A_vide);;
A_noeud("^
Ile de France", france);;
A_noeud("Paris", ilefr);;
A_noeud("Bourgogne", france);;
A_noeud("Dijon", bourg);;
A_noeud("Auxerre", bourg);;
France
Ile de France
Paris
Bourgogne
Dijon
Auxerre
94
Arbres
La racine de larbre est reconnue comme telle par son pere particulier :
A_vide. Dans cette repr
esentation il nest pas garanti que deux nffuds appar-
tiennent bien au m^eme arbre, il faut remonter jusquaux racines pour le constater.
On represente donc en fait une for^et non ordonnee plut^
ot quun unique arbre.
Enn, dans le cas o
u lon a besoin de pouvoir monter et descendre dans un arbre,
on peut utiliser une representation mixte o
u chaque nffud contient un lien vers
son pere et un lien vers ses ls.
Repr
esentation
Dans cette representation chaque nffud contient un lien vers son premier ls
et un lien vers son frere suivant appele (( frere droit )) (cf. gure 17). Chaque
nffud na plus que deux liens, eventuellement vides, ce qui transforme un arbre
ordonne quelconque en un arbre binaire dont la racine na pas de ls droit et une
for^et darbres ordonnes en un arbre binaire quelconque. Cette representation nest
pas fondamentalement dierente de celle o
u tous les ls sont ranges dans une liste
cha^nee, mais elle est plus economique en termes de memoire.
a
b
d
e
ef g hi j
kl m
c
h
f
g
d
k
i
j
l
m
Figure 17 : repr
esentation ls gauche - fr
ere droit
7-3
Pour appliquer un m^eme traitement a tous les nffuds de cet arbre, par exemple les compter, les imprimer ou comparer leur etiquette a une valeur donnee, il
faut parcourir larbre. On distingue deux methodes de parcours.
95
traitement pr
exe, traitement inxe et traitement postxe designent des actions ou calculs eventuels a eectuer.
Lordre dapplication de ces traitements est :
pr
exe : nffud, descendants droits, descendants gauches.
inxe : descendants droits, nffud, descendants gauches.
postxe : descendants droits, descendants gauches, nffud.
prfixe
Noeud
postfixe
infixe
96
Arbres
(* a = arbre, n = num
ero postfixe
*)
(* retourne le prochain num
ero postfixe *)
let rec imprime a n = match a with
| B_vide
-> n
| B_noeud(e,g,d) -> let n = imprime g n in
let n= imprime d n in
print_int(n);
print_char(:);
print_string(e);
print_newline();
n+1
;;
let a = B_noeud("France",
B_noeud("Ile de France",
B_noeud("Paris",
B_vide,
B_noeud("5`
eme arr.", B_vide,B_vide)),
B_noeud("Versailles",B_vide,B_vide)),
B_noeud("Bourgogne",
B_noeud("Dijon",B_vide,B_vide),
B_noeud("Auxerre",B_vide,B_vide)))
in imprime a 1;;
1:5`
eme arr.
2:Paris
3:Versailles
4:Ile de France
5:Dijon
6:Auxerre
7:Bourgogne
8:France
- : int = 9
France
Ile de France
Paris
Versailles
Bourgogne
Dijon
Auxerre
5eme arr.
97
Une formule est representee par un arbre dont les feuilles sont etiquetees
par des valeurs et les nffuds internes sont etiquetes par des operateurs unaires ou
binaires. Le constructeur Opn correspond a la repetition dun operateur binaire
associatif pour lequel on specie lelement neutre qui est retourne en guise de
valeur dans le cas dune liste vide. Le caractere postxe du traitement eectue
nappara^t pas clairement dans le code de evalue, mais resulte de la convention
caml comme quoi les arguments dune fonction sont calcules avant que le code de
la fonction soit execute. Par exemple la ligne :
| Op2(op,g,h)
-> op (
evalue g) (
evalue h)
De m^eme, la fonction evalue_liste eectue levaluation recursive des branches dune operation multiple et un traitement inxe entre chaque branche, a
savoir le calcul et stockage des resultats partiels dans accu. Exemple :
let f = Opn(add_int, 0,
[Op2(mult_int, Valeur 1, Valeur 2);
Op2(div_int, Valeur 9, Valeur 3);
Valeur 5;
Opn(mult_int, 1, [Valeur 2; Valeur 3; Valeur 4])])
in e
value(f);;
- : int = 34
98
Arbres
niveau (( de gauche a droite )). Si lon veut eectuer une recherche ou un calcul
sur les nffuds de la for^et alors il sut de modier en consequence linstruction :
do_list traitement for^
et.
Complexite : on suppose que traitement a un temps dexecution constant et donc
que literation de traitement sur une liste a un temps dexecution proportionnel
a la longueur de cette liste. Le temps dexecution dun appel a liste_fils, sans
compter les appels recursifs qui en decoulent, est de la forme T = ad + b o
ua
et b sont des constantes et d le degre du nffud considere. Le temps dexecution
de parcours pour une for^et de k nffuds ayant ensemble k0 ls, non compris le
parcours de la for^et des ls, est de la forme : T 0 = ak0 + ck. Dans le parcours
complet dun arbre, chaque nffud co^
ute donc a + c unites de temps (c seulement
pour la racine) et le temps total de parcours est lineaire par rapport a la taille de
larbre.
7-4 D
enombrements sur les arbres binaires
7-4
99
D
enombrements sur les arbres binaires
Calculs
el
ementaires
Th
eor`
eme :
1. Un arbre binaire a
n nffuds poss
ede n + 1 branches vides.
2. Dans un arbre binaire a
n nffuds, le nombre de nffuds sans ls est
inf
erieur ou
egal a
(n + 1)/2. Il y a
egalit
e si et seulement si tous les
nffuds ont z
ero ou deux ls.
3. La hauteur dun arbre binaire non vide a
n nffuds est comprise entre
blog2 nc et n 1.
D
emonstration :
1. Par recurrence sur n.
2. Soient p le nombre de nffuds ayant un seul ls et q le nombre de nffuds sans
ls. p + 2q = n + 1 (nombre de branches vides) donc q = (n + 1 p)/2.
3. Dans un arbre de taille n la profondeur dun nffud est son nombre dascendants stricts donc est inferieure ou egale a n 1. La hauteur dun arbre est
la plus grande profondeur donc est aussi majoree par n 1.
Un arbre binaire non vide de hauteur h a au plus 1 + .. . + 2h = 2h+1 1
nffuds. Soit a un arbre binaire de taille n et h = blog 2 nc : tout arbre binaire
non vide de hauteur inferieure ou egale a h 1 a au plus 2h 1 < n nffuds
donc la hauteur de a est au moins egale a h.
Application aux calculs de complexit
e
Considerons un arbre de decision binaire (chaque test na que deux issues)
ayant N sorties. Une sortie est une branche vide (il ny a plus de test a faire) donc
cet arbre possede N 1 nffuds et a une hauteur au moins egale a blog2 (N 1)c.
Ceci signie que le nombre de tests a eectuer dans le pire des cas est au moins egal
a 1 + blog2(N 1)c = dlog 2 Ne. On obtient ainsi une minoration de la complexit
e
intrins
eque dun probleme.
Par exemple le tri comparaisons de n elements distincts a une complexite
dans le pire des cas au moins egale a dlog2(n!)e, complexite comptee en nombre
de comparaisons, puisquune issue du tri est une permutation des elements les
remettant dans lordre, permutation bien denie si les elements sont distincts, et
toutes les permutations sont possibles (voir lexercice 7-19 pour une construction
formelle de larbre de decision associe a un algorithme de tri par comparaisons).
Cela prouve que la complexite intrinseque dans le pire des cas du tri par comparaisons est (n ln n).
Le minorant obtenu par cette methode nest pas toujours aussi pertinent.
La recherche du plus grand element dans une liste de taille n produit un arbre
100
Arbres
de decision a n issues (une issue est la la position de ce plus grand element), elle
necessite donc au moins dlog2 ne comparaisons. Mais en realite il est impossible de
conna^tre le plus grand element sans les avoir tous examines, donc la complexite
intrinseque de ce probleme est (n).
Dans le m^eme ordre didees, un calcul dependant de n variables et realise
par des operations binaires ne peut ^etre conduit en moins de log2 (n) unites de
temps dans le pire des cas m^
eme si lon eectue autant dop
erations binaires
en parall
ele que lon veut. Larbre exprimant le calcul a eectuer, dont les nffuds
sont les operateurs binaires et les feuilles sont les variables, possede n feuilles donc
a une hauteur au moins egale a dlog2 ne. Ainsi il est impossible de determiner par
comparaisons le plus grand element dune liste de taille n sur une machine parallele
en moins de dlog2 ne unites de temps, et le minorant est cette fois pertinent (cf.
multiplication en parallele, section 6-1).
Arbres
equilibr
es
Un arbre binaire est dit
equilibr
e en hauteur sil est vide ou si pour tout
nffud x, les branches gauche et droite issues de x ont m^eme hauteur a une unite
pres.
dsquilibre
4
2
1
3
0
2
1
1
0
3
0
2
1
0
0
Figure 19 : arbres
equilibr
e et d
es
equilibr
e
Remarquons que la propriete dequilibre est une propriete globale valable pour
larbre entier et pour tous ses sous-arbres.
Th
eor`
eme
: Soit h la hauteur dun arbre
equilibr
e en hauteur a
n nffuds
1+ 5
et = 2 . Alors log2 (n + 1) 6 h + 1 < log (n + 2).
D
emonstration :
Pour h N soient m(h) et M(h) le plus petit et le plus grand nombre de
nffuds dun arbre equilibre de hauteur h. On a pour h > 2 :
m(h) = 1 + m(h 1) + min(m(h 1), m(h 2)),
7-4 D
enombrements sur les arbres binaires
et donc :
101
m(h) + 1 = ah + b ,
M(h) + 1 = c2h ,
o
u a, b, c sont des constantes independantes de h, = 1+2 5 et = 12 5 (voir
letude de la suite de Fibonacci dans le cours de mathematiques). Compte tenu
des conditions initiales, on obtient :
h+3
)/ 5,
m(h) + 1 = (h+3
M(h) + 1 = 2h+1 .
h+3
h+3
implique h+3 = (m(h) + 1) 5 +
< (m(h) + 2) 5 car
< 1 < 5
donc :
n1
X
Ck Cnk1
(n > 1).
k=0
P
Notons C(z) = n=0 Cnzn la serie generatrice associee. En multipliant la
relation precedente par zn1 et en sommant de n = 1 a , on obtient :
1 1 4z
C(z) C0
2
2
= C(z) zC(z) C(z) + 1 = 0 C(z) =
z
2z
et C etant de classe C au voisinage de 0, le est en fait un . Il estainsi prouve
que, si la serie C a un rayon de convergence non nul alors, C(z) = (1 1 4z)/2z.
Considerons alors la fonction denie par :
1 1 4z
f(z) =
.
2z
f est developpable en serie entiere,
X
X
X
1 1/2
Cn
2n n
n+1 n
z =
an z n
f(z) =
(4)
z =
2 n+1
n+1
n=0
n=0
n=0
102
Arbres
n1
X
ak ank1
k=0
pour n > 1 car les deux membres sont les coecients des developpements en serie
entiere de (f(z) a0 )/z et f(z)2 , et ces fonctions sont egales par construction de f.
Enn, comme a0 = 1 = C0, on peut conclure :
n N, Cn = an =
Cn
2n
.
n+1
n1
X
k=0
= (n 1)Cn +
n1
X
k=0
Cnk1Pk +
n1
X
Ck Pnk1,
k=0
Pn = 4n (n + 2)Cn+1 + (n + 1)Cn
(n > 1).
n
el
ements est donc :
Pn
pn =
n (n ).
nCn
7-4 D
enombrements sur les arbres binaires
103
Le (a) = Le (a0 ) + p + 2.
On en deduit :
Li (n) = nLi(n 1) + Le (n 1),
Le (n) = (n + 1)Le (n 1) + 2 n!
Le (n)
Le (n 1)
2
=
+
,
(n + 1)!
n!
n+1
n
X
1
1
Li (n)
=2
+ . .. +
.
n!
2
k
k=2
el
ements construit aleatoirement est :
Li (n)
2 ln(n).
n n!
104
7-5
Arbres
Exercices
Ecrire
une fonction caml transformant une for^et darbres generaux en un arbre
binaire suivant la convention (( ls gauche - frere droit )) et une fonction eectuant
la transformation inverse.
Exercice 7-6 : repr
esentation fils gauche, fr`
ere droit
Soient a un arbre general ordonne et a0 larbre binaire associe a a dans la representation ls gauche, frere droit. Quel rapport y a-t-il entre les ordres prexe et
postxe des nffuds de a et les ordres prexe, postxe et inxe des nffuds de a0 ?
Exercice 7-7 : arbres binaires parfaits
Soit a un arbre binaire parfait a n nffuds range dans un vecteur v. Peut-on
calculer en memoire constante les indices des successeurs dun nffud dindice i
pour les ordres prexe, inxe, postxe ?
Exercice 7-8 : ordres de parcours inverses
Le parcours prexe inverse dun arbre consiste a traiter un nffud dabord puis
ensuite a parcourir les branches issues de ce nffud en commencant par la derniere
branche. On denit de m^eme lordre postxe inverse et, pour un arbre binaire,
lordre inxe inverse. Comparer ces ordres aux ordres de parcours directs.
Exercice 7-9 : fonctions de parcours
Etudier
les fonctions de parcours suivantes (quel est lordre de parcours, quelle est
la complexite asymptotique du parcours realise en supposant que traitement a un
temps dexecution constant) :
let rec parcours traitement for^
et = match for^
et with
| [] -> ()
| G_noeud(e,f)::suite ->
traitement(e); parcours traitement (f @ suite)
;;
7-5 Exercices
105
Ecrire
une fonction liste_prefixe qui constitue la liste des etiquettes des nffuds
dun arbre binaire suivant lordre prexe. Analyser sa complexite temporelle (il
existe une solution de complexite lineaire par rapport a la taille de larbre).
Exercice 7-11 : impression textuelle dun arbre
Ecrire
une fonction imprime_arbre_binaire qui prend en argument une fonction de
conversion a -> string et un arbre binaire a etiquettes de type a et limprime
sous forme semi graphique. Par exemple, on devra avoir :
imprime_arbre_binaire
string_of_int
(B_noeud(1, B_noeud(2, ...)));;
______1______
/
\
__2__
__9__
/
\
/
\
3
6
10
13
/ \
/ \
/ \
/ \
4
5
7
8
11 12 14 15
1. Ecrire
une fonction est_sous_arbre qui dit si a est un sous-arbre de b (un
sous-arbre est lensemble des descendants dun nffud).
2. Ecrire
une fonction est_inclus qui dit si a est inclus dans b (cest-
a-dire si
a sobtient en supprimant certaines branches dun certain sous-arbre de b).
Exercice 7-13 : arbre dynastique
La gure page suivante presente un extrait de larbre dynastique de la maison de
Bourbon. Ecrire
une fonction liste_rois qui, a partir dun tel arbre, donne la
liste des personnes ayant regne.
Exercice 7-14 : repr
esentation dun arbre par une liste parenth
es
ee
On represente un arbre a par une expression parenthesee :
1
2
3
5
4
106
Arbres
Henri IV
1553{1610
Louis XIII
1601{1643
Louis XIV
1638{1715
Louis le Grand Dauphin
1661{1711
Louis
1682{1712
Philippe
1683-1746
Louis XV
1710{1774
Philippe
1748{1765
Louis
1729{1765
Louis
1751{1761
Louis XVI
1754{1793
Louis-Joseph
1781{1789
Philippe
1730{1733
Louis XVIII
1755{1824
Louis XVII
1785{1795
Charles
1686{1714
Charles X
1757-1836
Louis-Antoine
1775-1844
Charles-Ferdinand
1778-1820
Henri
1820-1883
7-5 Exercices
107
On demande :
1. Une fonction caml qui calcule lexpression parenthesee dun arbre.
2. Une fonction caml qui calcule larbre associe a une expression parenthesee.
Les expressions parenthesees seront representees par des listes selon la declaration :
type a terme = Pargauche | Pardroite | Etiquette of a;;
type a expression_parenth
es
ee == a terme list;;
o
u les champs de type string contiennent la representation en cha^ne de caracteres
de lelement considere et le champ de type int code la priorite dun operateur
binaire. Ecrire
une fonction dimpression pour ce type de formules en imprimant
le minimum de parentheses necessaires pour respecter la priorite des operateurs
binaires. Largument dun operateur unaire sera systematiquement mis entre parentheses.
Exercice 7-16 : arbre binaire
equilibr
e en poids
Soit 21 6 < 1. On note |A| la taille dun arbre binaire A et on dit quun arbre
A est -equilibre en poids si pour tout sous-arbre B de branches G, D, on a :
|G| 6 |B| et |D| 6 |B|. Montrer quun arbre -equilibre de taille n a une
hauteur (ln n).
Exercice 7-17 : arbre binaire
equilibr
e en hauteur
Un arbre binaire est dit equilibre en hauteur a k pres si pour tout nffud x les
branches gauche et droite de x ont m^eme hauteur a k pres (k > 1). Montrer que
la hauteur dun tel arbre a n nffuds est (ln n).
Exercice 7-18 : d
enombrement des arbres a
` n nuds
Soient Gn le nombre darbres generaux ordonnes non etiquetes de taille n et Bn
le nombre darbres binaires non etiquetes de taille n.
1. Quelle relation y a-t-il entre ces quantites ?
2. A un arbre general A on associe lexpression parenthesee, u = [u0, . .., u2n1]
o
u ui est une parenthese ouvrante ou fermante (cf. exercice 7-14). Montrer
quune suite de 2n parentheses represente eectivement un arbre de taille n
si et seulement si elle contient autant de parentheses ouvrantes que de fermantes et si toute sous-suite [u0, . . ., ui] avec i < 2n 1 contient strictement
plus de parentheses ouvrantes que de fermantes. Une telle suite sera dite
(( admissible )).
108
Arbres
3. Soit u = [u0, . .., u2n1] une suite de parentheses contenant autant douvrantes que de fermantes avec u0 = (. On denit la suite :
T (u) = [u0, u2, u3, .. ., u2n1, u1]
(on fait tourner toutes les parentheses sauf la premiere). Montrer quune
et une seule des suites u, T (u), T 2(u), .. ., T 2n2(u) est admissible (faire un
dessin representant la dierence entre le nombre douvrantes et de fermantes
dans [u0, .. ., ui1] en fonction de i et interpreter geometriquement loperation T ).
4. Retrouver ainsi lexpression de Bn en fonction de n.
Exercice 7-19 : Complexit
e en moyenne du tri par comparaisons
1. Soit a un arbre binaire non vide a n nffuds. Montrer que la longueur du
chemin externe de a est minimale (
a n xe) si et seulement si tous les niveaux
de a sauf peut-^etre le dernier sont complets. En deduire que, dans le cas
general, on a Le (a) > (n + 1)blog2 nc.
2. On considere un algorithme de tri par comparaisons A operant sur des listes
de n entiers avec n > 2. Si est une permutation de [[1, n]], on note T le
nombre de comparaisons eectuees par A pour trier la liste ((1), . .., (n)).
Le nombre moyen de comparaisons eectuees par A est :
Tn =
1 X
T
n!
o
u la somme porte sur toutes les permutations de [[1, n]]. En modelisant A
par un arbre de decision, montrer que Tn > blog2 (n! 1)c.
Chapitre 8
Arbres binaires de recherche
8-1
Un arbre binaire non vide etiquete est appele arbre binaire de recherche si
les etiquettes appartiennent a un ensemble totalement ordonne et sil verie lune
des deux conditions equivalentes suivantes :
1. la liste des
etiquettes en ordre inxe est croissante au sens large ;
2. pour tout nffud x d
etiquette e, les
etiquettes des
el
ements de la branche
gauche de x sont inf
erieures ou
egales a
e et les
etiquettes des
el
ements
de la branche droite de x sont sup
erieures ou
egales a
e.
Remarques :
{ La condition 2 implique que letiquette dun nffud est comprise entre celles
des ses ls gauche et droit quand ils existent, mais il ny a pas equivalence.
{ Par denition m^eme, tout sous-arbre non vide dun arbre binaire de recherche
est encore un arbre binaire de recherche.
{ Pour un ensemble donne detiquettes il existe plusieurs arbres binaires de
recherche contenant ces etiquettes, en particulier deux arbres lin
eaires assimilables a des listes ordonnees et des arbres (( mieux equilibres )) (cf. gure 21).
6
5
4
3
2
1
4
5
3
6
5
6
2
1
110
4
2
1
a
3
b
x=2?
6
x=1?
x=3?
b c
x=5?
e
x=6?
g
a
8-2 Insertion
111
8-2
Insertion
Etant
donnes un arbre binaire de recherche a et une etiquette x, on veut
construire un nouvel arbre binaire de recherche b contenant les etiquettes des
nffuds de a et x. Noter que b nest pas entierement specie dans ce probleme
car plusieurs arbres peuvent correspondre au m^eme ensemble detiquettes. La
methode la plus simple consiste a determiner dans quelle branche issue de la
racine de a on peut inserer x, et a realiser cette insertion recursivement.
let rec ins`
ere compare x a = match a with
| B_vide
-> B_noeud(x,B_vide,B_vide)
| B_noeud(e,g,d) -> match compare x e with
| PLUSGRAND -> B_noeud(e,g,ins`
ere compare x d)
| PLUSPETIT -> B_noeud(e,ins`
ere compare x g,d)
| EQUIV
-> a
;;
112
14
4
2
9
16
ins`
ere racine 9
10
6
4
2
14
6
12
10
8
16
12
8
ins`
ere 9
14
4
2
14
16
supprime 10
10
6
12
8
16
9
12
8
8-3 Suppression
113
8-3
Suppression
Soit a un arbre binaire de recherche et x un nffud de a que lon veut supprimer. Si x na pas de ls on le remplace par une branche vide, et sil na quun
ls, y, on remplace la branche de racine x par celle de racine y. Dans les deux
cas on obtient encore un arbre binaire de recherche car aucun nffud ne change
de position par rapport a ses ascendants. Lorsque x a un ls gauche y et un ls
droit z, soient y0 le predecesseur et z0 le successeur de x dans lordre de parcours
inxe. y est le plus a droite des descendants de y et z0 est le plus a gauche des
descendants de z. On peut alors au choix : retirer y0 de la descendance de y ou
retirer z0 de la descendance de z et mettre letiquette du nffud retire a la place de
celle de x. Dans les deux cas la propriete dun arbre de recherche est conservee :
toutes les etiquettes a gauche sont inferieures a celle de la racine qui est inferieure
a toutes les etiquettes a droite.
(* supprime l
el
ement le plus a
` droite dun arbre
*)
(* renvoie l
etiquette supprim
ee et le nouvel arbre *)
let rec suppmax(a) = match a with
| B_vide
-> failwith "suppression impossible"
| B_noeud(e,g,B_vide) -> (e,g)
| B_noeud(e,g,d)
-> let (e,d) = suppmax(d) in
(e,B_noeud(e,g,d))
;;
(* recherche si l
etiquette x figure dans a et la supprime *)
let rec supprime compare x a = match a with
| B_vide
-> failwith "x nest pas dans a"
| B_noeud(e,g,d) -> match compare x e with
| PLUSGRAND -> B_noeud(e,g,supprime compare x d)
| PLUSPETIT -> B_noeud(e,supprime compare x g,d)
| EQUIV
-> if g = B_vide then d
else if d = B_vide then g
else let (e,g) = suppmax(g) in B_noeud(e,g,d)
;;
114
lop
eration de recherche, insertion ou suppression suivante a une complexite temporelle et spatiale moyenne O(ln n). Mais cette propriete nest pas recurrente :
apres une suite dinsertions et de suppressions aleatoires la distribution de probabilite des arbres obtenus nest pas celle des arbres (( construits aleatoirement )),
et nest pas connue theoriquement. Experimentalement il semble que les arbres bien equilibres sont plus frequents que dans le modele (( arbres construits
aleatoirement )) et que la profondeur moyenne reste O(ln n) ([Knuth] vol. 3, ch. 6).
8-4
Exercices
Ecrire
une fonction testant si un arbre binaire est bien un arbre de recherche.
Exercice 8-2 : complexit
e de la cr
eation dun arbre de recherche
Soit Tn le temps maximal de creation dun arbre binaire de recherche a partir dune
liste quelconque de n elements en procedant uniquement a des comparaisons entre
ces elements pour decider des positions dans larbre o
u les placer. Montrer que
n ln n = O(Tn ).
Exercice 8-3 : transformation dun vecteur tri
e en arbre de recherche
Ecrire
une fonction realisant la fusion de deux arbres binaires de recherche. Analyser sa complexite temporelle.
Exercice 8-6 : analyse du tri rapide
Soit une permutation des entiers de [[1, n]]. Montrer que le nombre de comparaisons eectuees lors du tri rapide de la liste ((1), . . ., (n)) est egal au nombre
de comparaisons eectuees lors de linsertion aux feuilles de (1), .. . , (n) dans
cet ordre dans un arbre binaire de recherche initialement vide. En deduire que le
nombre moyen de comparaisons eectuees pour trier rapidement une permutation
aleatoire de [[1, n]] est (n ln n). Le code du tri rapide est :
let rec d
ecoupe a liste = match liste with
| []
-> [],[]
| x::suite -> let (u,v) = d
ecoupe a suite in
if x < a then (x::u,v) else (u,x::v)
;;
let rec quicksort liste = match liste with
| []
-> []
| a::suite -> let (u,v) = d
ecoupe a suite in
(quicksort u) @ (a :: (quicksort v))
;;
Chapitre 9
Manipulation
dexpressions formelles
9-1
Introduction
2.4142136 ou la formule 1 + 2.
{ Les transformations elementaires : developpement dun produit, factorisation, substitution. Le developpement est relativement simple a eectuer
mais produit generalement une formule de grande taille : (1 + x)100 est
transforme en une somme de 101 termes. La factorisation est nettement
plus delicate : on peut facilement factoriser une somme autour dun facteur
commun present dans chaque terme, mais factoriser un polyn^
ome tel que
116
2
x+1
x 1
p
p
ln(x + x2 + 1) + ln(x + x2 + 1) 0.
Comme la factorisation, la simplication est une operation dicile, et ceci
dautant plus que le resultat attendu est deni de maniere ambigue. On peut
dailleurs objecter que (x 1)/(x2 1) et 1/(x + 1) ne sont pas reellement
equivalentes, la deuxieme expression est denie pour x = 1 mais pas la
premiere.
{ La derivation par rapport a une variable : l
a le calcul est facile a conduire
en appliquant les regles de derivation. Le probleme essentiel de la derivation
est la simplication du resultat. Loperation inverse, la primitivation, est
tres dicile a conduire car on ne dispose pas dalgorithme pour cela (mais
il existe des cas particuliers importants dans lesquels la primitivation peut
^etre automatisee, notamment pour les fractions rationnelles et pour les expressions dites (( elementaires )) constituees uniquement dexponentielles, de
logarithmes et de racines dequations polynomiales (algorithme de Risch)).
Levaluation a dej
a ete etudiee lors du parcours dun arbre general (cf. section 7-3). On se limitera dans ce chapitre a la derivation formelle et aux simplications elementaires : regrouper les termes identiques dans une somme ou dans
un produit, regrouper les constantes, eliminer les operations inutiles (0 + x x,
x0 1, .. . ).
9-2
Repr
esentation des formules
expression =
of a
of string
of string * (a expression)
of (a expression) * (a expression)
(*
(*
(*
(*
constante
variable
fonction
somme
*)
*)
*)
*)
9-2 Repr
esentation des formules
| Moins
| Mult
| Div
| Puiss
;;
of
of
of
of
(a
(a
(a
(a
expression)
expression)
expression)
expression)
*
*
*
*
117
(a
(a
(a
(a
expression)
expression)
expression)
expression)
(*
(*
(*
(*
diff
erence
produit
quotient
puissance
*)
*)
*)
*)
Une fonction est identiee par son nom. On supposera quil existe des fonctions
caml feval et fder renvoyant le code devaluation et la derivee dune fonction de
nom donne.
Le type des constantes nest pas specie (a) ce qui permet theoriquement
decrire des algorithmes independants de la representation eective des constantes,
mais il faudra bien coder les operations binaires (Plus, Moins, Mult, Div et Puiss)
entre constantes. Une possibilite est de transmettre en argument aux fonctions de
manipulation les operateurs associes ainsi que les constantes elementaires 0, 1 et
1, mais elle alourdirait le code de ces fonctions. On supposera pour simplier que
les constantes sont de type float. Il sagit certainement dun mauvais choix car les
calculs sur les (( reels machine )) sont approches et les erreurs darrondi peuvent
g^ener la simplication. En pratique, il vaudrait mieux prendre des
constantes
de type entier et accepter des expressions constantes comme 3 2, mais cela
conduirait a developper une bibliotheque de calcul sur les entiers de longueur
arbitraire et les nombres algebriques sortant largement du cadre de ce cours.
Le probleme principal de la representation precedente est la complication
quelle entra^ne pour les simplications elementaires : (x+y)(y+x) est represente
par larbre :
x y y x
et il nest pas immediat de constater sur larbre que les x et les y sen vont. De
m^eme, 2 (x/2) est represente par :
/
x 2
118
expression =
of a
of string
of string * (a expression)
of (a * a expression) list
of (a * a expression) list
(*
(*
(*
(*
(*
constante *)
variable *)
fonction, argument *)
comb. lin
eaire
*)
produit g
en
eralis
e *)
9-2 Repr
esentation des formules
119
normalisees )), mais il faut sengager a les mettre sous forme normale a la n des
calculs. Remarquons enn que les simplications du type :
x1
1
,
2
x
+
1
x 1
p
p
ln(x + x2 + 1) + ln(x + x2 + 1) 0,
ne sont pas prises en compte : la premiere releve dalgorithmes de factorisation et
la deuxieme de regles de simplication fonctionnelles.
Relation dordre
Une maniere simple de comparer deux expressions consiste a les parcourir
simultanement en profondeur dabord jusqu
a ce que lon trouve une dierence.
On declare la premiere expression plus grande ou plus petite que lautre en fonction
de cette premiere dierence si lon en trouve une, egale a lautre si lon nen trouve
pas :
let rec compare e e = match (e,e) with
| (Const(a),Const(b)) ->
else
| (Const(_),_)
->
| (_,Const(_))
->
| (Var(a),Var(b))
| (Var(_),_)
| (_,Var(_))
->
else
->
->
| (Fct(f,u),Fct(g,v)) ->
else
| (Fct(_),_)
->
| (_,Fct(_))
->
| (CL(l),CL(l))
| (CL(_),_)
| (_,CL(_))
-> compare_listes l l
-> PLUSPETIT
-> PLUSGRAND
| (PG(l),PG(l))
-> compare_listes l l
120
< d
esigne a la fois loperateur de comparaison entre reels et celui entre cha^nes
de caracteres. La fonction compare ci-dessus compare successivement tous les
nffuds des expressions e et e0 dans lordre prexe, et termine des quune dierence
est detectee, soit dans un constructeur soit dans une etiquette (valeur dune
constante ou dun coecient, nom dune variable ou dune fonction). Lordre
parmi les constructeurs est deni arbitrairement par :
9-3
D
erivation
Par ailleurs, bien quil soit souhaitable de retourner une expression sous forme
normale, on se limitera dans un premier temps au calcul dune expression de e/x
non simpliee, quitte a la simplier apres coup (voir cependant lexercice 9-7 a ce
sujet).
9-3 D
erivation
121
(ea1 . ..ean ) = a e1 ea11 ea2 . ..ean +. ..+a en ea1 .. .ean1 ean1 pour
1
n
n
n
2
n1 n
x 1
x 1
x 1
des expressions e1, . . ., en et des constantes a1 , .. ., an.
let rec d
erive
| Const(_) ->
| Var(v)
->
| Fct(f,u) ->
| CL(liste) ->
| PG(liste) ->
x e = match e with
Const(0.0)
if v = x then Const(1.0) else Const(0.0)
PG [(1.0,d
erive x u); (1.0,fder f u)]
CL(map (d
eriveCL x) liste)
CL(map (d
erivePG liste x) liste)
and d
eriveCL x (a,e) = (a,d
erive x e)
and d
erivePG liste x (a,e) =
(a, PG( (1.0,d
erive x e) :: (-1.0,e) :: liste ))
;;
map applique la fonction pass
ee en premier argument a la liste passee en deuxieme
1
an
argument. La fonction derivePG accole a liste (representant ea
1 . . . en )
u = match f with
Fct("exp",u)
(*
PG [(-1.0,u)]
(*
CL [(-1.0,Fct("sin",u))] (*
Fct("cos",u)
(*
(* autres
Fct(f^"",u)
(*
exp(u) = exp(u)
ln(u) = u^-1
cos(u) = -sin(u)
sin(u) = cos(u)
d
eriv
ees usuelles
f(u) = f(u)
*)
*)
*)
*)
*)
*)
122
u0
f0
u
f0
u
qui est a priori au moins egal a la taille de u. Lorsque f0 est compliquee, u
peut appara^tre plusieurs fois. Par exemple si lon dispose dans la batterie des
fonctions usuelles de la fonction secante (sec x = 1/ cos x) alors la derivation de
sec (u) produit larbre :
u0
sec
tan
car sec0 (x) = sec(x) tan(x) (ou sin(x)/ cos 2(x)). En fait, dans limplementation de
caml, les sous-arbres ne sont pas recopies et toutes les donnees complexes sont
referencees par des pointeurs, donc larbre precedent est en realite un graphe :
u0
sec
tan
u
9-3 D
erivation
123
#simplifie(e);;
- : float expression =
___CL____
/
\
*
___*____
/ \
/
\
2.0 x
-2.0
sin
|
_CL__
/
\
*
*
/ \
/ \
1.0 t 2.0 x
Figure 24 : d
erivation et simplication
124
a1
e01
a2
e1
1
e02
e1
2
a3
e03
e1
3
1 a2 a3
ea
1 e2 e3
9-4
Simplification
9-4 Simplification
125
sans avoir besoin de simplier les autres facteurs, mais il nest pas garanti que
cela suse, il se peut quun facteur savere nul apres simplication seulement. La
validite de la simplication postxe est justiee ci-apres.
Algorithme de simplification
{ Une constante et une variable sont d
ej
a simpli
ees.
{ Soit e = f(u) o
u f est une fonction et u une expression : simplier u
en u0 puis, si u0 est une constante et f est
evaluable, remplacer e par la
constante f[u0] sinon par lexpression f(u0 ).
{ Soit e = a1 e1 + ... + an en o
u les ai sont des coecients et les ei des
expressions : simplier chaque ei en e0i. Si e0i est une combinaison
lin
eaire, distribuer le coecient ai . On obtient ainsi une combinaison
lin
eaire b1 f1 + ... + bp fp o
u les bj sont des coecients et les fj des
expressions simpli
ees et ne sont pas des combinaisons lin
eaires. Trier
la liste et regrouper les termes correspondant a
la m^
eme sous-expression,
supprimer les termes ayant un coecient nul, regrouper les constantes
en une seule avec coecient 1 si elle est non nulle, aucune sinon. Si
la liste obtenue est vide, remplacer e par z
ero ; sil ne reste plus quun
terme, f, avec un coecient 1, remplacer e par f sinon remplacer e par
la combinaison lin
eaire obtenue.
an
1
u les ai sont des exposants et les ei des expres{ Soit e = ea
1 ... en o
sions : simplier chaque ei en e0i . Si e0i est un produit g
en
eralis
e, distribuer lexposant ai . Si e0i est une combinaison lin
eaire a
un seul terme,
e0i = af, la transformer en produit af puis distribuer lexposant ai (il est
possible ici que f soit aussi un produit, distribuer lexposant sur chaque
facteur dans ce cas). Trier la liste des facteurs obtenue en regroupant
les facteurs
egaux et en supprimant les facteurs ayant un exposant nul.
Regrouper toutes les constantes en une seule, c, et soit f la liste des
facteurs restants. Si f est vide, remplacer e par la constante c ; si c = 0
remplacer e par z
ero ; si c = 1 et f ne contient quun terme g avec
un exposant aussi
egal a
1, remplacer e par g ; si c = 1 et f contient
plusieurs facteurs ou un facteur avec un exposant di
erent de 1, remplacer e par PG(f) ; si c 6= 1 et f ne contient quun terme, g, qui est une
combinaison lin
eaire avec un exposant 1, distribuer c et remplacer e par
la combinaison lin
eaire obtenue ; dans tous les autres cas remplacer e
par la combinaison lin
eaire cPG(f).
126
Terminaison
Montrons par recurrence sur la hauteur h de e que la simplication de e
termine : pour h = 0, e est une feuille, donc une constante ou une variable et
la terminaison est evidente. Si la simplication termine pour toute expression de
hauteur h1 et si e est de hauteur h alors e est de la forme f(u) ou a1e1 +. . .+an en
an
1
ou ea
ees par hypothese en
1 . ..en : la branche u ou les branches ei sont simpli
un temps ni, et il reste a verier quon eectue un nombre ni doperations apres
simplication des branches. Cest immediat si e = f(u).
Si e = a1 e1 + . .. +an en il faut verier quon nappliquera pas une innite de
fois la regle de distributivite : on constate ici que lalgorithme est incompletement
specie puisquil nest pas dit si lon doit distribuer recursivement le coecient
ai dans le cas o
u e0i contient des combinaisons lineaires imbriquees. On peut remarquer que ceci ne peut pas se produire si lalgorithme est correct puisque e0i
est supposee simpliee, mais la correction de lalgorithme nest pas prouvee . . .
Cette situation peut se regler de plusieurs manieres : demontrer dabord la correction ou la demontrer ensuite mais en veriant quon nutilise pas lhypothese de
terminaison, demontrer en m^eme temps la correction et la terminaison puisquici
on a besoin de lhypothese de correction au rang h 1 et non h, revoir la description de lalgorithme en precisant quon ne distribue pas recursivement (cette
precision ne changeant rien si lalgorithme est correct) ou remarquer que, m^eme si
lon distribue recursivement, il y a un nombre ni de e0i chacun ayant un nombre
ni de descendants, donc on ne pourra pas appliquer une innite de fois cette
regle de distributivite. Une fois la distribution des coecients eectuee, le tri
des termes, leur regroupement et lelimination des constantes prennent un temps
manifestement ni donc la simplication dune combinaison lineaire de hauteur h
termine.
Si e est un produit generalise de hauteur h, on constate comme dans le cas
precedent quon obtient en un temps ni une liste de facteurs isoles, la transformation des combinaisons lineaires a un seul terme en produit ne pouvant ^etre eectuee
une innite de fois m^eme si elle est appliquee recursivement. Lelimination des
facteurs constants et les simplications nales ont aussi un temps dexecution ni
donc par recurrence, lalgorithme de simplication termine !
Correction
Dej
a, on montre par une recurrence immediate que lexpression e0 deduite
de e par simplication est equivalente a e sous lhypoth
ese que les calculs sur
les constantes sont exacts. Avec des constantes de type float il ny a aucune
garantie dequivalence et e0 est seulement une approximation de e ce qui ne veut
rien dire dans labsolu. En supposant les calculs exacts, il reste a prouver que e0
satisfait aux conventions de normalisation denies en 9-2, ce qui se fait encore
par recurrence sur la hauteur h de e :
{ Aucun terme dune combinaison lin
eaire nest lui-m^
eme une combinaison lin
eaire : si e est une combinaison lineaire, les termes simplies e0i
ne contiennent pas de combinaisons lineaires imbriquees par hypothese de
9-4 Simplification
127
recurrence et si e0i est une combinaison lineaire elle est eclatee par distributivite donc e0 ne contient pas de combinaison lineaire imbriquee. Si e est
un produit generalise, les facteurs e0i ne contiennent pas de combinaisons
lineaires imbriquees et e0 est soit un produit de certains de ces termes (ou de
leurs descendants), soit une combinaison lineaire de produit avec plusieurs
facteurs ou un seul si son exposant est dierent de 1, soit lun des e0i ou un
descendant. En aucun cas, e0 ne contient de combinaison lineaire imbriquee.
Lorsque e est une constante, une variable, ou de la forme f(u) il ny a pas
creation de nouvelle combinaison lineaire donc l
a encore e0 ne contient pas
de combinaison lineaire imbriquee.
{ Aucun facteur dun produit g
en
eralis
e nest lui-m^
eme un produit g
en
eralis
e : par un raisonnement analogue.
{ Les sous-expressions dune combinaison lin
eaire ou dun produit g
en
eralis
e sont tri
ees, deux expressions successives
etant distinctes ;
{ dans une combinaison lin
eaire, aucun coecient nest nul et toutes les
constantes sont regroup
ees en une seule (avec coecient 1) si elle est
non nulle, en aucune sinon ;
{ dans un produit g
en
eralis
e, aucun exposant nest nul et il ny a pas de
facteur constant ;
{ un produit g
en
eralis
e comporte au moins deux facteurs ou un seul facteur avec un exposant di
erent de 1 :
par construction.
Complexit
e
Soit e une expression de taille n que lon simplie en e0. Chacune des regles de
simplication reduit le nombre de nffuds de lexpression manipulee, sauf peut-^etre
la regle stipulant de remplacer un produit ayant un coecient multiplicatif c 6= 1
par une combinaison lineaire a un terme de coecient c. Mais il est impossible
dobtenir un coecient c 6= 1 sil ny a pas de facteur constant dans le produit
apres simplication des facteurs et eclatement des produits imbriques. On cree
un nffud supplementaire (la combinaison lineaire) en ayant supprime au moins un
facteur (constant) donc cette derniere regle naugmente pas le nombre de nffuds
de lexpression a simplier. Ainsi, il est garanti que e0 a moins de nffuds que e et
que, au moins en ce sens, e0 est plus simple que e.
Soit T (e) le temps de simplication de e. On a les relations de recurrence :
T (e) 6
T (f(u)) 6 + T (u),
T (a1 e1 + . .. + ap ep ) 6 T (e1 ) + . .. + T (ep ) + n ln n,
a
p
1
T (ea
1 . ..ep ) 6 T (e1 ) + . .. + T (ep ) + n ln n,
128
deuxieme hypothese ne va pas de soi car il faut tenir compte du temps de comparaison de deux expressions de tailles arbitraires, ce temps est considere ici comme
constant en moyenne. Si Tn designe le temps de simplication dune expression
de taille n dans le pire des cas, on a donc :
T1 6 ,
Tn 6 max( + Tn1,
Tn1 + .. . + Tnp + n ln n, p > 1, ni > 1, n1 + . .. + np = n 1),
pour n > 2.
6 Xn .
n1
X
k ln k + . .. +
k=2
{z
np
X
k=2
np1 termes
k ln k +n ln n
}
+
+
e1
e2
e3
e4
e5
+
e6
9-5 Exercices
9-5
129
Exercices
1. Ecrire
une fonction figure qui dit si f gure dans e. e et f seront supposees
sous forme normale.
2. Ecrire
une fonction substitue qui remplace dans e chaque occurrence de f
par une autre expression g. Il nest pas demande de simplier le resultat.
Exercice 9-3 : complexit
e de la d
erivation
Montrer que les complexites temporelle et spatiale de derive sont O(n2) pour une
expression de taille n sil y a recopie des sous-arbres lors de la derivation de f(u)
ap
1
ou de ea
1 . ..ep .
Exercice 9-4 : d
erivation optimis
ee
Si une expression e comporte des sous-arbres partages, peut-on eviter de calculer
plusieurs fois la derivee dun sous-arbre ?
Exercice 9-5 : taille dun arbre avec partage
Si lon admet le partage des sous-arbres et si lon considere quun nffud a p ls
occupe p + 1 mots memoire, quel est le plus gros arbre que lon peut stocker dans
n mots memoire ?
Exercice 9-6 : simplification
Transcrire en caml lalgorithme de simplication du cours.
Exercice 9-7 : d
erivation et simplification
Quelle est la meilleure strategie : deriver puis simplier, deriver et simplier en
m^eme temps ?
Chapitre 10
Langages r
eguliers
Il fait beau
kzw30 xxx tfgrd
la maison mange le chat
x=3
Vues comme suites de caracteres, chacune de ces phrases est bien formee ;
vues comme suites de mots francais, les phrases 1 et 3 sont bien formees, la phrase
2 ne lest pas car elle contient au moins un mot non francais. Dun point de vue
grammatical, les phrases 1 et 3 sont aussi bien formees : sujet, verbe, complement
dobjet ; mais dun point de vue s
emantique la phrase 3 na pas dinterpretation
valide. La phrase 4 est bien formee selon les regles du langage caml, et admet une
interpretation valide (expression booleenne disant si x vaut 3), elle est aussi bien
formee pour le langage c et admet une interpretation dierente (placer la valeur
3 dans la variable x). Les problemes lies aux langages sont :
9-5 Exercices
131
{ Denir un langage du point de vue lexical (lettres autorisees, regles dassemblage des lettres en lexemes), syntaxique (regles dassemblage des lexemes
en phrases) et s
emantique (interpretation dune phrase valide). Lorsque le
langage nautorise quun nombre ni de suites, il sut de les lister toutes
et de donner leur interpretation, cest ce que fait un dictionnaire pour la
description lexicale du francais. Par contre lorsque le langage est inni, il
sagit de donner une description nie et non ambigue de toutes les suites
autorisees, et de leur interpretation.
{ Decomposer une suite de lettres en lexemes (analyse lexicale), reconna^tre
si une suite de lexemes est valide (analyse syntaxique) et determiner son
interpretation (analyse semantique).
{ Traduire une phrase valide pour un langage en une phrase valide pour un
autre langage en respectant au mieux le sens de la phrase.
La division de la description dun langage en une description lexicale et une
description syntaxique permet de simplier la description globale du langage. Par
exemple pour le francais il est plus simple de donner la liste des mots, chaque mot
etant qualie par un attribut (nom, adjectif, verbe transitif,. .. ) et les regles de
formation des phrases :
sujet, verbe, compl
ement dobjet, "."
verbe, sujet, compl
ement dobjet, "?"
verbe, compl
ement dobjet, "!"
...
plut^
ot que de donner toutes les phrases possibles (qui sont en nombre inni dans
le cas du francais compte tenu des propositions subordonnees).
En ce qui concerne les langages informatiques, lanalyse lexicale et syntaxique dun texte est eectuee par un compilateur ou un interpr
eteur. Le compilateur reconna^t un programme source valide et le traduit en un programme
executable (liste dinstructions machine). Linterpreteur reconna^t une phrase
valide, la traduit en instructions machine et execute ces instructions avant de
passer a la phrase suivante. Il ny a pas danalyse semantique, aucun logiciel
(connu de lauteur a ce jour) nest en mesure de dire que le programme :
let rec myst`
ere(a,b) = if b = 0 then a else myst`
ere(b,a mod b);;
Langages r
eguliers
132
10-1
D
efinitions
Un alphabet est un ensemble ni non vide dont les elements sont appeles
lettres. Un mot sur lalphabet A est une suite nie, eventuellement vide, de
lettres. On ecrit u = a1a2 .. .an pour designer la suite (a1 , .. ., an). Le mot vide
est note . La longueur dun mot u est notee |u|. Si u est un mot sur A et x
une lettre de A, on note |u|x le nombre doccurrences de x dans u. Lensemble
de tous les mots sur A est note A . Un langage sur A est un ensemble de mots,
cest-
a-dire un sous-ensemble de A . Il peut ^etre ni ou inni.
Exemples :
{ A = {0, 1} (chires binaires). A est lensemble de toutes les suites nies
constituees de 0 et de 1. Lensemble L des suites de 0 et de 1 commencant par
un 1 constitue un langage sur A. L peut ^etre interprete comme lensemble
des representations en base 2 des entiers naturels non nuls, ceci constitue
une interpretation de L. On peut aussi interpreter un mot de L comme la
representation binaire dun entier impair en lisant les chires de droite a
gauche, ou comme une suite de tirages a pile ou face commencant par pile.
{ A = {a, b, c, .. ., z}, L = {mots francais non accentues et sans trait dunion}.
Ici L est un langage ni.
{ A = {0, 1, .. ., 9, +, , , /, (, )}, L est lensemble des expressions arithmetiques
correctement parenthesees (ceci constitue une description ambigue quil faudrait preciser). Un mot de L peut en general ^etre interprete de plusieurs
manieres : 3 + 4 5 peut ^etre interprete comme 3 + (4 5) ou (3 + 4) 5, il faut
xer des regles de priorite pour decider quelle est la (( bonne )) interpretation.
Op
erations sur les mots
Deux mots u = a1 .. .an et v = b1 . . .bp sur un m^eme alphabet A peuvent
^etre juxtaposes pour former le mot uv = a1 . . .an b1 . ..bp appele concat
enation
de u et v. En identiant les lettres de A et les mots a une lettre, lecriture a1 . . .an
peut ^etre interpretee comme le mot constitue des lettres indiquees ou comme le
produit de concatenation des mots a une lettre indiques. Ces deux interpretations
denissent clairement le m^eme mot. On a les proprietes :
|uv| = |u| + |v| ;
10-2 Op
erations sur les langages
133
Pour u A et n N , on note u0 = et un = u
. . . u}.
| u{z
n facteurs
Si u et v sont des mots sur A, on dit que u est un facteur de v sil existe
deux mots v0, v00, eventuellement vides, tels que v = v0uv00. Lorsque v0 = on dit
que u est un pr
exe de v, et lorsque v00 = on dit que u est un suxe de v.
Si u = a1 . ..an o
u les ai sont des lettres, limage miroir de u est u
~ = an .. .a1 .
10-2
Op
erations sur les langages
L(M + N) = LM + LN ;
(M + N)L = ML + NL ;
(L + M) = (L M) L = L (ML ) (regle de Lazard).
Lintersection et le complementaire nont par contre pas de (( bonne )) pro
priete vis-
a-vis de la concatenation : L 6= L ( appartient au premier et pas
au second) et L(M N) 6= (LM) (LN) (par exemple L = A , M et N les sousensembles des mots de longueur paire, de longueur impaire).
Langages r
eguliers
134
Expressions r
eguli`
eres
Une expression r
eguli
ere sur lalphabet A est une formule de longueur nie
correctement parenthesee utilisant uniquement les operations somme, concatenation et etoile, le langage vide et les langages reduits a un mot : {u} o
u u est un
mot quelconque sur A. Pour alleger les notations, on ecrira u pour le langage {u}.
Un langage L est dit r
egulier sil peut ^etre decrit par une expression reguliere.
Un langage regulier est aussi dit rationnel pour des raisons liees a la theorie des
series formelles.
Exemples :
{ Sur un alphabet A, le langage L constitue des mots de longueur paire :
L = {u tq |u| 2N} est regulier car il est decrit par lexpression L = (AA)
(ici A est une abreviation pour la somme de toutes les lettres, ce qui constitue
une expression reguliere puisque A est ni).
{ Sur lalphabet A = {0, 1} le langage L des mots commencant par 1 est decrit
par lexpression reguliere L = 1(0 + 1) , il est donc regulier. Sur le m^eme
alphabet, le langage L0 constitue des mots contenant exactement trois fois la
lettre 1 est decrit par lexpression reguliere L0 = 0 1010 10.
{ Sur lalphabet A = {a, . .., z} le langage des mots contenant comme facteur
lun des mots : facteur ou factrice est deni par lexpression reguliere :
L = A fact(eur + rice)A. Les expressions regulieres :
(A facteurA) + (A factriceA)
A (facteur)(facteur + factrice)(factrice)A
denissent le m^eme langage, ce qui montre quil ny a pas unicite dune
expression reguliere denissant un langage regulier donne.
{ Le langage des parentheses embo^tees est deni par L = {an bn tq n N}
o
u A = {a, b}, a designant une parenthese ouvrante et b une parenthese
fermante. Ce langage nest pas regulier, voir une demonstration a la section 11-6 et une autre demonstration dans lexercice 10-8.
Par denition m^eme, la somme, le produit de deux langages reguliers et
letoile dun langage regulier sont encore reguliers, mais il nest pas evident que
lintersection de deux langages reguliers ou le complementaire dun langage regulier
le soient. On verra au chapitre suivant que cest cependant le cas. Par ailleurs, tout
langage ni est regulier puisquil est la somme des mots quil contient. Enn, si L
~ lest aussi : on obtient une expression reguliere pour
est un langage regulier, alors L
~ en permutant recursivement les operandes des concatenations et en remplacant
L
les mots par leurs images miroir dans une expression reguliere pour L
un langage r
10-3 Appartenance dun mot a
egulier
10-3
135
= (* a est le
(*
(a vect)
(*
(a exp) * (a
(a exp) * (a
(a exp)
cest-
a-dire que appartient(e2,w) nest pas evalue si appartient(e1,v) retourne
false, et d
ecoupe(e1,e2,u,i+1) nest
evalue que si lun des deux appels a appartient a retourn
e false. On remarque que chaque appel recursif a appartient
porte sur une expression plus petite (en nombre de nffuds) et un mot plus petit,
Langages r
eguliers
136
lune des deux inegalites etant toujours stricte car on traite a part lappartenance
du mot vide a une expression E . Donc appartient termine et on demontre par
recurrence sur max(|exp|, |u|) que le booleen retourne est correct.
Il ne sagit certainement pas dun algorithme ecace : par exemple pour constater que le mot aab nappartient pas au langage deni par lexpression (a + b) c,
on essaie successivement :
(a + b) et aab c ?
a (a + b) et (a + b) et ab c ?
a (a + b) et a (a + b) et (a + b) et b c ?
a (a + b) et a (a + b) et b (a + b) et (a + b) et c ?
Il y a donc repetition des m^emes tests, repetition due aux (( points de
decoupage )) multiples pour reconna^tre une concatenation et pour reconna^tre
une etoile. Plus precisement, si lexpression reguliere est la concatenation de k
expressions simples (mots ou sommes de mots), alors on teste dans le pire des cas
toutes les possibilites de placer k points de decoupage entre les lettres de u, soit
pour un mot de longueur n, Ckn+1 essais. Compte tenu des court-circuits booleens
eectues par le compilateur caml, il nest pas evident que tous ces essais soient
eectues, mais cela se produit certainement si chaque essai echoue lors du dernier
test compile. A k xe la complexite dans le pire des cas de la reconnaissance pour
un mot de longueur n a un langage de la forme L1 . . .Lk cro^t au moins aussi vite
que nk .
Si lexpression reguliere est de la forme L , alors on teste dans le pire des
cas tous les decoupages de u en facteurs de longueur superieure ou egale a 1,
donc tous les sous-ensembles de positions distinctes entre les lettres de u et il y
a 2n tels sous-ensembles. Dans le cas general, la complexite de appartient pour
une expression reguliere donnee comportant au moins une etoile et pour un mot
arbitraire de longueur n est au moins exponentielle.
10-4
Exercices
10-4 Exercices
137
X = KX + LY + M
Y = K0 X + L0 Y + M0
admet une solution unique (que lon ne demande pas dexpliciter), et que si
K, K0, L, L0 , M, M0 sont reguliers, alors X et Y sont aussi reguliers.
Exercice 10-7 : expression sans ni
Soit L un langage regulier non vide et ne contenant pas le mot vide. Montrer quil
existe une expression reguliere denissant L ne faisant intervenir ni ni .
Exercice 10-8 : langage non r
egulier
Soient L = {an bn tq n N} le langage des parentheses embo^tees et pour p N,
Lp = Lbp et Lp = ap L. Montrer que tout langage regulier inclus dans un Lp
(p Z) est ni. Ceci demontre que L nest pas regulier.
Chapitre 11
Automates finis
11-1
D
efinitions
M
3
M
D
2
D
1
D
0
D
automate
dascenseur
11-1 D
efinitions
139
a
b
0
a
b
1
2
a
a,b
0
0
1
1
1
2
2
0
0
0
3
3
0
0
1
bloque
a
2 3
a
0
a
1
a
2
140
Automates finis
u
1
b
a
2
a
0..9
0..9
0 +*/
141
0..9
0..9
E
7 0..9
6 +
0..9
a..z
3
a..z,0..9
e
e
0
_
1
_
e
n
2
_
e
e
3
_
4
_
e
i
11-2
142
Automates finis
0
1
2
3
4
5
6
e
1
1
1
4
1
1
1
n
m
0
0
2
0
3
0
0
0
2
5
0
0
1 1
i
0
0
0
0
0
0
0
0
0
0
6
0
1 1
(e,l) with
0
2 | (1,_)
3 | (2,_)
0
2 | (4,m)
6 | (5,_)
-> 0
-> 0
-> 5 | (4,_) -> 0
-> 0
inconnu"
143
(* a est un automate d
eterministe, u un mot a
` analyser *)
(* dit si u appartient au langage de a.
*)
let analyse(a,u) = try
let e = ref(a.d
epart) in
for i = 0 to vect_length(u)-1 do
e := a.transition(!e,u.(i))
done;
a.final(!e)
with Failure "transition ind
efinie" -> false
;;
La correction de analyse est immediate, et sa complexite pour un automate a donne est proportionnelle a la longueur de u sous reserve que la fonction
a.transition sex
ecute en un temps constant.
On peut aussi representer un automate par un ensemble de fonctions mutuellement recursives o
u chaque appel recursif correspond a une transition :
let rec e
tat_0(u) = match u with
| e :: v -> e
tat_1(v)
| _
:: v -> e
tat_0(v)
| _
-> false
and e
tat_1(u)
| e :: v ->
| n :: v ->
| _
:: v ->
| _
->
= match u with
e
tat_1(v)
e
tat_2(v)
e
tat_0(v)
false
and e
tat_2(u)
| e :: v ->
| n :: v ->
| _
:: v ->
| _
->
= match u with
e
tat_1(v)
e
tat_3(v)
e
tat_0(v)
false
and e
tat_3(u)
| e :: v ->
| _
:: v ->
| _
->
= match u with
e
tat_4(v)
e
tat_0(v)
false
and e
tat_4(u)
| e :: v ->
| n :: v ->
| m :: v ->
| _
:: v ->
| _
->
= match u with
e
tat_1(v)
e
tat_2(v)
e
tat_5(v)
e
tat_0(v)
false
and e
tat_5(u)
| e :: v ->
| i :: v ->
| _
:: v ->
| _
->
= match u with
e
tat_1(v)
e
tat_6(v)
e
tat_0(v)
false
and e
tat_6(u) = true
;;
Un mot u (represente ici par une liste cha^nee de lettres) est reconnu si et
seulement si lappel etat_0(u) retourne true. Ce codage est moins compact que
la fonction de transition denie plus haut, mais chaque fonction de transition
sexecute plus rapidement puisquelle na a examiner que la premiere lettre du
mot propose et non le couple (
etat, lettre). Tous les appels recursifs sont terminaux, donc lanalyse dun mot peut ^etre compilee de maniere a sexecuter en
memoire constante. Le logiciel camllex est un generateur de programmes : a partir
144
Automates finis
etant donn
es un automate non d
eterministe sans -transitions, un ensemble I d
etats initiaux, un ensemble F d
etats nals et un mot u,
d
eterminer si lon peut passer dun
etat de I a
un
etat de F en suivant
les transitions correspondant aux lettres de u.
Ce probleme sapparente a un parcours de graphe o
u lon cherche un chemin
menant dune source a un but dans un graphe oriente a priori quelconque. Il existe
essentiellement deux solutions a ce probleme, le parcours en profondeur dabord
du graphe : on suit un chemin aussi loin que possible, puis on revient recursivement
sur les choix eectues en cas dimpasse ; et le parcours en largeur dabord :
on explore en parallele tous les chemins possibles. La methode du parcours en
profondeur dabord sapparente a lalgorithme presente a la section 10-3 pour la
reconnaissance dune expression reguliere. Lalgorithme de parcours en largeur est
simple : determiner tous les successeurs autorises de tous les etats de I compte
tenu de la premiere lettre de u, et appliquer recursivement lalgorithme avec cet
ensemble de successeurs et la suite de u.
(* a est le type des e
tats, b est
type (a,b) automate_nd = {
d
epart : a list;
final : a -> bool;
transition : (a * b) -> a list
};;
145
1);
(0,a)
(0,b)
(1,c)
(2,a)
(2,b)
_
->
->
->
->
->
->
[0;2]
[1]
[1]
[2]
[1]
[])
146
11-3
Automates finis
D
eterminisation dun automate
11-4 Le th
eor
eme de Kleene
147
b
a
depart
{0}
{0}
{1, 4}
{1, 4}
{0, 2, 3}
{0, 2, 3}
{1, 2, 3, 4}
{1, 2, 3, 4}
b
a
1
4
a
a
3
lettre
a
b
a
b
a
b
a
b
arrivee
{1, 4}
{0, 2, 3}
{1, 2, 3, 4}
{1, 2, 3, 4}
{0, 2, 3}
table de transition
14
a
023
1234
11-4
Le th
eor`
eme de Kleene
Th
eor`
eme : soit L un langage sur un alphabet A. Il y a
equivalence entre :
1. L est d
eni par une expression r
eguli
ere.
2. L est reconnu par un automate ni.
D
emonstration de 1 = 2 (construction de Thompson)
L est represente par une expression reguliere E que lon assimile a un arbre comme a la section 10-3. On construit recursivement un automate non
deterministe E 0 qui simule le parcours de E : a chaque nffud n de E on associe deux etats dans E 0, un etat dentree et un etat de sortie (un seul etat pour un
nffud de type Etoile). On place des -transitions entre ces etats et ceux des ls
de n comme indique gure 30, et des transitions sur lettre entre les lettres dune
feuille de type Mot (ou une -transition dans le cas du mot vide). Les feuilles
correspondant au langage vide nont pas de transition denie. Il est clair, par
recurrence sur la taille de E, que E 0 reconna^t exactement le langage decrit par
lexpression reguliere E.
148
Automates finis
Somme
Concatnation
Etoile
Mot
Vide
mot
vide
uvxyz
M
(L+M)
(LM)
(M*)
(uvxyz)
15
11
12
10
13
14
11-4 Le th
eor
eme de Kleene
149
a,c
1
18
b
a,b
a,b,c
a,b
a,c
10
a,c
a,b
u
v
gure 33 : suppression de l
etat u
Considerons un etat u de A autre que x ou y. On construit un automate
A0 , lui aussi indexe par des expressions regulieres, ayant pour etats tous les etats
de A sauf u, et tel que pour tous etats v, w de A0 on ait LA0 (v, w) = LA(v, w).
150
Automates finis
par v +
w (cf. gure 33). Ceci etant fait pour tous couples (v, w), on
obtient un automate A0 qui verie LA0 (v, w) = LA(v, w) pour tous etats v, w. Le
m^eme procede peut ^etre applique a A0 et de proche en proche on aboutit a lun
des automates A00 ou A000 de la gure 34 selon que x = y ou x 6= y o
u , , ,
et sont des expressions regulieres.
A00
A000
gure 34 : automates r
eduits
Donc LA(x, x) = LA00 (x, x) = ou LA (x, y) = LA000 (x, y) = (+ ) sont
des langages reguliers et ceci acheve la demonstration du theoreme de Kleene.
Exemple : considerons lautomate ordinaire non deterministe gure 35 (
a gauche).
En supprimant dabord les etats 1 et 4 puis letat 2 et enn letat 3, on obtient
limposante expression :
ab + ab(ab) ab + (ab + ab(ab) a(ab + a(ab) a) (ab + a(ab) ab))
pour le langage reconnu. En appliquant la m^eme technique a lautomate deterministe equivalent obtenu en 11-3, on obtient une expression plus simple :
+ ab(aa b) .
Cest un excellent exercice de patience que de montrer a
la main lequivalence
de ces deux expressions. Ainsi, le langage reconnu par lautomate est forme du
mot vide et de lensemble des mots constitues des lettres a et b, commencant par
ab, se terminant par b et ne contenant pas deux b consecutifs.
b
a
ab
b
1
ab
ab
ab+a(ab)*ab
a
a
ab+ab(ab)*a
ab
ab
ab+ab(ab)*ab
ab
ab
ab+a(ab)*a
11-5 Stabilit
e et algorithmes de d
ecision
11-5
151
Stabilit
e et algorithmes de d
ecision
Th
eor`
eme : soient L, L0 deux langages r
eguliers sur un alphabet A. Alors
les langages L, L L0 et L \ L0 sont r
eguliers.
D
emonstration : on a L L0 = L + L0 et L \ L0 = L + L0 donc il sut de prouver
que L est regulier. Soit A un automate deterministe reconnaissant L. On peut
supposer que A est complet car si ce nest pas le cas, on peut ajouter a A un
etat rebut et diriger vers cet etat toutes les transitions indenies dans A, et faire
boucler letat rebut sur lui-m^eme pour toutes les lettres de A. On suppose donc
que pour tout mot u A , il existe un unique etat xu de lautomate complete
u
tel que q0
xu o
u q0 est letat initial de A. Alors L est lensemble des mots u
tels que xu F o
u F designe lensemble des etats nals de A, et L est lensemble
des mots u tels que xu F, cest-
a-dire que L est reconnu par le m^eme automate
que L en changeant lensemble des etats nals en son complementaire.
Il est ainsi possible, a partir dune expression reguliere E denissant un langage L, de construire par programme une expression reguliere E 0 denissant le
langage L : on construit un automate reconnaissant L, on le transforme en automate deterministe et on le complete, on echange les etats nals et non nals et on
reconstruit une expression reguliere, probablement abominable, pour lautomate
obtenu. De m^eme on peut par programme trouver une expression reguliere reconnaissant lintersection ou la dierence de deux langages denis par des expressions
regulieres.
Compte tenu de la taille des expressions obtenues, les algorithmes precedents
sont pratiquement de peu dutilite. Cependant, dun point de vue theorique, il
existe donc des algorithmes repondant aux questions suivantes :
{ Un langage deni par une expression reguliere est-il vide ? L = M + N est
vide si et seulement si M et N le sont ; L = MN est vide si et seulement si
M ou N lest ; L = M nest jamais vide. On peut donc ramener le probleme
de la vacuite au m^eme probleme pour des expressions regulieres plus courtes
et les cas de base, , , lettre ou mot sont evidents. En termes dautomates,
on peut determiner si le langage reconnu par un automate ni est non vide
en cherchant sil existe un chemin menant dun etat initial de lautomate
a un etat nal, avec lalgorithme de Warshall (de complexite O(n3 ) o
u
n est la taille de lautomate). Donc la question de la vacuite est resoluble
algorithmiquement.
{ Un langage deni par une expression reguliere est-il ni ? L
a aussi, ce
probleme se ramene au m^eme probleme pour des expressions regulieres plus
courtes.
{ Deux expressions regulieres denissent-elles le m^eme langage ? Si L et L0
sont les langages denis par ces expressions regulieres, il sut de tester si
L \ L0 et L0 \ L sont vides, ce qui est decidable puisque lon peut obtenir des
expressions regulieres pour ces deux langages.
Ainsi, legalite s
emantique de deux expressions regulieres est decidable par
programme.
152
11-6
Automates finis
Langages non r
eguliers
11-7 Exercices
153
a,b
0
1 a,b
a,b
gure 36 : automate a
n+1
etats dont le d
eterminis
e a au moins 2n
etats
la i-eme lettre de u est un a si et seulement si ai1 u1Ln . Cela signie que
Ln a au moins 2n langages residuels distincts, donc tout automate deterministe
complet reconnaissant Ln a au moins 2n etats. Lautomate non deterministe de
la gure 36 constitue un exemple sur lequel toute methode de determinisation a
une complexite exponentielle.
Th
eor`
eme : (lemme de l
etoile) soit L un langage r
egulier. Alors il existe
un entier n tel que tout mot u L de longueur sup
erieure ou
egale a
n se
d
ecompose en trois parties : u = xyz avec |xy| 6 n, |y| > 1 et xykz L pour
tout k N.
Autrement dit, dans un langage regulier, pour tout mot u susamment long
on peut supprimer ou dupliquer la partie centrale de u un nombre arbitraire de
fois sans quitter L. Contrairement au theoreme sur les residuels en nombre ni, le
lemme de letoile ne constitue pas une caracterisation des langages reguliers (cf.
exercice 11-13).
D
emonstration : puisque L est regulier, il admet un nombre n ni de langages
residuels. Soit u L de longueur superieure ou egale a n. u admet n + 1 prexes
de longueur inferieure ou egale a n donc il existe deux prexes produisant le m^eme
langage residuel. Notons x et xy ces prexes, (donc |xy| 6 n et |y| > 1) et soit
u = xyz. Alors (xy)1L = x1L cest-
a-dire :
v A , xyv L xv L.
En particulier, xyz L donc xz L mais aussi x(yz) L donc xy(yz) L et de
proche en proche, pour tout k N, xyk z L.
Exemple : le langage des parentheses embo^tees nest pas regulier (troisieme
demonstration en comptant celle de lexercice 10-8). En eet, soit n N quelconque et u = an bn L que lon decoupe en u = xyz avec |xy| 6 n et |y| > 1.
Le facteur y est de la forme y = ap avec p > 1, donc xz = anp bn
/L.
11-7
Exercices
154
Automates finis
(1,0)
(1,1)
1
0
(0,1)
(1,1)
2
(0,0)
Ecrire
une fonction caml produisant un automate deterministe A0 equivalent a A.
0
A sera deni par :
1.
2.
3.
4.
le nombre q detats ;
la liste des transitions sur lettre (liste de triplets (d
epart, lettre, arriv
ee)) ;
le numero de letat initial ;
la liste des etats nals.
11-7 Exercices
155
L = {u A tq u2 L}. Montrer
Soit L un langage sur un alphabet
A.
On
note
1. Ecrire
une fonction caml prenant un mot u (vecteur de lettres) et disant
sil appartient au langage L = {an bn , n N} (langage des parentheses
embo^tees).
2. Un ordinateur executant la fonction precedente constitue un automate reconnaissant le langage des parentheses embo^tees, connu pour ^etre non regulier.
Comment est-ce possible ?
156
Automates finis
0 = 1,
1x = x1 = x,
1 = 1,
2 = ,
22 = 2,
= .
2 = 2 = ;
Probl`
emes
Probl
emes
158
Question 1
Soit a un entier naturel. On sait que a admet une unique ecriture binaire :
a = a0 + 2a1 + 4a2 + .. . + 2n1an1,
o
u ai {0, 1} et n est un entier naturel susamment grand. Le nombre ai est
appele i-
eme bit de a ou aussi bit i de a.
a) Donner une expression simple calculant a0 en fonction de a.
b) Quelle est lecriture binaire de ba/2c en fonction de celle de a (b c designe la
partie entiere) ?
c) En deduire une fonction caml bit : int -> int -> int telle que bit p a
retourne le bit p de a si a et p sont des entiers naturels. On donnera deux
versions : une version recursive et une version iterative.
Question 2
Soit v = [|v0; v1; . ..; vn1|] un vecteur a elements entiers naturels. On veut
reordonner ce vecteur de sorte que tous les entiers vi pairs soient places en t^ete et
tous les vi impairs en queue, lordre relatif des elements etant conserve a linterieur
de chaque groupe. Par exemple si :
v = [|3; 1; 4; 1; 5; 9; 2; 6|]
alors on souhaite obtenir apres transformations :
v = [|4; 2; 6; 3; 1; 1; 5; 9|].
Il est autorise pour ce faire dutiliser un vecteur auxiliaire w de longueur n.
a) Donner un algorithme en francais eectuant la transformation demandee. On
demontrera que cet algorithme repond eectivement au probleme pose.
b) Ecrire
une fonction caml permute : int vect -> unit implementant cet algorithme.
c) On appelle transfert une operation v.(i) <- qqch ou w.(j) <- qqch. Calculer
le nombre de transferts eectues par votre programme en fonction des nombres
a et b dentiers pairs et impairs dans v.
d) On generalise le probleme en ajoutant a permute un parametre p entier naturel
de sorte que lappel permute p v place en t^ete de v les elements dont le bit p
vaut 0 et en queue ceux dont le bit p vaut 1, lordre initial des entiers etant
conserve a linterieur de chaque groupe. Indiquer quelles sont les modications
a apporter a votre code donne en 2-b.
159
Question 3
Soit v = [|v0; v1; .. .; vn1|] un vecteur a elements entiers naturels que lon veut
trier par ordre croissant. On execute lalgorithme suivant :
. Calculer M = max(v0, v1, ..., vn1).
. D
eterminer un entier K tel que M < 2K.
. Pour p = 0, 1, ..., K 1 faire permute p v n pour
a) Executer cet algorithme sur le vecteur v = [|3; 1; 4; 1; 5; 9; 2; 6|]. On indiquera
les valeurs de M, K, et la valeur de v a la n de chaque iteration de la boucle .
b) Traduire cet algorithme en caml. On rappelle que caml dispose dune fonction max : int -> int -> int qui retourne le plus grand de ses deux arguments. Il ny a pas delevation a la puissance dans les entiers et il est interdit
dutiliser celle des ottants.
c) Montrer qu
a la n de chaque iteration de la boucle la propriete suivante est
veriee :
la suite (v0 mod 2p+1 , v1 mod 2p+1 , ..., vn1 mod 2p+1 ) est croissante.
En deduire que le vecteur v est trie par ordre croissant a la n de lalgorithme.
d) On suppose que tous les entiers vi sont compris entre 0 et 230 1 (taille maximale dun entier caml sur une machine 32 bits). Quelle est la complexite
asymptotique de cet algorithme de tri comptee en nombre de transferts effectues ?
Interpolation de Lagrange
et multiplication rapide
Soient n N , P(x) = a0 + a1 x + a2x2 + .. . + an1 xn1 un polyn^
ome a
coecients complexes de degre strictement inferieur a n et X = (x0 , x1, .. ., xn1)
une suite de complexes deux a deux distincts. La liste des valeurs de P aux points
xi est la suite notee Y = P{X} = (P(x0 ), . .., P(xn1)). On etudie dans ce probleme
des algorithmes permettant de calculer P{X} a partir de P et X, et des algorithmes
permettant de calculer P a partir de X et P{X}.
Les algorithmes pourront ^etre ecrits en francais ou en caml. On supposera
que le langage caml dispose dun type de donnees complexe representant les nombres complexes et des operations arithmetiques usuelles sur les complexes notees
+:, -:, *: et /:, ainsi que de fonctions de conversion :
Probl
emes
160
complexe_of_floats : (a, b) 7 a + ib
floats_of_complexe : a + ib 7 (a, b).
Les polyn^
omes et les suites de valeurs seront representes par des vecteurs
caml a elements complexes :
Le vecteur representant P est p = [| a0 ; a1; . . .; an1 |] ;
Le vecteur representant X est x = [| x0; x1; . ..; xn1 |] ;
Le vecteur representant P{X} est y = [| P(x0 ); P(x1); . ..; P(xn1) |].
Question 1
Ecrire
un algorithme calculant la valeur P(z) pour un polyn^
ome P et un complexe z donnes. On prouvera la validite de cet algorithme et on donnera son
temps dexecution mesure en nombre doperations complexes en fonction de la
longueur n de P.
Question 2
Ecrire
un algorithme calculant Y = P{X} en fonction du polyn^
ome P et de la suite
de points X. Il est suppose que P et X ont m^eme longueur n. Donner la complexite
de cet algorithme en fonction de n (en nombre doperations complexes).
Question 3
Etant
donne deux suites X = (x0 , .. ., xn1) et Y = (y0, . .., yn1) de n complexes,
les xi etant distincts, il existe un unique polyn^
ome P de degre inferieur ou egal a
n 1 tel que P{X} = Y. Ce polyn^
ome peut ^etre calcule par lune des relations :
a) Formule de Lagrange : P(x) =
n1
P
06j<n
j6=i
i=0
x xj
xi x j .
yn1 Q(xn1)
U(x)
U(xn1)
o
u Q est le polyn^
ome deni par deg(Q) 6 n2, Q{x0 , .. ., xn2} = (y0 , .. ., yn2)
et U(x) = (x x0)(x x1 ).. .(x xn2).
c) Formule dAitken : P(x) =
x x0
x xn1
P0,n2(x) +
P1,n1(x)
x0 xn1
xn1 x0
o
u Pa,b est le polyn^
ome de degre inferieur ou egal a b a tel que :
Pa,b {xa, . .., xb } = (ya , .. ., yb).
161
Question 4
On suppose dans cette question que n est une puissance de 2 : n = 2 , et que X est
la suite des racines n-emes de 1 dans C : xk = e2ik/n. Soient Y = (y0 , .. ., yn1)
une suite de n complexes quelconques et P le polyn^
ome de degre strictement
inferieur a n deni par P{X} = Y. On note Y0 et Y1 les sous-suites paire et
impaire associees a Y : Y0 = (y0, y2, y4, . .., yn2), Y1 = (y1, y3, y5, . . ., yn1),
X0 la sous-suite paire associee a X et P0, P1 les polyn^
omes de degres strictement
inferieurs a n/2 denis par P0{X0} = Y0 et P1 {X0} = Y1 .
a) Montrer que P(x) =
1 + xn/2
1 xn/2
P0 (x) +
P1(xe2i/n).
2
2
Probl
emes
162
a) Ecrire
un algorithme permettant de savoir si C est ou non une sous-sequence
de A. La validite de cet algorithme devra ^etre justiee.
b) En supposant que C est bien une sous-sequence de A, ecrire un algorithme
calculant une liste I des indices des elements de A a supprimer pour obtenir C.
Lorsquil existe plusieurs listes I solution, une seule doit ^etre retournee.
c) Executer les algorithmes precedents sur lexemple :
A = (3, 1, 4, 1, 5, 9),
C = (1, 5, 9).
si ai1 = bj1 ;
sinon.
Arbres de priorit
e
equilibr
es
163
c) Ecrire
un algorithme permettant, a partir des listes A, B et de la matrice L de
calculer une plsc(A, B).
d) Executer les algorithmes precedents sur lexemple :
A = (p, i, o, l, e, t),
B = (p, l, i, e, r).
Question 3 : pr
e-traitement de A et B
Pour accelerer le calcul dune plsc(A, B), on supprime de A tous les elements
ne gurant pas dans B et on supprime de B tous ceux ne gurant pas dans A.
En notant A0 , B0 les listes obtenues, toute plsc(A, B) est une plsc(A0 , B0) et
reciproquement.
a) Ici on suppose que les elements de A et B appartiennent a un ensemble E de
cardinal susamment petit pour quil soit envisageable de creer en memoire
des listes ou des vecteurs de longueur card(E). Ceci est le cas si A et B sont des
listes de caracteres ; E est alors lensemble de tous les caracteres representables
croissantes. Ecrire
un algorithme calculant A0 et B0 a partir de A, B, At, Bt .
Question 4
Determiner la complexite asymptotique du pre-traitement selon a ou b. Pour b,
la complexite du tri devra ^etre prise en compte : il nest pas demande decrire un
algorithme de tri, vous pouvez citer un algorithme vu en cours. Est-il raisonnable
deectuer un pre-traitement (la reponse devra ^etre argumentee) ?
Arbres de priorit
e
equilibr
es
Etant
donne un arbre binaire a, on note N(a) le nombre de nffuds de a et
H(a) la hauteur de a. On pose par convention :
N() = 0,
H() = 1.
Probl
emes
164
Soit a un arbre binaire dont les etiquettes appartiennent a un ensemble totalement ordonne. On dit que a est un arbre de priorit
e
equilibr
e (APE) sil
verie pour tout nffud n a :
1. letiquette de n est superieure ou egale a celles de ses ls sil en a ;
2. si g et d designent les branches gauche et droite issues de n alors :
N(g) 1 6 N(d) 6 N(g).
Par convention un arbre vide est un APE. Ce type darbre intervient dans
les problemes de les dattente avec priorite o
u lon doit eectuer plusieurs t^
aches
selon un ordre de priorite. Si chaque t^
ache est representee par un nffud dun
APE etiquete par la priorite de la t^
ache, alors la t^
ache representee par la racine
de larbre est lune des t^
aches les plus prioritaires. La condition 2. signie que
les autres t^
aches sont reparties equitablement entre les branches gauche et droite,
la branche gauche etant (( plus lourde dun nffud )) en cas dinegalite. On etudie
dans ce probleme les operations suivantes :
1. insertion dune nouvelle t^
ache ayant une certaine priorite ;
2. extraction dune t^
ache prioritaire (celle associee a la racine) et reconstitution dun APE avec les t^
aches restantes.
Les APE seront representes en caml par des arbres binaires ordinaires suivant
la declaration :
type a arbre = B_vide | B_noeud of a * (a arbre) * (a arbre);;
o
u a est le type ordonne representant les t^
aches avec leur priorite.
B_vide repr
esente un APE vide ;
B_noeud(e, g, d) repr
esente un APE dont la racine porte letiquette e et dont
Question 1
Soit a un APE non vide. Montrer que H(a) = blog2 (N(a))c.
Question 2 : insertion
Ecrire
une fonction insertion telle que si a designe un APE et e une etiquette
alors insertion(a,e) renvoie un APE a0 contenant tous les nffuds de a et un
nffud supplementaire detiquette e. On prouvera la correction de cette fonction,
en particulier on prouvera que larbre a0 retourne est bien un APE, et on donnera
sa complexite temporelle. Executer (( a la main )) votre fonction sur lexemple :
5
a=
4
3
1
2
e = 2.
Arbres de priorit
e
equilibr
es
165
Ecrire
une fonction transforme qui constitue a0 a partir de a1 . On prouvera la
correction de cette fonction et on donnera sa complexite temporelle en fonction
de N(a).
Question 4 : extraction de la racine
Soit a un APE dont on souhaite retirer la racine. On procede en deux temps :
1. On supprime le nffud le plus a gauche dans a et on permute les branches
gauche et droite de chaque nffud ascendant du nffud supprime. Soient a0
larbre obtenu et e letiquette du nffud supprime.
2. On remplace letiquette r de la racine de a0 par e et on reconstitue un
APE, a00, selon lalgorithme de la question precedente.
Exemple :
a
5
4
3
1
2
a0
a00
1
0
4
2
1
0
3
2
b) Ecrire
le code de la fonction extraction qui retourne larbre a00 a partir de a.
Donner la complexite temporelle de extraction en fonction de N(a).
Question 5 : utilisation des APE pour le tri
Pour trier une liste [e0; e2; . . .; en1] delements appartenant a un ensemble totalement ordonne, on insere un a un ces elements dans un APE initialement vide
puis on extrait par ordre de priorite decroissante les elements de lAPE obtenu et
on les insere dans une nouvelle liste initialement vide. Quelle est la complexite
temporelle de cette methode de tri ?
Probl
emes
166
167
Question 3
a) Deduire de la question precedente un algorithme de compilation optimal dune
formule f. Cet algorithme sera donne en francais, puis code en caml en
introduisant les denitions de type adequates pour representer les formules et
les codes compiles. On ne cherchera pas a optimiser le temps de construction
du code, mais on evitera la repetition de calculs identiques.
b) Proposer une methode permettant deviter les concatenations en queue de liste
dans la production du code. Le codage en caml de cette amelioration nest
pas demande.
Question 4
Si la pile operationnelle dun processeur comporte 8 niveaux, quelle est la taille
minimale, comptee en nombre de nffuds, dune formule dont le calcul est impossible ?
a1 = bi+1 , .. .,
a|m|1 = bi+|m|1.
()
a) Ecrire
une fonction caml implementant cet algorithme. Donner sa complexite
asymptotique dans le pire des cas en fonction de |m| et |t|.
Probl
emes
168
b) On suppose dans cette question seulement que toutes les lettres de m sont
dierentes. Cette information permet-elle dameliorer lalgorithme precedent ?
Si oui, donner la complexite de lalgorithme modie.
c) Analyse en moyenne : on note (t, m) le nombre de comparaisons de lettres
eectuees par lalgorithme du 1-a pour tester () pour des valeurs donnees de
t et m. En admettant que tous les mots m de longueur ` sont equiprobables,
le nombre moyen de comparaisons a t, ` xes est :
1 X
(t, m)
(t, `) =
|A|` |m|=`
o
u la somme porte sur tous les mots m de longueur `. Montrer que lon a :
(t, `) 6
|A|
|t|.
|A| 1
1 P
(t, m) (nombre moyen de comparai|A|` |t|=`
sons pour m xe et t aleatoire de longueur `).
d) Majorer de m^eme :
~ (`, m) =
Question 2
Le deuxieme algorithme consiste a construire un automate deterministe complet
Am reconnaissant le langage Lm = A m et a lui faire lire le texte t. Chaque
passage par un etat nal de Am correspond a une occurrence de m dans t.
a) Exemple : A = {a, b, c} et m = aabaac. Construire un automate non
deterministe reconnaissant Lm et en deduire un automate deterministe complet reconnaissant le m^eme langage.
b) Ecrire
une fonction caml prenant en argument un automate Am (sous une
forme a denir) et le texte t et retournant la premiere position de m dans t si
elle existe et declenchant une erreur dans le cas contraire.
Construction automatique de Am :
Pour m, u A on note S(m, u) le plus long mot v qui soit a la fois un prexe
de m et un suxe de u (v = eventuellement). On construit Am de la maniere
suivante :
{ les etats de Am sont les prexes de m (il y a |m| + 1 prexes en comptant
et m) ;
{ si u est un prexe de m et a une lettre alors Am contient la transition
a
u S(m, ua) ;
{ letat initial de Am est et letat nal m.
c) Montrer que Am reconna^t eectivement Lm.
d) Soient u un prexe de m dierent de et u0 le mot obtenu en supprimant la
premiere lettre de u. Montrer que lon a pour toute lettre a :
ua
si ua est un prexe de m,
S(m, ua) =
S(m, S(m, u0)a) sinon.
169
e) On represente en machine un prexe a0 . ..ai1 de m par lentier i (0 representant ) et la fonction de transition de Am par une matrice M a |m| + 1 lignes
et |A| colonnes telle que M.(i).(a) = j represente la transition :
a
a0 .. .ai1 a0 .. .aj1
(les lettres de A sont supposees ^etre representees par des nombres entiers).
Deduire de la question precedente un algorithme ecace de calcul de M a
partir de m et A. Determiner sa complexite asymptotique en fonction de |m|.
Executer votre algorithme sur le mot m = aabaac.
f ) Montrer que lautomate Am construit par la methode precedente est optimal,
cest-
a-dire quil nexiste pas dautomate deterministe complet a moins de
|m| + 1 etats reconnaissant Lm .
Question 3
Cet algorithme est une variante du premier algorithme : on teste les positions i
eventuelles par valeurs croissantes, mais les tests de () sont eectues de droite a
gauche, cest-
a-dire quon eectue dans cet ordre les comparaisons :
a|m|1 = bi+|m|1, . . .,
a1 = bi+1 ,
a0 = b i .
(0)
Travaux pratiques
Chemins dans Z2
171
Chemins dans Z2
Ecrire
une fonction points : (int*int) -> direction list -> (int*int) list qui
calcule les points dun chemin dont lorigine et le mot sont passes en arguments.
Tirer des mots de chemins au hasard et les faire acher (eacer la fen^etre graphique
entre deux traces).
2. D
etection et
elimination des boucles
a) Ecrire
une fonction multiples : (int * int) list -> bool qui teste si un chemin contient des points multiples. On utilisera la fonction caml mem : a ->
a list -> bool qui dit si une liste contient un
element donne en premier
argument.
b) Pour supprimer les boucles dans le chemin ` = (A0 , . .., An) on utilise lalgorithme suivant :
172
Travaux pratiques
1. Constituer la liste de couples ` = ((A1 , A0), (A2, A1), ..., (An, An1)).
Cette liste sera utilis
ee comme (( table de pr
ed
ecesseurs )) gr^
ace a
la fonction standard assoc : assoc M ` renvoie pour un point M le premier
point N tel que le couple (M, N) appartient a
`, cest-
a-dire le premier
pr
ed
ecesseur de M dans ` (si M na pas de pr
ed
ecesseur, assoc d
eclenche
une erreur).
2. Constituer de proche en proche le chemin sans boucle `0 = (A00 , ..., A0p)
associ
ea
`a
laide des relations :
A0p = An ,
A00 = A0 .
3. Remplissage
Soit ` un chemin ferme simple ; on veut (( noircir )) la region bornee delimitee par
` (en fait la remplir avec la derniere couleur selectionnee par set_color). Voici un
algorithme possible pour ce faire :
1. D
eterminer les ordonn
ees minimale et maximale, y1 et y2, des points
de `.
Chemins dans Z2
173
174
Travaux pratiques
(* trac
e des segments et des points *)
let rec trace = function
| []
-> ()
| (x,y)::suite ->
let r = if suite = [] then rayon1 else rayon2 in
fill_circle (x0 + x*pas) (y0 + y*pas) r;
lineto (x0 + x*pas) (y0 + y*pas);
trace(suite)
in trace(points)
;;
(* noircit un rectangle de diagonale [(x1,y1),(x2,y2)] *)
let noircit (x1,y1) (x2,y2) =
let x0 = size_x()/2
and y0 = size_y()/2
in
let x3 = min x1 x2
and y3 = min y1 y2
in
let dx = (max x1 x2) - x3 and dy = (max y1 y2) - y3 in
fill_rect (x0 + x3*pas) (y0 + y3*pas) (dx*pas) (dy*pas)
;;
Le r^
ole de #open "graphics" est de rendre accessibles les fonctions graphiques (elles
sont chargees en memoire lorsquon lance camlgraph mais leurs noms courts ne sont
connus de linterpreteur quapres ce #open "graphics").
random_chemin tire au hasard un mot de chemin, , comportant n fois Nord, s
fois Sud, e fois Est et w fois West. On obtient un mot de chemin ferme si (et
seulement si) n = s et e = w.
dessine trace dans la fen^
etre graphique un chemin ` (liste de points) passe en
argument. Les quantites pas, rayon1 et rayon2 determinent lunite dechelle et la
taille des disques materialisant les points du chemin.
noircit trace un rectangle dont on donne deux sommets oppos
es en tenant compte
du facteur dechelle pas.
1. Impl
ementation des files dattente
Une le dattente est liste dont on limite lusage aux operations suivantes :
{ la liste est-elle vide ?
{ extraire la t^ete de la liste ;
{ ajouter un element en queue de liste.
On rencontre souvent des les dattente dans la vie courante, par exemple a
la caisse dun supermarche ou a un feu rouge. En informatique une le dattente
175
permet de stocker des informations qui ne peuvent ^etre traitees de suite, mais qui
devront l^etre en respectant leur ordre darrivee dans la le (structure de donnees
FIFO : rst in, rst out).
On peut realiser ces operations avec le type liste cha^nee fourni en standard
par caml, mais loperation (( insertion en queue )) a une mauvaise complexite sur
ce type de listes, aussi utilise-t-on des structures de donnees mieux adaptees aux
fonctionnalites des les dattente. Dans ce TP on implementera une le dattente
par un couple de listes cha^nees : lavant de la le, classee par ordre darrivee et
larriere, classee par ordre inverse darrivee.
Les nouveaux arrivants seront
places en t^ete de la liste arriere, les
premiers arrives seront extraits en
t^ete de la liste avant. Lorsque la
liste avant est epuisee on retourne
la liste arriere, on la place a lavant
et on reinitialise la liste arriere a [].
Cette operation de retournement a
une complexite lineaire en la taille
de la liste arriere, donc le temps dextraction du premier element dune
le ainsi implementee nest pas constant, mais comme un element de la
le nest retourne quune seule fois,
le temps cumule de n extractions en
t^ete de la le est lineaire en n.
arriere
13
12
11
10
9
8
7
6
1
2
3
4
5
avant
type a file = {
mutable avant
: a list;
mutable arri`
ere : a list
};;
Dans la declaration ci-dessus les champs avant et arri`ere sont declares mutables de facon a pouvoir ^etre modies sur place. Si f est une variable de type a file
alors on modie sa liste avant par une instruction de la forme : f.avant <- qqch.
Recopier la denition du type a file et programmer les fonctions suivantes :
nouv_file:
est_vide :
longueur :
ajoute :
retire :
unit ->
a file
a file
a file
a file
a
->
->
->
->
file
bool
int
a -> unit
a
176
Travaux pratiques
premier entier de Hamming est 1 et que tout autre entier de Hamming est le double, le triple ou le quintuple dun entier de Hamming plus petit (ces cas netant
pas exclusifs). Il sut donc dutiliser trois les dattente, h2, h3 et h5 contenant
initialement le seul nombre 1 puis dappliquer lalgorithme :
d
eterminer le plus petit des trois nombres en t^
ete des les dattente,
soit x. Imprimer x, le retirer de chacune des les le contenant et ins
erer
en queue de h2, h3 et h5 respectivement 2x, 3x et 5x.
a) Programmer cet algorithme et faire acher les n premiers entiers de Hamming.
Observer levolution des les dattente a chaque etape.
b) Lalgorithme precedent est tres dispendieux car il place la plupart des entiers
de Hamming dans les trois les alors quune seule surait. En eet, si x est un
entier de Hamming divisible a la fois par 2, 3 et 5 alors x a ete place dans h 2
au moment o
u lon extrayait x/2, dans h3 au moment o
u lon extrayait x/3 et
dans h5 au moment o
u lon extrait x/5. Modier votre programme de sorte
quun m^eme entier de Hamming ne soit insere que dans une seule des les
dattente.
c) Les entiers caml sont limites a un milliard environ ce qui ne permet pas daller
tres loin dans la suite de Hamming. Pour pouvoir traiter des grands nombres
on convient de representer un entier de Hamming x par le triplet (a, b, c) tel
que x = 2a 3b 5c. Reprendre votre programme avec cette convention et calculer
le millionieme entier de Hamming. Pour comparer deux entiers de Hamming
x et y connus par leurs exposants il sut de comparer les reels ln x et ln y
(ln est note log en caml). On admettra que la precision des calculs sur les
ottants est susante pour ne pas induire de comparaison erronee.
d) Determiner experimentalement la complexite memoire de lalgorithme de recherche du n-eme nombre de Hamming. Cette complexite sera mesuree par
la somme ` des longueurs des trois les h2 , h3 et h5 . Pour cela on relevera les
valeurs de ` pour n = 1000, n = 2000, n = 4000 etc, et on conjecturera une
relation simple entre ` et n.
Recherche de contradictions
par la m
ethode des consensus
1. Pr
esentation
Soient p1 , . . ., pn des variables booleennes. On appelle :
{ litt
eraux les propositions pi et leurs complementaires pi ;
{ clause toute disjonction de litteraux, par exemple p1 + p2 + p3 ;
{ syst
eme de clauses toute famille nie de clauses.
177
La clause c est dite triviale sil existe une variable p telle que p et p apparaissent dans c. Dans ce cas la valeur de verite de c est vraie quelles que soient les
valeurs de verite des pi . La clause Faux est la clause constituee daucun litteral,
sa valeur de verite est fausse quelles que soient les valeurs des variables p i . Dans ce
TP on ne considerera que des clauses non triviales. Ces clauses seront representees
par un couple de deux listes : la liste des variables apparaissant positivement
dans c (p1 et p2 dans lexemple precedent) et la liste des variables apparaissant
n
egativement (p3 dans lexemple precedent). Pour une clause non triviale ces
listes sont donc disjointes, et elles sont toutes deux vides pour la clause Faux et
pour elle seulement.
Un systeme de clauses est dit contradictoire si la conjonction de toutes les
clauses du systeme est egale a la clause Faux. Par exemple le systeme :
{c + d, c + m, d + m, m}
est contradictoire comme on peut sen rendre compte en developpant a la main le
produit :
(c + d)(c + m)(d + m)m = c c d m + c c m m + c m d m + c m m m
+ d c d m + d c m m + d m d m + d m m m.
Cette methode de developpement complet nest pas praticable lorsque n est grand :
la longueur dune clause non triviale peut atteindre n, et il y a 2n clauses de
longueur n ; le produit de toutes ces clauses comporte donc dans sa forme developn
pee n2 termes. .. On peut aussi se rendre compte quun systeme est contradictoire
en calculant la table de verite de la conjonction des clauses, mais pour n variables
booleennes il y a quand m^eme 2n valeurs de verite a calculer. Lobjectif de ce
TP est detudier un autre algorithme de reconnaissance de contradictions, appele
m
ethode des consensus, qui permet de determiner si un systeme est contradictoire
en general plus ecacement quen calculant le produit de toutes les clauses du
systeme ou en cherchant la table de verite de leur conjonction.
Si c et c0 sont deux clauses, on dit que c implique c0 si tout litteral apparaissant dans c appara^t aussi dans c0 . Ceci correspond a la notion usuelle
dimplication : c = c0 si et seulement si tout choix des variables rendant c vraie
rend aussi c0 vraie. Par convention la clause Faux implique toutes les autres.
Dans un systeme S, une clause c S est dite minimale sil nexiste pas de
clause c0 S \ {c} telle que c0 = c.
Si c et c0 sont deux clauses telles quil existe une variable p apparaissant
positivement dans une clause et negativement dans lautre, par exemple c = p+c1
et c0 = p + c01 (c1 et c01 ne contenant ni p ni p), on appelle consensus des clauses
c et c0 la clause c00 = c1 + c01 . c00 a la propriete d^etre vraie chaque fois que c
et c0 le sont, et cest la plus petite clause pour lordre dimplication parmi les
clauses independantes de p ayant cette propriete (cest-
a-dire si d est une clause
independante de p, on a cc0 = d si et seulement si c00 = d). Sil existe une autre
variable q apparaissant positivement dans lune des clauses c, c0 et negativement
178
Travaux pratiques
dans lautre alors c1 + c01 contient q + q donc est la clause triviale. Ceci montre
quil existe trois cas possibles pour deux clauses c et c0 :
{ ou bien elle nont pas de consensus (aucune variable nappara^t positivement
dans une clause et negativement dans lautre) ;
{ ou bien elles ont un unique consensus ;
{ ou bien elles ont plusieurs consensus mais alors ils sont tous triviaux.
Soit S un systeme de clauses. On determine si S est contradictoire de la
maniere suivante :
1. simplier S en retirant toutes les clauses non minimales ;
2. former tous les consensus non triviaux entre deux clauses de S et les
ajouter a
S;
3. recommencer les
etapes 1 et 2 tant que lon obtient en sortie de 2 un
syst
eme di
erent de celui en entr
ee de 1 ;
4. le syst
eme dorigine est contradictoire si et seulement si le syst
eme
nal est r
eduit a
{Faux }.
La terminaison de cet algorithme est immediate (il ny a quun nombre ni de
systemes de clauses pour un ensemble de variables donne), sa correction lest
moins, ce pourrait ^etre un tres bon sujet de probleme.
Exemple : quand ils ont un devoir, les
el
eves apprennent leur cours. Sils ont
appris leur cours, ils nont pas de mauvaises notes. Sils nont pas de devoir,
ils nont pas non plus de mauvaise notes. Montrer que les
el
eves nont jamais
de mauvaises notes.
On modelise ce probleme avec trois variables booleennes : d = (( avoir un
devoir )) ; m = (( avoir une mauvaise note )) ; c = (( apprendre son cours )) ; et on
dispose des hypotheses :
h1 (d = c c + d),
h2 (c = m c + m),
h3 (d = m d + m).
S = {c + d, c + m, d + m,
S = {c + d, c + m, d + m,
S = {c + d,
S = {c + d,
S={
S={
S = {Faux}
S = {Faux}
m}
m, d + m, c + m, c, d}
m, d + m, c + m, c, d}
m, d + m, c + m, c, d, d, c, m}
m,
c, d, d, c, m}
m,
c, d, d, c, m, Faux}
179
de clauses *)
a b = ([b], [a])
a b = ([],
[a;b])
a b = ([a;b],[])
a b = ([a], [b])
(*
(*
(*
(*
a => b
a => non b
non a => b
non a => non b
*)
*)
*)
*)
180
Travaux pratiques
conformement au code de print_clause. On pourra par ailleurs utiliser les fonctions a caractere ensembliste faisant partie de la bibliotheque standard de caml :
union, intersect, subtract, mem et except.
3. Programmation de l
etape 1
Ecrire
les fonctions suivantes :
implique
present
ajoute
simplifie
:
:
:
:
clause
clause
clause
clause
->
->
->
->
clause
systeme
systeme
systeme
->
->
->
->
bool
bool
systeme
systeme
{ implique c c0 dit si c = c0 .
{ present c s dit sil existe une clause c0 dans s telle que c0 = c.
{ ajoute c s retourne un systeme s0 equivalent au systeme s {c} en retirant de
s {c} toutes les clauses c0 6= c telles que c = c0 . De la sorte, si lon part dun
systeme s ne contenant que des clauses minimales, le systeme s0 retourne a aussi
cette propriete.
{ simplifie s retourne un systeme s0 equivalent a s et ne contenant que des clauses
minimales. Pour ce faire, on ajoutera une a une les clauses de s a un systeme
initialement vide.
4. Programmation des
etapes 2 et 3
Ecrire
les fonctions suivantes :
ajoute_cons
: clause -> clause -> systeme -> systeme
ajoute_consensus : clause -> systeme -> systeme -> systeme
cloture
: systeme -> systeme
181
Montrer que les regles de ce club sont si contraignantes que personne ne peut
en ^etre membre.
6. Affichage des
etapes dune contradiction
Le programme precedent dit que le club ecossais ne peut pas avoir de membres,
mais on ne sait pas vraiment pourquoi : on sait seulement que la machine a trouve
une contradiction entre toutes les regles. En fait il nest pas dicile dobtenir une
demonstration en bonne et due forme de la contradiction trouvee, il sut chaque
fois quon produit un nouveau consensus de memoriser a partir de quelles clauses
il a ete obtenu. Lorsquon aboutit a la clause Faux , il ne reste plus qu
a acher
ces etapes dans le bon ordre. Modier le type clause de la maniere suivante :
type clause == (string list) * (string list) * raison
and raison = H | D of clause * clause;;
m
e => Faux
182
Travaux pratiques
Mod
elisation dun tableur
Un tableur est un programme permettant de gerer un tableau constitue dune
matrice de valeurs et dune matrice de formules. Voici un exemple de tableau :
0
1
2
1
4
7
2
5
8
3
6
9
2A20
A02
A22
A20 + A22
A11 + A01
A00
A10 + A21
0
1
2
valeurs
formules
(int*int) list;;
(*
Rien | Somme of lcell;;
{
int; p : int;
(*
int vect vect;
(*
formule vect vect;
(*
liste de cellules
*)
dimensions
*)
valeurs des cellules *)
formules
*)
Mod
elisation dun tableur
dep: int vect vect;
suc: lcell vect vect;
mutable lt : lcell
};;
183
(* nombre de d
ependances *)
(* successeurs
*)
(* ordre de calcul
*)
1. Tri topologique
Programmer lalgorithme du tri topologique. Voici a titre indicatif une decomposition possible des operations a eectuer :
d
ependances : tableau -> unit
calcule les matrices dep et suc dun tableau a partir de sa matrice f.
place : tableau -> (int*int) -> unit
place une cellule dans la liste lt et decremente le compte de dependance
decremente les comptes de dependance des cellules transmises en deuxieme argument et appelle place pour chaque cellule dont le compte de
dependance devient nul.
184
Travaux pratiques
tri_topo : tableau -> unit
2. Calcul du tableau
Maintenant que le tableau est (( trie topologiquement )) il reste a evaluer les formules dans lordre et a modier en consequence la matrice v du tableau. Programmer cela. On doit trouver pour le tableau servant dexemple les valeurs suivantes :
0
1
2
1
2
1
9
10
19
1
21
9
3. Compl
ement
Lorsque lon modie la valeur dune cellule qui nest pas soumise a contraintes, il
faut reevaluer toutes les formules qui font intervenir cette cellule, directement ou
indirectement. Une solution nave consiste a recalculer tout le tableau, mais on
peut faire mieux en notant pour chaque cellule non contrainte la liste des cellules
a recalculer, triee par ordre topologique.
Analyse syntaxique
1. Pr
esentation
Lobjectif de ce TP est deectuer lanalyse syntaxique dun programme puis de
lexecuter a laide dun interpreteur a partir de lexpression arborescente fournie
par lanalyseur. Le langage de programmation que devra reconna^tre lanalyseur
est le suivant :
{ Les valeurs d
enies dans le langage sont les nombres entiers et les fonctions a
un argument.
{ Les op
erations d
enies dans le langage sont les op
erations arithm
etiques
usuelles entre nombres entiers : +, , , / et % (modulo) ainsi que
lapplication de fonction : si e1 et e2 sont deux expressions alors
e1 e2
Analyse syntaxique
185
d
esigne lapplication de la fonction e1 a
la valeur e2. Une telle application nest valide que si e1 d
esigne eectivement une fonction et
e2 une valeur appartenant au domaine de e1, mais cette restriction ne
sera pas prise en compte dans le cadre de lanalyse syntaxique ; cest
linterpr
eteur devant
evaluer une expression qui signalera une erreur
a
lex
ecution en pr
esence dune application invalide. De m^
eme, les
op
erations arithm
etiques impossibles telle que laddition dune fonction
et dun nombre entier ne seront signal
ees qu
a lex
ecution.
{ Les priorit
es entre op
erations binaires sont les priorit
es alg
ebriques habituelles : lapplication de fonction est prioritaire devant la multiplication
et la division qui sont prioritaires devant laddition et la soustraction,
elles-m^
emes prioritaires devant le modulo. Les op
erations de m^
eme
priorit
e sont
evalu
ees de gauche a
droite et des parenth
eses peuvent
modier lordre d
evaluation dune expression.
{ Les constructions syntaxiques du langage sont la liaison locale dune
expression a
un identicateur ( let x = e1 in e2), la d
enition de fonction ( fun x -> e1) et lalternative ( if e1 then e2 else e3) o
u e 1 , e2 , e3
sont des expressions et x un identicateur. Dans le cas de lalternative,
linterpr
eteur devra
evaluer e1 , v
erier quil sagit dun nombre entier,
puis
evaluer e2 si e1 = 0 ou e3 si e1 6= 0. Lexpression non s
electionn
ee
ne doit pas ^
etre
evalu
ee. Les d
enitions introduites par let seront
syst
ematiquement consid
er
ees comme r
ecursives.
Ce langage, bien que reduit, est susant pour coder des calculs interessants. Par
exemple :
let f = fun x -> if x*(x-1) then 1 else f(x-1) + f(x-2) in f 5
2. Analyse lexicale
La premiere etape de lanalyse dune phrase est le decoupage de cette phrase en
lexemes. On denit le type suivant pour les elements lexicaux du langage :
type lex`
eme =
| Nombre of int
(* constante
| Ident of string
(* identificateur
| Opr
of int * char
(* opr. infixe
| Let | In | Fun | If | Then | Else (* mots-cl
es
| Egal | Fl`
eche
(* = et ->
| ParO | ParF
(* parenth`
eses
;;
*)
*)
*)
*)
*)
*)
Ecrire
une fonction lex`emes : string -> lex`eme list qui decompose une cha^ne
de caracteres en liste de lexemes. Un identicateur est une suite de caracteres
alphabetiques la plus longue possible. Les mots let, in, fun, if, then et else
sont des mots-cl
es et non des identicateurs, ils seront codes par les lexemes
correspondants. Un operateur inxe est constitue dun unique caractere, + - * /
%, auquel on attache un niveau de priorit
e : 1 pour le modulo, 2 pour laddition
et la soustraction, 3 pour la multiplication et la division. Les parentheses et le
186
Travaux pratiques
3. Analyse syntaxique
Lanalyseur syntaxique a pour r^
ole de transformer une liste de lexemes telle que
celle retournee par la fonction lex`emes precedente en une expression codee sous
forme arborescente selon la denition du type expression suivante :
type expression =
| Const of int
(*
| Var
of string
(*
| Fct
of string * expression
(*
| Bin
of expression * char * expression
(*
| Appl of expression * expression
(*
| Test of expression * expression * expression
| Letin of string * expression * expression (*
;;
nombre
identificateur
fonction
op
erateur binaire
appl. de fonction
(* s
election
d
efinition locale
*)
*)
*)
*)
*)
*)
*)
( expression ) expression
exp1 Opr(p, op) exp2 Bin(exp1 , op, exp2)
exp1 exp2 Appl(exp1 , exp2 )
Fun Ident(x) Fl`
eche expression Fct(x, expression)
Let Ident(x) Egal exp1 In exp2 Letin(x, exp1 , exp2 )
If exp1 Then exp2 Else exp3 Test(exp1 , exp2 , exp3 )
Analyse syntaxique
187
Ecrire
une fonction empile : lex`eme_ou_expression -> pile -> pile qui empile
un lexeme ou une expression sur la pile passee en argument, procede recursivement
aux reductions eventuelles et retourne la nouvelle pile. La fonction expression cidessous utilise empile pour calculer lexpression associee a une liste de lexemes :
let expression liste =
let pile = ref [L ParO] in
do_list (fun x -> pile := empile (L x) !pile) liste;
pile := empile (L ParF) !pile;
match !pile with
| [E e] -> e
| _
-> failwith "erreur de syntaxe"
;;
188
Travaux pratiques
Bin
(Appl (Var "f", Bin (Var "x", -, Const 1)), +,
Appl (Var "f", Bin (Var "x", -, Const 2))))),
Appl (Var "f", Const 5))
4. Evaluation
Pour evaluer une expression comportant des variables on a besoin de conna^tre
les valeurs de ces variables. On utilisera ici une liste dassociation formee de
couples (nom,valeur ) avec la convention quune variable x a pour valeur la valeur
indiquee par le premier couple (x,qqch) gurant dans la liste. Sil ny a pas de
couple commencant par x alors le programme devaluation provoquera une erreur.
Une telle liste est appelee liste denvironnement. On denit le type des valeurs
possibles pour une expression :
type valeur =
| Int of int
| Cloture of environnement * expression
and environnement == (string * valeur) list
;;
Une valeur est soit un nombre entier x code Int(x), soit une fonction f codee
Cloture(env,expr ) o
u expr est lexpression donnee pour la denition de f dans
fun x -> expr et env est la liste denvironnement qui
etait en vigueur lors de la
denition de f. Il faut memoriser cet environnement car la liste denvironnement
en vigueur lors de levaluation dune application f(x) nest pas necessairement la
m^eme, et cest celle a la denition qui doit prevaloir dans une expression telle que :
let a = 1 in let f = fun x -> x + a in let a = 2 in f 3
Ecrire
une fonction valeur : environnement -> expression -> valeur qui calcule
la valeur de lexpression fournie en deuxieme parametre a laide de la liste denvironnement fournie en premier parametre. On aura par exemple :
valeur [] (expression (lex`
emes
"let f = fun x -> if x*(x-1) then 1 else f(x-1) + f(x-2) in f 5"));;
- : valeur = Int 8
190
Exercice 1-1
let classe_3(a,b,c) =
let (a,b) = if a <= b then (a,b) else (b,a) in
if c <= a then (c,a,b)
else if c <= b then (a,c,b)
else
(a,b,c)
;;
Il est eectue deux ou trois comparaisons pour classer la liste (a, b, c) ce qui est
minimal car un algorithme eectuant au plus deux comparaisons ne peut retourner
que quatre permutations de (a, b, c) parmi les six possibles.
Exercice 1-2
(* dit si n est parfait, n >= 2
let parfait(n) =
let s = ref 0 in (* somme des
for d = 1 to n-1 do
if n mod d = 0 then s := !s
done;
n = !s (* r
esultat = true ou
;;
*)
diviseurs d
ej`
a vus *)
+ d;
false *)
Exercice 1-3
rner consiste a calculer par indices decroissants les nombres :
Lalgorithme de Ho
yk = pk + pk+1 x + .. . + pn1xnk1
selon la relation de recurrence :
yn = 0,
yk = pk + xyk+1
si 0 6 k < n.
et lon a Q = Q0 .
(* calcule le polyn^
ome q tel que q(x) = p(x+a) *)
let translate p a =
let n = vect_length(p) in
let q = make_vect n 0 in
for k = n-1 downto 0 do
(* ici on a : q (x ) = p +1 + p +2 (x + a ) + ... + p 1(x + a ) 2 *)
for i = n-k-1 downto 1 do q.(i) <- a * q.(i) + q.(i-1) done;
q.(0) <- a * q.(0) + p.(k)
done;
q (* r
esultat *)
;;
Exercice 1-4
191
Exercice 1-4
1. Decodage dune cha^ne de caracteres : lecriture decimale dun entier naturel n est par denition la suite (n0, n1, .. ., np1) dentiers compris entre
0 et 9 telle que :
n = n0 + 10n1 + .. . + 10p1np1,
cette ecriture etant unique a prolongation par des zeros pres. Le calcul de n
a partir de la suite (n0, n1, . .., np1) se ramene donc a levaluation en x = 10
du polyn^
ome :
P(x) = n0 + n1x + . . . + np1 xp1
rner.
que lon peut realiser par exemple avec lalgorithme de Ho
let valeur(s) =
let p = string_length(s) in
let v = ref(0)
in
for i = 0 to p-1 do v := !v*10 + valeur_chiffre(s.[i]) done;
!v
;;
non significatifs *)
d = ref(0) in
(s.[!d] = 0)
do d :=
(s.[!d] = 0) do d :=
!d + 1 done;
!d + 1 done;
(* si les longueurs r
esiduelles sont diff
erentes *)
(* alors la comparaison est termin
ee
*)
if
n - !d > n - !d then 1
else if n - !d < n - !d then -1
else begin
(* comparaison lexicographique *)
let i = ref(0) in
while (!i < n - !d) & (s.[!d + !i] = s.[!d + !i])
do i := !i + 1 done;
192
if !i = n - !d then 0
else if s.[!d + !i] > s.[!d + !i] then 1 else -1
end
;;
Exercice 1-5
si 0 < p < n.
p
Il en resulte par recurrence que T 0 (n, p) = 2Cp
n et donc T (n, p) = 2Cn 1. Ainsi
la fonction binome fait environ deux fois plus de calculs que le resultat quelle
fournit !
Exercice 1-7
Si lon utilise la relation de recurrence de Pascal alors il faut memoriser les valeurs
dej
a calculees ce qui peut ^etre fait en utilisant un vecteur. Lexercice 1-3 adapte
au calcul de (X + 1)n fournit une solution relativement ecace si lon veut tous
les coecients Cp
e. Une solution pour calculer un seul coecient
n pour un n donn
Cp
ecurrence, par exemple :
n est dutiliser une autre formule de r
Cp
n =
n
n!
= Cp1
p! (n p)!
p n1
Exercice 1-8
193
194
Exercice 1-9
0
Soit n = 2p et Pn et Pn
les temps dexecution cherches. On a Pn+1 = Pn + Kna2
n
puisque x est code sur na chires, do
u:
Pn = Ka2 (1 + 2 + . . . + (n 1)) = K
n(n 1) 2 Kn2a2
a
.
2
2
0
Par ailleurs P2k
= Pk0 + K(ka)2 , donc :
0
Pn
= Ka2 (1 + 22 + 42 + . . . + (2p1 )2 ) = K
n2 1 2 Kn2a2
a
.
3
3
Ainsi, avec cette hypothese sur la duree dune multiplication, puiss_2 a un temps
dexecution de lordre de 23 du temps dexecution de puiss_1.
Remarque : la conclusion demeure pour n quelconque car on a les relations :
0
0
P2n
= Pn
+ Ka2 n2,
0
0
P2n+1
= Pn
+ Ka2 (n2 + 2n),
Ka2(n + 1)2
Ka2(n 1)2
0
6 Pn
6
.
3
3
Exercice 1-10
Notons n = n020 + n121 + .. . + nk12k1 lecriture binaire de n. On calcule de
proche en proche les quantites :
yi = x n 0 2
et
zi = x2
i
zi+1 = z2i , yi+1 = yizn
i .
let puiss_3(x,n) =
let y = ref 1
and z = ref x
and p = ref n in
while !p > 0 do
if !p mod 2 = 1 then y := !y * !z;
z := !z * !z;
p := !p / 2
done;
!y
;;
Exercice 1-12
195
Exercice 1-11
Le programme puiss_2 de lexercice 1-9 requiert 6 multiplications. En remarquant
que 15 = 3 5, on calcule en 2 multiplications x3 = y puis en 3 multiplications
supplementaires y5 = x15, soit en tout 5 multiplications. Est-ce le minimum ?
Il sut de chercher toutes les puissances de x que lon peut obtenir en moins
de 4 multiplications ce qui peut ^etre fait a la main. On trouve les exposants
1,2,3,4,5,6,7,8,9,10,12 et 16. Donc le nombre minimal demande est bien 5.
Exercice 1-12
1. let rec fibonacci(n) =
if n < 2 then 1 else fibonacci(n-1) + fibonacci(n-2);;
Le nombre dappels a fibonacci pour calculer Fn est egal a 2Fn 1 (demonstration similaire a celle de lexercice 1-6).
2.
cest-
a-dire que T2n et T2n+1 se calculent facilement en fonction de Tn . On
en deduit le programme suivant :
(* fibo(n) calcule le couple (Fn-1, Fn) *)
let rec fibo(n) = match n with
| 0 -> (0,1)
| 1 -> (1,1)
| _ -> let (u,v) = fibo(n/2) in
if n mod 2 = 0 then (u*(2*v - u), u*u + v*v)
else (u*u + v*v, v*(v + 2*u))
;;
196
Exercice 1-13
1. Si x est pair strictement superieur a 1 alors on a f(x) = 2f(x/2) et x/2 < x.
Si x est impair strictement superieur a 1 alors on a f(x) = 1 + 2f((x + 1)/2)
et (x + 1)/2 < x. Donc dans les deux cas recursifs on rappelle f en une
ou deux etapes avec un argument strictement inferieur a x ; ceci prouve la
terminaison du calcul de f(x) par recurrence sur x.
2. Soit g(x) = f(x) + x. En remplacant f(x) par g(x) x dans la denition de f
et en simpliant on obtient un programme calculant g :
let rec
if x
else
else
;;
g(x) =
<= 1 then 1+x
if x mod 2 = 0 then 2*g(x/2)
g(x+1)
*)
(* on suppose que a contient au moins un e
l
ement. *)
let ppcm_i a =
let p = ref a.(0) in
for i = 1 to vect_length(a) - 1 do p := ppcm2(!p,a.(i)) done;
!p
;;
2.
e
l
ements a.(i)..a.(j) *)
*)
=
a.(i)
ppcm2(a.(i),a.(j))
in ppcm2(ppcm_rec a i
k,
ppcm_rec a (k+1) j)
;;
let ppcm_dr(a) = ppcm_rec a 0 (vect_length(a)-1);;
Exercice 1-15
197
est probablement plus lente que ppcm_i compte tenu des operations non comptees
(division de a en 2, gestion des appels recursifs) et certainement plus compliquee
a ecrire et a lire . ..
Exercice 1-15
Soient A(x) = a0 +a1 x+a2 x2 et B(x) = b0 +b1 x+b2 x2 : il sagit de determiner les
cinq coecients du polyn^
ome C(x) = A(x)B(x), ce qui peut se faire en calculant
les valeurs de C en cinq points et en calculant le polyn^
ome de Lagrange associe.
Par exemple, en prenant les points 0, 1, 1, 2 et 2 on obtient :
C(x) = c0 + c1 x + c2 x2 + c3 x3 + c4 x4
C(0) 4
(x 5x2 + 4)
=
4
C(1) 4
(x + x3 4x2 4x)
6
C(1) 4
(x x3 4x2 + 4x)
6
C(2) 4
(x + 2x3 x2 2x)
+
24
C(2) 4
+
(x 2x3 x2 + 2x),
24
do
u:
c0 = C(0)
1
2
c1 = (C(1) C(1)) + (C(2) C(2))
3
12
5
2
1
c2 = C(0) + (C(1) + C(1)) (C(2) + C(2))
4
3
24
1
1
c3 = (C(1) C(1)) + (C(2) C(2))
6
12
1
1
1
c4 = C(0) (C(1) + C(1)) + (C(2) + C(2)),
4
6
24
avec :
C(0) = a0 b0
C(1) = (a0 + a1 + a2)(b0 + b1 + b2 )
C(1) = (a0 a1 + a2)(b0 b1 + b2 )
C(2) = (a0 + 2a1 + 4a2 )(b0 + 2b1 + 4b2)
C(2) = (a0 2a1 + 4a2 )(b0 2b1 + 4b2).
On en deduit un algorithme calculant le produit de deux polyn^
omes de
longueurs inferieures ou egales a 3n en cinq multiplications de polyn^
omes de
longueurs inferieures ou egales a n :
198
B = B0 + xn B1 + x2n B2
= (A0 + A1 + A2 )(B0 + B1 + B2 )
= (A0 A1 + A2 )(B0 B1 + B2 )
= (A0 + 2A1 + 4A2)(B0 + 2B1 + 4B2)
= (A0 2A1 + 4A2)(B0 2B1 + 4B2).
Exercice 2-2
199
Exercice 2-1
Version vecteur :
(* renvoie le plus grand e
l
ement de v *)
let maximum v =
if vect_length(v) = 0 then failwith "vecteur vide"
else begin
let m = ref v.(0) in
for i = 1 to vect_length(v)-1 do m := max !m v.(i) done;
!m
end
;;
Pour les listes cha^nees, on peut obtenir une fonction recursive terminale
(pouvant sexecuter en memoire constante) en ajoutant un deuxieme parametre
contenant le maximum du debut de la liste :
let rec maxi2 m l = match l with
| []
-> m
| a::suite -> maxi2 (max a m) suite
;;
let maximum l = match l with
| []
-> failwith "liste vide"
| a :: suite -> maxi2 a suite
;;
Exercice 2-2
(* applique f a
` chaque e
l
ement de l en commen
cant par la fin *)
let rec do_list_rev f l = match l with
| []
-> ()
| a::suite -> do_list_rev f suite; let _ = f(a) in ()
;;
200
Exercice 2-3
Avec concatenation en queue :
let rec rev_q l = match l with
| []
-> []
| a::suite -> rev_q(suite) @ [a]
;;
n(n 1)
an2
.
2
2
Exercice 2-5
201
La rotation sur place de k positions peut alors ^etre eectuee par k rotations
dune position avec une complexite totale proportionnelle a kn.
3. Rotation Tournesol. Soit la permutation a eectuer.
decomposition en cycles a supports disjoints :
admet une
= c1 c2 . .. cp ,
o
u chaque ci est un cycle de la forme :
ci = (j,
(j + k) mod n,
(j + 2k) mod n,
. . .)
pour un certain entier j que lon peut supposer compris entre 0 et k 1. Une
iteration de la boucle while :
let temp = v.(!i0)
...
v.(!i) <- temp;
compte := !compte + 1;
202
cest-
a-dire que la partie (contient f suite) nest pas evaluee si (f a) retourne
true. Ainsi, la fonction contient sarr^
ete des quun element satisfaisant le predicat
f est trouv
e, sans parcourir le reste de la liste.
Dernier element veriant le critere : on peut calculer limage miroir de l (cf.
exercice 2-3) puis chercher le premier element de cette liste veriant le critere
a laide du programme cherche_liste presente a la section 2-4. On peut aussi
parcourir la liste en conservant le dernier element trouve jusque l
a:
(* retourne le dernier e
l
ement de l v
erifiant f *)
(* ou a
` d
efaut x
*)
let rec dernier_1 f x l = match l with
| []
-> x
| a::suite -> if f(a) then dernier_1 f a suite
else dernier_1 f x suite
;;
(* retourne le dernier e
l
ement de l v
erifiant f *)
let rec dernier f l = match l with
| []
-> failwith "non trouv
e"
| a::suite -> if f(a) then dernier_1 f a suite
else dernier f
suite
;;
Exercice 2-6
Une methode simple est de comparer le debut de A et B : sils concident alors B
est une sous-liste de A au rang 0. Sinon on cherche si B est une sous-liste de la
queue de A et on adapte le rang eventuellement trouve.
Version liste cha^nee :
(* dit si le d
ebut de a est e
gal a
` la liste b *)
let rec est_d
ebut a b = match (a,b) with
| (_,[])
-> true
| ([],_)
-> false
| (x::sa, y::sb) -> (x = y) & (est_d
ebut sa sb)
;;
(* cherche si b est une sous-liste de a et renvoie
(* le premier rang dapparition de b dans a si oui.
(* Sinon, renvoie -1.
let rec cherche_sous_liste a b = match a with
| []
-> -1
| _::suite -> if est_d
ebut a b then 0
else let i = cherche_sous_liste suite
if i >= 0 then i+1 else -1
;;
*)
*)
*)
b in
Exercice 2-7
Version vecteur :
(* cherche si b est un sous-vecteur de a et renvoie *)
(* le premier rang dapparition de b dans a si oui. *)
(* Sinon, renvoie -1. On suppose b non vide.
*)
let cherche_sous_vect a b =
let
and
and
and
la = vect_length(a)
lb = vect_length(b)
i = ref 0
trouve = ref false in
Exercice 2-7
(* vecteur circulaire avec indice de d
ebut et longueur *)
type a cercle = {v:a vect; mutable d:int; mutable l:int};;
(* ins`
ere x en t^
ete de c *)
let ins_tete c x =
let n = vect_length(c.v) in
if c.l >= n then failwith "plus de place"
else begin
c.d <- (c.d + n - 1) mod n;
c.v.(c.d) <- x;
c.l <- c.l + 1
end
;;
(* ins`
ere x en queue de c *)
let ins_queue c x =
let n = vect_length(c.v) in
if c.l >= n then failwith "plus de place"
else begin
c.v.((c.d + c.l) mod n) <- x;
c.l <- c.l + 1
end
;;
203
204
Remarques :
{ ins_tete decremente lindice de debut par linstruction :
c.d <- (c.d + n - 1) mod n;
et non (c.d - 1) mod n car loperateur mod en caml retourne un resultat negatif
si son premier argument est negatif.
{ Linsertion dun element en t^ete ou en queue peut echouer si le vecteur c.v est
entierement rempli. On peut remedier a ce probleme en recopiant le vecteur c.v
dans un vecteur plus grand en cas de debordement :
type a cercle = {mutable v:a vect; mutable d:int; mutable l:int};;
(* allonge c.v par doublement de taille *)
let allonge c = c.v <- concat_vect c.v c.v;;
Le temps dune insertion nest alors plus constant, mais le temps cumule Tn de
n insertions reste asymptotiquement proportionnel a n car concat_vect v1 v2
sexecute en un temps asymptotiquement proportionnel a la somme des longueurs
de v1 et v2 donc on a lequation de recurrence :
T2n = Tn + (n)
qui a pour solution Tn = (n) (cf. section 6-3).
{ Une autre possibilite dimplementation des listes a double entree est dutiliser
deux listes cha^nees L1 et L2 telles que L = L1 @ miroir(L2 ) (cf. exercice 2-3).
Dans ce cas les operations dinsertion et dextraction peuvent ^etre eectuees de
maniere fonctionnelle, cest-
a-dire sans perdre la liste initiale :
Exercice 3-1
205
type a dbliste = {d
ebut:a list; fin:a list};;
let ins_tete l x = {d
ebut = x::l.d
ebut; fin = l.fin};;
let ins_queue l x = {d
ebut = l.d
ebut; fin = x::l.fin};;
let extr_tete(l) = match l.d
ebut with
| x::suite -> (x, {d
ebut=suite; fin=l.fin})
| []
-> match rev(l.fin) with
| x::suite -> (x, {d
ebut=suite; fin=[]})
| []
-> failwith "liste vide"
;;
let extr_dernier(l) = match l.fin with
| x::suite -> (x, {d
ebut=l.d
ebut; fin=suite})
| []
-> match rev(l.d
ebut) with
| x::suite -> (x, {d
ebut=[]; fin=suite})
| []
-> failwith "liste vide"
;;
206
(* insertion sans r
ep
etition dans une liste cha^
n
ee tri
ee *)
let rec ins`
ere_liste compare l x = match l with
| []
-> [x]
| a::suite -> match compare a x with
| PLUSPETIT -> a :: (ins`
ere_liste compare suite x)
| EQUIV
-> l
| _
-> x :: l
;;
Exercice 3-2
(* fusion sans r
ep
etition de deux listes cha^
n
ees *)
let rec fusion_sr compare l1 l2 = match (l1,l2) with
| ([],_) -> l2
| (_,[]) -> l1
| (a::s1, b::s2) -> match compare a b with
| EQUIV
-> fusion_sr compare l1 s2
| PLUSPETIT -> a :: (fusion_sr compare s1 l2)
| _
-> b :: (fusion_sr compare l1 s2)
;;
(* fusion sans r
ep
etition de deux vecteurs *)
let fusion_vect_sr compare v1 v2 =
let
let
and
and
in
v
i
j
k
=
=
=
=
Exercice 3-5
207
Remarque : fusion_vect_sr initialise le vecteur resultat avec v1.(0) ce qui declenche une erreur si v1 est de longueur nulle. On peut corriger ce defaut en traitant
a part le cas o
u lun des vecteurs est vide et en retournant une copie de lautre
dans ce cas.
Exercice 3-3
La fusion sans repetition fournit la reunion de deux ensembles. Le calcul de
lintersection peut ^etre conduit par un algorithme similaire :
let rec intersection compare e1 e2 = match (e1,e2) with
| ([],_) -> []
| (_,[]) -> []
| (a::s1, b::s2) -> match compare a b with
| EQUIV
-> a :: (intersection compare e1 s2)
| PLUSPETIT -> (intersection compare s1 e2)
| _
-> (intersection compare e1 s2)
;;
Exercice 3-5
Fusion de trois listes : on peut fusionner L1 et L2 dans une liste L puis fusionner
L et L3. Le nombre maximal de comparaisons est :
Ncomp = (`1 + `2 1) + (`1 + `2 + `3 1) = 2`1 + 2`2 + `3 2.
Il y a inter^et avec cette strategie a prendre pour L3 la liste la plus longue, mais si les
longueurs des listes ne sont pas connues a lavance, alors le temps de determination
de la liste la plus longue peut ^etre plus co^
uteux que leconomie realisee en temps
de comparaisons.
Une autre possibilite est de fusionner les trois listes en parallele suivant lalgorithme :
208
Exercice 3-7
209
si 0 6 an < b0 ;
n p = n 1 si b0 6 an < b1 ;
. ..
np = 0
donc :
K1
X
an =0
si bn1 6 an < K.
210
On a alors :
1
K
n+1
X K1
X
L0 an =0
(n p) =
1
K
n+1
(a0 + . . . + an1 ) = n
L0
K1
2K
1 P
K1
ai =
(valeur moyenne de ai sur lensemble des listes L). Donc
K n L0
2
K1
(n + 1) = (n) + n
avec (1) = 0, et nalement :
2K
car
(n) = n(n 1)
K1
.
4K
1
Lorsque K est grand, K1
echanges eectues
4K 4 donc le nombre moyen d
par le tri a bulles dun vecteur de longueur n est de lordre de n2/4, ce qui implique
que la complexite en moyenne du tri a bulles est quadratique (sous lhypothese
dequidistribution de tous les vecteurs de longueur n).
Exercice 3-8
1. Non en general. Par exemple si a0 est le plus grand element de L et si
(a1 , .. ., an1) est triee par ordre croissant, alors L est 1-presque triee a
gauche mais pas a droite.
2. La complexite du tri a bulles sur une liste L est proportionnelle au nombre dinversions de L et, lorsque L est p-presque triee a gauche, ce nombre
dinversions est majore par np. On a le m^eme resultat pour une liste ppresque triee a droite.
Exercice 3-9
On remarque que merge eectue la fusion de deux listes cha^nees suivant la relation dordre denie par la fonction booleenne order (order x y renvoie true si et
seulement si x 4 y).
sort fonctionne de la mani
ere suivante : on constitue par initlist l une
liste de sous-listes de l triees et de longueur 2, la derniere etant eventuellement
de longueur 1. Puis on fusionne ces sous-listes deux par deux avec merge2, et
on recommence tant quil reste au moins deux sous-listes (fonction mergeall).
Par recurrence sur la profondeur de recursion, on montre que la liste renvoyee
par mergeall est constituee de sous-listes triees formant une partition de la liste
initiale l. La recursion est nie car le nombre de sous-listes renvoyees decro^t
strictement a chaque appel jusqu
a ce quil ne reste plus quune seule sous-liste
qui est la liste triee associee a l.
Exercice 3-10
211
Exercice 3-10
(* Cherche la plus grande s
equence croissante initiale *)
(* de la liste l et renvoie cette s
equence et le reste
*)
(* de la liste.
*)
let rec cherche_s
equence compare l = match l with
| [] -> ([], [])
| [a] -> ([a], [])
| a::(b::suite as l) ->
if compare a b = PLUSGRAND then [a],l
else let (s,r) = cherche_s
equence compare l in (a::s, r)
;;
(* fusionne les sous-s
equences croissantes de l deux par deux *)
let rec fusionne_s
equences compare l = match l with
| [] -> []
| _ -> let (l1, r1) = cherche_s
equence compare l in
let (l2, r2) = cherche_s
equence compare r1 in
(fusion compare l1 l2) @ (fusionne_s
equences compare r2)
;;
(* code principal : on fusionne les s
equences deux par *)
(* deux tant quil y en a plusieurs
*)
let rec fusion_naturelle compare l =
let (l1,r1) = cherche_s
equence compare l in
if r1 = [] then l
else let (l2,r2) = cherche_s
equence compare r1 in
fusion_naturelle compare
((fusion compare l1 l2) @ (fusionne_s
equences compare r2))
;;
est proportionnelle a la somme des tailles des listes l1 et l2. Il en est de m^eme
pour la concatenation en queue dans :
(fusion compare l1 l2) @ (fusionne_s
equences compare r2)
et donc fusionne_s
equences compare l a une complexit
e asymptotique O(p) o
up
est la taille de l. Enn, fusion_naturelle itere fusionne_sequences tant quil reste
au moins deux sequences croissantes maximales, et le nombre de telles sequences
est divise par deux ou plus a larrondi superieur pres a chaque iteration. Donc le
nombre diterations est O(ln n) et le temps dexecution de fusion naturelle est
O(n ln n).
212
Remarque : plut^
ot que de rechercher systematiquement les sequences croissantes a
chaque appel a fusionne_s
equences, on pourrait d
ecouper dans un premier temps
l en listes de sequences croissantes, puis les fusionner deux par deux comme dans
lexercice 3-9.
Exercice 3-11
(* d
ecoupe l en deux listes s
epar
ees par le pivot p *)
let rec d
ecoupe compare p l = match l with
| []
-> [],[]
| a::suite ->
let (l1,l2) = d
ecoupe compare p suite in
if (compare a p) = PLUSPETIT then (a::l1,l2) else (l1,a::l2)
;;
let rec tri compare l = match l with
| []
-> []
| a::suite -> let (l1,l2) = d
ecoupe compare a suite in
(tri compare l1) @ (a :: (tri compare l2))
;;
Remarques :
{ Cet algorithme de tri est stable, car decoupe place dans la liste de droite les
elements equivalents a p en conservant leurs dispositions relatives.
{ Lusage de la concatenation en queue, @, nest pas penalisant ici car la complexite de cette concatenation dans le calcul de :
(tri compare l1) @ (a :: (tri compare l2))
est O(n) o
u n est la taille de l et decoupe a une complexite (n) donc le
co^
ut temporel de decoupe suivi de @ reste (n). On peut toutefois eviter la
concatenation en queue avec le code suivant :
(* trie la liste l et la concat`
ene a
` m *)
let rec tri compare l m = match l with
| []
-> m
| a::suite -> let (l1,l2) = d
ecoupe compare a suite in
tri compare l1 (a :: (tri compare l2 m))
;;
Exercice 3-12
let tri_rapide_it
eratif compare v =
(* empile le premier appel *)
let pile = ref [(0,vect_length(v)-1)] in
while !pile <> [] do
let (a,b) = hd(!pile) in
if a < b
(* bornes du vecteur a
` traiter *)
Exercice 4-1
213
x [x]
y [y]
o
u x, y sont des nombres et , des operateurs unaires (le fait que et
soient des operateurs unaires ne restreint pas la generalite du raisonnement
qui suit). On note f1 la formule deduite de f par application de (1), f2
la formule deduite de f par application de (2), f3 la formule deduite de f1
par application de (2) et f4 la formule deduite de f2 par application de (1).
Comme les sous-listes [x, ] et [y, ] ne se chevauchent pas dans f, on a
f3 = f4 . Par hypothese de recurrence f1 et f2 admettent des valeurs bien
denies, et comme f3 est obtenue a la fois par reduction de f1 et de f2 , les
valeurs de f1 et f3 sont egales de m^eme que les valeurs de f2 et f3 . On en
deduit que f1 et f2 ont m^eme valeur ce quil fallait demontrer.
214
Exercice 4-2
Ceci impose de prevoir plusieurs types de valeurs dont le type booleen et les
operations associees pour pouvoir evaluer condition, et donc de tester a chaque
operation si les operandes ont le type requis. Par ailleurs, la forme postxe associee
a une formule conditionnelle est :
exp1, exp2, condition, si
a lordre des termes pres, et donc les deux expressions exp1 et exp2 devront ^etre
evaluees avant de savoir laquelle est a retenir, ce qui ne permet pas devaluer une
formule conditionnelle telle que :
si x 6= 0 alors
sin x
sinon1.
x
*)
*)
Exercice 4-4
215
let y = popv() in
let x = popv() in
po := so;
pushv (f x y);
r
eduit(p)
| _ -> ()
in
(* empile un op
erateur ou une parenth`
ese en
*)
(* effectuant les op
erations binaires prioritaires *)
let pusho lexeme = match lexeme with
| VALEUR(_)
-> failwith "cas impossible"
| OP_UNAIRE(_)
-> po := lexeme :: !po
| OP_BINAIRE(p,_)
-> r
eduit(p); po := lexeme :: !po
| PARENTH`
ESE_OUVRANTE -> po := lexeme :: !po
| PARENTH`
ESE_FERMANTE ->
r
eduit(-1);
match !po with
| PARENTH`
ESE_OUVRANTE::so -> po := so; pushv(popv())
| _ -> failwith "formule incorrecte"
in
(* traitement dun lex`
eme *)
let traitement(lexeme) = match lexeme with
| VALEUR(x) -> pushv x
| _
-> pusho lexeme
in
(* parcours de la formule et extraction du r
esultat *)
traitement PARENTH`
ESE_OUVRANTE;
do_list traitement f;
traitement PARENTH`
ESE_FERMANTE;
match (!pv, !po) with
| [x],[] -> x
| _
-> failwith "formule incorrecte"
;;
Remarques : on a suppose que toutes les priorites des operateurs binaires sont
positives, donc linstruction reduit(-1) eectue toutes les operations unaires et
binaires en instance jusqu
a rencontrer une parenthese ouvrante dans la pile des
operateurs. De m^eme, lintroduction dune parenthese ouvrante avant le parcours
de f et dune parenthese fermante apres ce parcours permet deectuer simplement
les dernieres operations en instance.
216
Exercice 4-5
Il sut de remplacer dans lexercice 4-4 la pile de valeurs pv par une pile de lexemes
et dy empiler les operateurs retires de po dans les fonctions reduit et pushv au lieu
de calculer les resultats de ces operations. Lorsque f a ete entierement parcourue,
pv contient limage miroir de la liste f0 d
esiree.
Exercice 4-6
Lexercice 4-5 fournit un algorithme de construction de f0 , ce qui prouve son
existence. On en demontre lunicite par recurrence sur la longueur de f.
{ Une formule inxe de longueur 1 bien formee est reduite a une variable, et la
seule formule postxe equivalente est elle aussi reduite a cette variable.
{ Considerons une formule inxe bien formee f de longueur n > 1 comportant
donc au moins un operateur. Les regles de priorite determinent de maniere non
ambigue le dernier operateur, op, a evaluer : cest un operateur unaire si f est de
la forme f = op(qqch) et cest loperateur binaire de niveau le plus externe, de
priorite la plus basse et le plus a droite dans les autres cas. Cet operateur doit
donc ^etre place en derniere position de f0 et le debut de f0 est constitue dune ou de
deux formules postxes calculant le ou les operandes de op dans le bon ordre. Ces
formules sont les formules postxes associees aux sous-formules de f denissant
les operandes de op, donc elles sont uniques par hypothese de recurrence.
Exercice 5-1
On a p = p nand p ; p et q = p nand q ; p ou q = p nand q. Donc le connecteur
nand permet dexprimer les trois connecteurs et, ou, non et donc toutes les formules
booleennes.
La negation ne peut ^etre exprimee uniquement a laide de et et de ou car
toute formule non constante constituee de ces connecteurs vaut faux lorsque toutes
les variables valent faux.
Exercice 5-2
1. peutetre
2.
= fun
Vrai ->
_
->
Faux ->
_
->
Vrai
Faux
Faux
Peutetre
Exercice 5-3
217
3.
#(* v
erifie que deux fonctions normandes de trois *)
(* variables sont e
gales
*)
let est_
egal f g =
let val = [|Vrai; Faux; Peutetre|] in
let res = ref(true)
in
for i = 0 to 2 do for j = 0 to 2 do for k = 0 to 2 do
res := !res & ( f val.(i) val.(j) val.(k)
= g val.(i) val.(j) val.(k) )
done done done;
!res
;;
est_
egal :
(normand -> normand -> normand -> a) ->
(normand -> normand -> normand -> a) -> bool = <fun>
#(* associativit
e *)
est_
egal (fun p q r -> et (et p q) r)
(fun p q r -> et p (et q r));;
- : bool = true
#est_
egal (fun p q r -> ou (ou p q) r)
(fun p q r -> ou p (ou q r));;
- : bool = true
#(* distributivit
e *)
est_
egal (fun p q r -> et (ou p q) r)
(fun p q r -> ou (et p r) (et q r));;
- : bool = true
(* etc *)
218
Exercice 5-4
On a : p p vrai, p + q p q pq et (p q)(r s) pr ps qr qs. Ces
trois regles permettent de mettre recursivement une formule exprimee a laide de
et, ou et non sous la forme dune somme exclusive des constantes vrai, faux et de
produit de variables.
On peut aussi considerer quune fonction booleenne est une application de
(Z/2Z)n dans Z/2Z, et quune telle application est polynomiale car Z/2Z est un
corps ni pour les lois et . La transformation dune formule logique en somme
exclusive correspond donc a une ecriture polynomiale de la fonction associee.
On demontre lunicite a ordre pres dune telle ecriture, apres suppression
des termes nuls ou repetes, par recurrence sur n. Pour n = 1 il sut de constater que les quatre expressions possibles, vrai, faux, p et vrai p denissent
des fonctions booleennes de p distinctes. Supposons lunicite etablie pour toute
formule booleenne a n 1 variables et considerons une formule booleenne f a n
variables p1 , .. ., pn, ayant deux decompositions en sommes exclusives simpliees.
En regroupant dans chaque decomposition les termes ayant pn en facteur, on a :
f a bpn c dpn
o
u a, b, c, d sont des sommes exclusives simpliees en les variables p1 , .. ., pn1.
En prenant pn = 0 on obtient a c donc a = c par hypothese de recurrence, et
en prenant pn = 1 on obtient a + b c + d avec a = c do
u b d et donc b = d
par hypothese de recurrence encore (= designe ici legalite a ordre pres).
Puisquil y a unicite on peut tester si f represente une tautologie en calculant
sa forme somme exclusive simpliee : ou bien elle se reduit a vrai et f represente
bien une tautologie, ou bien elle se reduit a faux et f nest jamais satisable, ou
bien elle contient dautres termes et sa valeur nest pas constante. Comme pour la
methode (( forme conjonctive )), cette methode a un co^
ut memoire (et donc aussi
temps) exponentiel dans le pire des cas. Par exemple la forme somme exclusive
reduite de :
(p1 p2 )(p1 p3 ). ..(p1 pn )
est :
M
n
2
p1 p
2 . ..pn
p2 . ..pn
o
u (2 , . .., n ) decrit {0, 1}n1, donc cette forme comporte 2n1 + 1 termes.
Exercice 5-5
La seule diculte est de realiser la reunion sans repetition des listes de variables
de deux sous-formules. Comme les cha^nes de caracteres peuvent ^etre comparees
par lordre lexicographique (ordre total qui est celui que fournit <= en caml), on
peut utiliser la methode de fusion sans repetition sur les listes de variables triees
selon cet ordre.
let rec liste_variables f = match f with
| Const(_) -> []
| Var(p)
-> [p]
Exercice 5-6
219
Exercice 5-6
let rec simplifie f = match f with
| (Const(_) | Var(_)) -> f
| Mono(op,g) -> begin
match simplifie g with
| Const(x) -> Const(op x)
| g
-> Mono(op,g)
end
| Bin(op,g,h) -> begin
match (simplifie g,
| Const(x),Const(y)
| Const(x),h
| g,Const(x)
| g,h
end
simplifie h) with
-> Const(op x y)
-> simplifie_`
a_gauche op x h
-> simplifie_`
a_droite op g x
-> Bin(op,g,h)
where simplifie_`
a_gauche op x f =
match (op x true),(op x false) with
| true,true -> Const(true)
| true,false -> f
| false,true -> Mono(non,f)
| false,false -> Const(false)
and simplifie_`
a_droite op f x =
match (op true x),(op false x) with
| true,true -> Const(true)
| true,false -> f
| false,true -> Mono(non,f)
| false,false -> Const(false)
;;
220
fonctions a
` obtenir *)
true; true; true; false;
true; false; false; true;
false; true; false; true;
false; false; true; false;
true; true; false; true;
(* fonctions de transfert *)
let non
a
= map (fun x -> not x) a;;
let et
a b = map2 (prefix &) a b;;
let ou
a b = map2 (prefix or) a b;;
let ouex a b = map2 (prefix <>) a b;;
let nonet a b = non(et a b);;
let nonou a b = non(ou a b);;
let binops = [et; ou; ouex; nonet; nonou];;
false;
true;
false;
true;
false;
false;
false;
true;
true;
false;
false]
false]
false]
false]
false]
Exercice 5-7
221
*)
*)
*)
*)
222
Exercice 5-9
223
Exercice 5-8
Soit p la profondeur du circuit calculant Sn : par recurrence le nombre dentrees
de ce circuit est au plus egal a 2p et toutes les entrees A0 . . .An1, B0 . ..Bn1
doivent ^etre prises en compte car chacune de ces entrees est susceptible dinuer
sur Sn . On a donc 2p > 2n do
u le resultat.
Exercice 5-9
Premi`
ere m
ethode
2
R00
0
1
0
0
1
0
R01
0
0
1
0
0
1
R0
0
0
1
1
0
0
R1
0
1
0
0
0
1
u
Comme 4 1 [3 ], on a N A1A0 + A3A2 + .. . + A2p1A2p2 [3 ] o
p = dn/2e et A2p1 = 0 si n est impair. Donc, pour obtenir le residu de N
modulo 3, il sut de grouper les bits de N deux par deux, de calculer les residus
modulo 3 de chaque groupe, puis dadditionner modulo 3 les residus obtenus. Le
2
2
circuit logique ci-dessous calcule le residu B1 B0 de A1 A0 modulo 3.
A0
A1
B0
B1
224
A1
0
0
0
0
0
0
1
1
1
B0
0
1
0
0
1
0
0
1
0
B1
0
0
1
0
0
1
0
0
1
C0
0
1
0
1
0
0
0
0
1
C1
0
0
1
0
1
0
1
0
0
On en deduit : C0 = B0 si A0 = A1 = 0, C0 = B0 + B1 si A0 = 1, et C0 = B1
si A1 = 1, soit dans tous les cas : C0 = B0 (A0 + A1 ) + A0(B0 + B1 ) + A1B1 . On
obtient de m^eme : C1 = B1 (A0 + A1 )+A1 (B0 + B1 )+A0 B0 et lon peut construire
un circuit (( additionneur modulo 3 )) implementant ces formules :
A0
A 0 B0
B0 (A0 + A1 )
C1
A1
A1 (B0 + B1 )
C0
B0
A0 (B0 + B1 )
B1 (A0 + A1 )
B1
A 1 B1
Exercice 5-10
225
Exercice 5-10
1.
A0
B0
2.
A0
S0
E0
I0
B0
A1
S1
S
E1
E
I
I1
B1
S0..3
I0..3
S E I
226
D
0
0
0
0
0
0
0
0
1
1
C B
0 0
0 0
0 1
0 1
1 0
1 0
1 1
1 1
0 0
0 0
A
0
1
0
1
0
1
0
1
0
1
a b
1 1
1
1 1
1 1
1
1
1
1 1
1 1
1 1
c
1
1
1
1
1
1
1
1
1
d e f
1 1 1
1
1
1
1
1
1
1 1
1
1
1
1
1
1
1
1 1
1
1
1
C
0
1
0
Do
u les formules :
a
A+B
A+B
1
b
c
1
A+B
AB
1
1
1
d
e
A+B A
A B AB
1
A
a = (C A) + B + D,
b = C(A B),
c = A + B + C + D,
d = C(A + B) + C(A B) + D,
e = A(B + C),
f = C A + B + CAB + D,
g = CB + CAB + D.
f
A+B
AB
1
g
B
AB
1
Exercice 6-3
227
Exercice 6-1
T (n 1)
T (n)
a
=
+
+ b.
1. On a T (n) = nT (n 1) + an + b donc
n!
n!
(n
1)!
(n
1)!
P
Comme la serie k=0 1/k! est convergente, on en deduit quil existe > 0
tel que T (n) n!.
2. Il y a n mineurs dordre n 1 a calculer, C2n mineurs dordre n 2 et de
maniere generale Ckn mineurs dordre n k. Le temps de calcul dun mineur
dordre k connaissant tous les mineurs dordre k 1 est tk = ak + b en
supposant que les mineurs dordre k 1 sont memorises de telle sorte quils
puissent ^etre retrouves en temps constant. Donc le temps de calcul dun
determinant n n est :
n
n
n
X
X
X
(ak + b)Ckn = n2n1a + 2nb.
Ckntk =
Ckntnk =
T (n) =
k=0
k=0
k=0
max(Ckn, 0 6 k 6 n) = Cn
2(n1)/2
.
n
k
k
X
255 X
k+1
m k+1
255 X
m
+
+
=
256 m=1 256m1
256 m=1 256m1
256m1
256k
m=k+1
255 X
m 256
6
=
256 m=1 256m1
255
228
1+ 5
=
2
1 5
1
=
= = 1 .
2
et
v(n) = T (n) T (n 1)
nk
n u(1) v(1) X
+
f(k)
T (n) =
k=2
u(n) v(n)
.
nk
p
P
T (2p ) = 2T (2p1) + p2p donc T (2p ) = 2p T (1) +
k p2 2p1.
k=1
Exercice 6-8
229
Exercice 6-6
On pose np = 2p 1 de sorte que b(np 1)/2c = 2p1 1 = np1. On peut donc
etudier la relation partielle :
T (np ) = 2T (np1) + 2p 1,
qui a pour solution :
p
X
2k 1
T (np ) = 2p T (n0) +
p2p .
k
2
k=0
n
X
k=1
Trec (n k) = a + bn +
n1
X
Trec (k)
k=0
= 2Trec (n 1) + b
donc Trec (n) 2n pour un certain > 0.
En supposant une recuperation systematique de la memoire utilisee par les
variables locales des quune fonction est terminee, comme u_rec nutilise quun
nombre xe de memoires locales (n, s, k et ladresse de retour), le nombre de
positions memoire necessaires au calcul de u_rec est proportionnel au nombre
maximal dappels imbriques, soit Mrec (n) = O(n).
Exercice 6-8
On a de maniere immediate Titer (n) = O(n) et Miter (n) = O(n). Par ailleurs Trec
verie la relation :
Trec (n) = a + Trec (bn/2c) + Trec (bn/3c).
Soit > 0. En posant U(n) =
U(n) 6
Trec (n) + a
on obtient :
n
1
1
U(bn/2c) + U(bn/3c)
2
3
donc si lon a 1/2 + 1/3 6 1 alors la fonction U est bornee et lon en deduit
que Trec (n) = O(n ). Comme lequation 1/2 + 1/3 = 1 admet une unique
racine 0 0.787, on obtient nalement Trec (n) = O(n0 ). Enn Mrec (n) est
proportionnel au nombre maximal dappels imbriques, soit Mrec (n) = O(ln n).
La methode recursive nave savere donc plus ecace que la methode iterative
avec stockage des resultats intermediaires ! Dans le cas particulier de cette equation
230
Exercice 7-7
231
Exercice 7-6
Les ordres prexe sur a et a0 concident ; lordre postxe sur a concide avec
lordre inxe sur a0 ; lordre postxe sur a0 na pas dinterpretation simple pour a.
Exercice 7-7
successeur pr
efixe
let rec succ_pref(i,n) =
if 2*i <= n then 2*i
(* fils gauche *)
else if (i mod 2 = 0) & (i+1 <= n) then i+1 (* fr`
ere droit *)
else if i > 1 then succ_pref(i/2, 2*(i/2)-1)
(* successeur du p`
ere apr`
es suppression des fils *)
else failwith "plus de successeur"
;;
232
Les corrections de descend et succ_post sont immediates. Comme la fonction descend est recursive terminale, descend et succ_post peuvent sexecuter en
memoire constante.
successeur infixe
let rec succ_inf(i,n) =
if 2*i+1 <= n then descend(2*i+1,n) (* desc. gauche du fils droit *)
else if i mod 2 = 0 then i/2
(* p`
ere *)
else if i > 1 then succ_inf(i/2,i-1)
(* successeur du p`
ere apr`
es suppression de ce fils *)
else failwith "plus de successeur"
;;
non compris le temps passe dans les appels recursifs est de la forme ng (i) +
donc le temps total de calcul pour un arbre a de taille n est :
X
T (a) =
ng (i) + n 6 nh + n
ia
P
o
u h la hauteur de larbre (en eet, dans
ng (i) un nffud donne est compte
autant de fois quil a dascendants a sa droite, donc au plus h fois). La complexite
en nh est eectivement atteinte pour un arbre en forme de peigne gauche (chaque
Exercice 7-12
233
branche droite contient un seul nffud). Une meilleure solution consiste a parcourir
larbre en ordre postxe inverse (cf. exercice 7-8) en accumulant les nffuds rencontres, ce qui permet de ne faire que des insertions en t^ete de liste et donne une
complexite lineaire en n :
let rec liste_pr
efixe(a,l) = match a with
| B_vide -> l
| B_noeud(e,g,d) -> let l = liste_pr
efixe(d,l) in
let l = liste_pr
efixe(g,l) in
e :: l
;;
Exercice 7-11
Voir le chier arbres.ml disponible sur le serveur de lINRIA :
http://pauillac.inria.fr/~quercia/automatx.tgz
Exercice 7-12
1. let rec est_sous_arbre(a,b) = match (a,b) with
| (B_vide,B_vide) -> true
| B_noeud(ea,ga,da), B_noeud(eb,gb,db) ->
(a = b) or est_sous_arbre(a,gb) or est_sous_arbre(a,db)
| _ -> false
;;
Legalite entre arbres est predenie en caml (comme legalite entre deux
structures quelconques de m^eme type non fonctionnel). Si ce netait pas le
cas, on pourrait la denir par :
let rec e
gal(a,b) = match (a,b) with
| (B_vide,B_vide) -> true
| (B_noeud(ea,ga,da),B_noeud(eb,gb,db)) ->
(ea = eb) & e
gal(ga,gb) & e
gal(da,db)
| _ -> false
;;
234
Exercice 7-13
On ne peut pas repondre precisement a la question car les donnees fournies (annees
de naissance et de deces des individus) ne permettent pas de savoir dans quel ordre
ont eu lieu les naissances et les deces dans une m^eme annee, ni a quelles dates la
royaute etait eectivement en vigueur (Louis XVII, et les descendants de Charles X
nont pas regne car le regime politique en vigueur alors etait le regime republicain).
Le programme ci-dessous fait abstraction des changements de regime et suppose
que dans une m^eme annee toutes les naissances ont lieu avant tous les deces et que,
en cas de deces multiples, les individus meurent en respectant lordre dynastique.
On parcourt larbre en ordre prexe et on imprime tous les noms dindividus
encore en vie apres le deces du dernier roi rencontre jusqualors.
type individu == string*int*int;; (* nom, naissance, d
ec`
es *)
(* imprime les noms des rois a
` partir de la date d *)
(* retourne la date de d
ec`
es du dernier roi
*)
let rec imprime(d, (G_noeud((x,_,b), fils))) =
if b >= d then print_endline(x);
let f = ref(fils) and d = ref(max b d) in
while !f <> [] do
d := imprime(!d, hd(!f));
f := tl(!f)
done;
!d
;;
Remarquer que larbre donne est incoherent : le cousin de Louis XV est cense ^etre
ne deux ans apres le deces de son pere, cette incoherence gure dans le document
cite en reference.
Exercice 7-14
1. On constitue lexpression parenthesee par parcours prexe inverse comme a
lexercice 7-10 pour garantir une complexite lineaire (rappel : rev calcule
limage dune liste de longueur n en temps (n)).
let rec exp_of_arbre a accu = match a with
| G_noeud(e,f) -> Pargauche :: Etiquette(e)
:: exp_of_for^
et (rev f) (Pardroite :: accu)
and exp_of_for^
et f accu = match f with
| []
-> accu
| n::suite -> exp_of_for^
et suite (exp_of_arbre n accu)
;;
Exercice 7-16
235
and for^
et_of_expr liste = match liste with
| Pardroite :: suite -> ([],suite)
| _ -> let (a,suite) = arbre_of_expr(liste) in
let (f,reste) = for^
et_of_expr(suite) in
(a::f, reste)
;;
arbre_of_expr(liste) v
erie que le debut de liste est lexpression dun arbre et
renvoie cet arbre et le reste de la liste. De m^eme, for^et_of_expr(liste) extrait la
for^et representee par le debut de liste et terminee par une parenthese fermante,
et renvoie cette for^et et le reste de la liste sans la parenthese fermante. La liste
complete represente bien un arbre si et seulement si arbre_of_expr(liste) termine
sans erreur et si le reste de la liste est vide.
Exercice 7-15
(* imprime une formule en pla
cant des parenth`
eses si *)
(* n
ecessaire. "p" est la priorit
e de lop
erateur
*)
(* pr
ec
edent ou suivant.
*)
let rec imprime_avec_parenth`
eses p f = match f with
| Valeur(_)
-> imprime(f)
| Op1(_)
-> imprime(f)
| Op2(_,q,_,_) -> if q < p then begin
print_char (; imprime(f); print_char )
end
else imprime(f)
(* imprime une formule sans placer de parenth`
eses autour *)
and imprime(f) = match f with
| Valeur(v)
-> print_string(v)
| Op1(nom,g)
-> print_string(nom);
print_char (;
imprime(g);
print_char )
| Op2(nom,p,g,h) -> imprime_avec_parenth`
eses p g;
print_char ;
print_string(nom);
print_char ;
imprime_avec_parenth`
eses p h
;;
Exercice 7-16
Soit h(n) la hauteur maximale dun arbre -equilibre de taille inferieure ou egale
a n. On a la relation :
h(n) 6 1 + h(bnc)
et donc par recurrence,
h(n) 6 k + h(bk nc).
En prenant k = d ln(n)/ ln()e on obtient h(n) = O(ln n) et linegalite inverse
est vraie pour tout arbre binaire de taille n, quil soit equilibre ou non.
236
Exercice 7-17
Pour h N soit m(h) le plus petit nombre de nffuds dun arbre de hauteur h
equilibre a k pres. On a pour h > 2 :
m(h) = 1 + m(h 1) + min(m(h 1), m(h 2), . .., m(h k 1)).
Par consequent la fonction m est croissante sur N et m(0) = 1, m(1) = 2, donc
elle est croissante sur N. On en deduit :
m(h) = 1+m(h1)+m(hk1) 1+m(h) = (1+m(h1))+(1+m(hk1)).
Soit lunique racine positive de l equation xk+1 = xk + 1 (1 < < 2). Par
recurrence on a m(h) > ch pour une certaine constante c donc :
h6
ln(m(h)) ln c
.
ln
ln(n) ln c
.
ln
Exercice 7-18
1. La transformation (( ls gauche - frere droit )) met en correspondance les
arbres generaux ordonnes a n nffuds et les arbres binaires a n nffuds dont
la branche droite est vide. Donc Gn = Bn1.
2. Cest immediat par recurrence sur n. Lexercice 7-14 fournit par ailleurs
un algorithme de calcul de larbre represente par une liste admissible de
parentheses.
3. On note f(i) la dierence entre le nombre de parentheses ouvrantes et le
nombre de parentheses fermantes dans [u0, .. ., ui1]. La gure ci-dessous
presente les graphes des fonctions f associees aux iterees par T de la suite
u = [ ( ) ( ( ) ) ) ( ].
Exercice 7-19
237
1 n1
C
,
n 2n2
Bn =
1
Cn .
n + 1 2n
Exercice 7-19
1. Soit h la hauteur de a et x un nffud de profondeur h. Sil existe un nffud y
de profondeur h0 < h 1 ayant une branche vide, alors on peut (( deplacer ))
le nffud x pour le mettre a la place de cette branche vide. Larbre a0 obtenu
est un arbre binaire a n nffuds tel que Le (a0 ) = Le (a) + h0 h + 1 < Le (a)
donc la longueur du chemin externe de a nest pas minimale. Ceci prouve
quune condition necessaire pour que Le (a) soit minimale est que tous les
nffuds de profondeur inferieure ou egale a h 2 ont deux ls, ce qui equivaut
a dire quil y a 2k nffuds de profondeur k pour tout k [[0, h 1]].
Reciproquement, supposons cette derniere condition remplie et notons
p le nombre de nffuds de a de profondeur h. Alors n = p + 2h 1 avec
1 6 p 6 2h do
u h = blog2 nc, p = n + 1 2h et :
Le (a) = 2p(h + 1) + (2h p)h = (n + 1)h + 2p,
quantite independante de larbre considere, et donc minimale. Linegalite
Le (a) > (n + 1)blog 2 nc pour un arbre binaire quelconque a n nffuds est
alors immediate.
2. On represente les comparaisons eectuees par A lors du tri dune permutation par des questions de la forme : (( est-ce que (i) > (j) ? )) o
u i et j
sont deux entiers (( choisis )) par A en fonction des reponses obtenues pour
les questions precedentes (linegalite dans la question pourrait ^etre stricte,
mais cest une distinction sans importance puisquon trie des listes delements
distincts).
On construit alors un arbre de decision a associe a A de la maniere
suivante : la racine de a est etiquetee par la premiere comparaison eectuee
par A sur une permutation . Cette premiere comparaison est independante
de puisque A est un algorithme de tri par comparaisons. Les branches
de larbre de decision sont denies recursivement : la branche gauche est
238
Exercice 8-2
On peut trier une liste en construisant un arbre binaire de recherche associe et
en le parcourant en ordre inxe. Comme le parcours inxe dun arbre a une
complexite lineaire en la taille de larbre, on obtient ainsi un algorithme de tri
par comparaisons de complexite Tn + O(n), do
u le resultat compte tenu de la
complexite intrinseque dun tri par comparaisons.
Exercice 8-5
239
Exercice 8-3
(* place les e
l
ements de v.(a..b) dans un arbre de recherche *)
let rec construit v a b =
if a > b then B_vide
else if a = b then B_noeud(v.(a),B_vide,B_vide)
else let c = (a+b)/2 in
B_noeud(v.(c), construit v a (c-1), construit v (c+1) b)
;;
let arbre_of_vect v = construit v 0 (vect_length(v)-1);;
jn 1 k
2
+T
l n 1 m
2
+ K,
do
u lon deduit T (n) 6 max(T (1), K)n par recurrence sur n. Ainsi, T (n) = O(n)
et m^eme T (n) = (n) car chaque element du sous-vecteur est place dans larbre.
Le cas dune liste cha^nee triee peut se traiter de m^eme, mais il faut parcourir
la liste pour reperer lelement median et ceci doit ^etre fait a chaque niveau de
recursion, ce qui donne une complexite (n ln n). Il est preferable de recopier la
liste dans un vecteur avant de la mettre en arbre.
Exercice 8-4
Par recurrence sur n, on montre que larbre obtenu par insertion aux feuilles est
identique a celui obtenu par insertion a la racine en inversant lordre dinsertion
des elements.
Exercice 8-5
Pour fusionner un arbre a de racine r et un arbre b on decoupe b en arbres majore
et minore par r et on fusionne ces sous-arbres avec les branches de b.
let rec fusion compare a b = match a with
| B_vide -> b
| B_noeud(e,g,d) ->
let (g,d) = d
ecoupe compare e b in
B_noeud(e, fusion compare g g, fusion compare d d)
;;
240
Exercice 9-2
and contient l l
| _,
[]
| [],
_
| (a::s), (b::s)
241
;;
figure_liste parcourt la liste l jusqu
a trouver un terme dans lequel gure f ou
avoir epuise la liste, et contient dit si une liste en contient une autre, ces listes
x (xx )
.. ..
242
Exercice 9-3
On note T (n) le nombre maximal de nffuds que peut contenir la derivee dune
expression de n nffuds. La derivation de f1 .. .fn1 (x) montre que T (n) > n2/2.
Supposons quil existe un nombre K > 1 tel que T (k) 6 Kk2 pour tout k strictement inferieur a n et considerons une formule e a n nffuds (n > 2).
Si e = f(u) alors e0 = u0f0 (u) comporte au plus K(n 1)2 + a(n 1) + b
nffuds o
u a est le nombre doccurrences de x dans f0 (x) et b le nombre de nffuds
0
de f (x) autres que ces occurrences. En considerant que a et b sont bornes, on
peut supposer que a 6 2K et b 6 K quitte a changer K, et donc le nombre de
nffuds de u0f0 (u) est majore par Kn2.
Si e = a1 e1 + . .. + ap ep alors e0 = a1 e01 + . . .ap e0p . Soient n1, .. ., np les
nombres de nffuds de e1, . .., ep : n1 + .. . + np = n 1 et le nombre de nffuds
de e0 est majore par :
1 + K(n21 + . .. + n2p ) 6 1 + K(n1 + . .. + np )2 6 Kn2.
a
p
1
Si e = ea
u ei contient ni nffuds alors e0 =
1 . . .ep o
0
nombre de nffuds de e est majore par :
ai e0ie1
i e, donc le
(n 1) = (1 K)n2 + K(n 1)
Exercice 9-4
243
et ces quantites sont negatives si K > 2 et n > 1. Comme est une fonction
convexe, on a aussi (p) 6 0 pour K > 2, p [1, n 1]. Lhypothese T (n) 6 Kn2
est donc recurrente et par consequent etablie. La complexite spatiale est proportionnelle au nombre de nffuds crees (m^eme en tenant compte de la pile de
recursion puisque sa hauteur est celle de e) donc est O(n2 ). De m^eme, le temps
de creation dun nffud etant borne, et la derivation se resumant a la creation de
nffuds et a quelques calculs en nombre borne par nffud, la complexite temporelle
est elle aussi O(n2 ).
Exercice 9-4
Il sagit en fait dun probleme de parcours de graphe o
u lon ne veut passer quune
seule fois par chaque nffud. Une solution nave est dajouter a la representation
des nffuds un indicateur mutable signalant que le nffud a dej
a ete traite :
type a r
esultat = Inconnu | Calcul
e of a;;
type a mexpression = {
exp
: a expression;
mutable res : a mexpression r
esultat
}
and a expression =
| MConst of a
| MVar of string
| MFct of string * (a mexpression)
| MCL of (a * a mexpression) list
| MPG of (a * a mexpression) list
;;
*)
*)
*)
*)
*)
*)
let rec d
erive x m = match m.res with
| Calcul
e(r) -> r
| Inconnu -> let e = match m.exp with
| MConst(_) -> MConst(0.0)
| MVar(v)
-> if v = x then MConst(1.0) else MConst(0.0)
244
Tn = 1 + max(pTnp1 ,
1 6 p 6 n 2).
Exercice 9-6
| u
end
245
-> Fct(f,u)
in
in
in
in
(*
(*
(*
(*
(*
(*
(*
(*
c l)
*)
*)
*)
*)
*)
*)
*)
*)
246
Exercice 10-2
247
ainsi assure que tous les termes constants gureront en debut de liste apres classement, ce qui simplie le regroupement des constantes. Cette simplication est
probablement (( non portable )) et devra ^etre revue si lon change de compilateur.
Exercice 9-7
Dapres lexercice 9-3, si e est une expression a n nffuds alors e/x a O(n 2)
nffuds donc la simplication de e/x prend un temps O(n4 ln n). Si lon simplie
au fur et a mesure les sous-expressions que lon derive, en notant T (e) le temps de
calcul et simplication de e/x, on a :
T (e) 6
T (f(u)) 6 T (u) + n2 ln n,
T (a1 e1 + . .. + ap ep ) 6 T (e1 ) + . .. + T (ep ) + n2 ln n,
a
p
2
1
T (ea
1 . ..ep ) 6 T (e1 ) + . .. + T (ep ) + n ln n.
248
Exercice 10-3
Soit X lensemble des chires autres que 1 et 3 et L le langage cherche. On a :
L = (X + 3) (1 1X(X + 3) ) 1 .
En eet, si u est un mot quelconque, on peut decouper u en facteurs separes par
des suites de 1, cest-
a-dire u = u1 1n1 .. .up 1np o
u les ui ne contiennent pas le
chire 1, ui 6= pour i > 2 et n1 > 1, .. . np1 > 1, np > 0. Alors u L
si et seulement si u2, .. . , up ne commencent pas par 3, soit u1 (X + 3) et
ui X(X + 3) pour i > 2. En decoupant un mot suivant les suites de 3, on
obtient une autre expression :
L = 3 ((X + 1) X33) (X + 1) .
Exercice 10-4
1. 01 2 3 4 5 6 78 9 .
2. Le langage des suites arithmetiques de raison nulle est : 0 + 1 + . .. + 9 .
Les suites arithmetiques de raison non nulle sont en nombre ni (puisque les
termes sont bornes), il sut de les lister toutes.
Exercice 10-5
On note a, b, c, d, e les caracteres (, ), {, } et * et a0 , b0, c0 , d0, e0 les ensembles
complementaires dans lensemble de tous les caracteres. Alors le langage des commentaires est deni par :
L = aeL1 eb + cd0 d
o
u L1 est le langage des mots ne comportant pas la sequence *). On a, comme a
lexercice 10-3 :
L1 = e (e0(b + e)0 bb ) e0 .
Exercice 10-6
1. Soit X solution de X = KX+L. On a donc X = K(KX+L)+L = K2 X+(K+)L
puis de proche en proche :
X = Kn X + (Kn1 + . . . + K + )L
pour tout entier n > 1. Comme K ne contient pas le mot vide, la longueur
dun mot de Kn X est au moins egale a n, donc tout mot de X appartient a
lun des langages (Kn1 + . .. + K + )L pour n assez grand. Ceci prouve que
X KL. Reciproquement, tout mot de K L appartient a un langage de la
forme (Kn1 + .. . + K + )L pour n convenable, donc appartient aussi a X,
do
u X = K L. Enn, le langage K L est eectivement solution de lequation :
KKL + L = (KK + )L = K L.
Remarque : si K contient le mot vide alors K L est encore solution de lequation, mais il ny a plus unicite car tout langage contenant K L est aussi
solution.
Exercice 10-8
2. Le systeme :
249
X = KX + LY + M
Y = K0 X + L0 Y + M0
250
Exercice 11-1
P
On construit un automate simulant levaluation de ak 2k mod 3 par lalgorithme
rner :
de Ho
0
1
0
1
2
Exercice 11-2
On interprete les mots sur {0, 1} comme les representations binaires de nombres
entiers naturels avec bit de poids faible en t^ete. Notons f(x) (resp. g(x), h(x)) le
mot emis par lautomate lorsquil part de letat 0 (resp. 1, 2) et lit le nombre x,
complete par susamment de zeros pour rejoindre letat nal (ce nombre est bien
deni puisque lautomate emet 0 lorsquil lit un zero a partir de letat 0). On a :
f(0) = 0,
g(0) = 1,
h(0) = 2,
f(2x) = 2f(x),
g(2x) = 2f(x) + 1,
h(2x) = 2g(x),
f(2x + 1) = 2g(x) + 1,
g(2x + 1) = 2h(x),
h(2x + 1) = 2h(x) + 1.
0
0
1
2
1
3
4
5
2 3 4 5 6
6 9 12 15 18
7 10 13 16 19
8 11 14 17 20
7 8 9 10
21 24 27 30
22 25 28 31
23 26 29 32
Exercice 11-5
251
dune quatrieme lettre, , representant le temps qui passe et qui sera emise a
intervalles reguliers pour forcer lascenseur a changer detat lorsquil ny a pas
dappels.
_
2
0A
_
0M1
0
M12
0M2
0
M1
_
0M12
_
M2
M02
_
2
_
M012
M01
_
1M2
1A
1M02
0
_
0
1M12
_
2A
1M02
_
2D1
1M2
2
1D1
2D0
1
_
2
1D01
_
1D0
destinations
2
D01
_
1
_
1D012
1D12
_
1D0
direction
_
1D02
position
M12
1M012
_
2D01
1D02
_
D0
_
D02
D012
Exercice 11-5
Premi`
ere
etape : calcul des cl
otures par -transitions.
On represente les ensembles detats par des vecteurs de booleens et il sagit de
construire une matrice m telle que m.(i).(j) vaut true si et seulement si lon peut
passer de letat i a letat j par -transitions. Dans un premier temps on initialise m
avec toutes les -transitions connues, puis on applique lalgorithme de Warshall
pour trouver les etats accessibles par -transitions generalisees.
let cl^
oture(n,liste) =
(* n = nombre d
etats, liste = liste des e-transitions *)
(* retourne la matrice dincidence m
*)
(* cr
eation et initialisation de la matrice dincidence *)
let m = make_matrix n n false in
for i = 0 to n-1 do m.(i).(i) <- true done;
do_list (fun (x,y) -> m.(x).(y) <- true) liste;
252
;;
l
etat k et passant par des
etats interm
ediaires de num
ero strictement
inf
erieur a
i.
Complexite : O(n3 ) de maniere evidente (si liste ne comporte pas de repetitions
et donc est de taille inferieure ou egale a n2).
Deuxi`
eme
etape : calcul des transitions sur lettre.
A laide de la matrice m obtenue precedemment et de la liste des transitions sur
lettre fournie en argument, on construit la matrice t de transition generalisee de
lautomate, telle que t.(i).(a) est lensemble des etats accessibles a partir de
letat i par transition sur la lettre a puis -transitions.
let transitions_g(n,p,liste,m) =
(* n = nombre d
etats, p = nombre de lettres
(* liste = liste des transitions sur lettre
(* m = matrice dincidence
(* renvoie la matrice de transition g
en
eralis
ee
*)
*)
*)
*)
La complexite de cette etape est O(pn3 ) en considerant que liste contient au plus
pn2 triplets (cest-
a-dire est sans repetitions).
Exercice 11-5
253
Troisi`
eme
etape : calcul des ensembles d
etats accessibles depuis les
etats initiaux.
On applique la methode vue en cours : ne generer que les ensembles detats
necessaires. Pour cela on part de lensemble des etats initiaux (sous forme de
vecteur de booleens) et on essaye toutes les transitions jusqu
a ce quil ny ait
plus de nouvel etat cree. De facon a garder un temps dacces constant, les etats
dej
a crees sont conserves dans un vecteur de longueur variable dont la taille est
doublee a chaque fois quil menace de deborder (ce doublement garantit un temps
dinsertion moyen constant).
type a m
emoire = {
mutable v : a vect; (* vecteur sur-dimensionn
e
*)
mutable l : int};; (* nombre d
el
ements pr
esents *)
(* cherche "
etat" dans la m
emoire "mem" et lins`
ere au besoin *)
(* "mem" est modifi
ee sur place, renvoie lindice de "
etat". *)
let num
ero(mem,
etat) =
let i = ref(0) in
while (!i < mem.l) & (mem.v.(!i) <> e
tat) do incr i done;
if !i < mem.l then !i (* e
tat d
ej`
a enregistr
e *)
else begin
(* e
tat non trouv
e, il faut lins
erer *)
if mem.l = vect_length(mem.v) then begin
(* plus de place, agrandit le tampon *)
let w = make_vect (2*mem.l) e
tat in
for j = 0 to mem.l - 1 do w.(j) <- mem.v.(j) done;
mem.v <- w
end;
(* maintenant il y a assez de place, ins`
ere "
etat" *)
mem.v.(mem.l) <- e
tat;
mem.l <- mem.l + 1;
!i (* indice de "
etat" *)
end
;;
Il ny a plus qu
a calculer les sous-ensembles obtenus a partir du sous-ensemble
initial et a construire la nouvelle table de transition :
(*
(*
(*
(*
(*
(*
n = nombre d
etats (autom. ind
eterministe)*)
p = nombre de lettres
*)
initiaux = liste des e
tats initiaux
*)
finals
= liste des e
tats finals
*)
m = matrice dincidence
*)
t = matrice de transition g
en
eralis
ee
*)
254
Exercice 11-6
255
256
Lensemble E retourne ne contient manifestement que des etats accessibles et si q est un etat accessible alors on montre que q est place dans E par
recurrence sur la longueur dun chemin dans A reliant un etat initial a q.
Lensemble des etats coaccessibles sobtient de m^eme a partir de lensemble
des etats nals de A et des ensembles de predecesseurs dun etat.
3. A est deterministe si et seulement si les langages dentree des etats de A sont
deux a deux disjoints.
4. B et C reconnaissent le langage Lf
A donc D et E reconnaissent le langage LA .
En particulier E est equivalent a A.
Lalgorithme de determinisation par la methode des sous-ensembles sans
etat rebut ne produit que des etats accessibles donc tous les etats de C sont
accessibles, et par consequent tous les etats de D sont coaccessibles. Les etats
de E sont des ensembles detats de D non vides (car on determinise sans etat
rebut), ils sont eux aussi tous coaccessibles.
C etant deterministe a etats accessibles, les langages dentree des etats
de C sont deux a deux disjoints non vides donc les langages de sortie des etats
de D sont eux aussi deux a deux disjoints et non vides. Alors si {q1, . .., qn}
est un etat de E, son langage de sortie dans E est la reunion des langages de
sortie dans D des etats q1 , . .., qn, elle est distincte de toute autre reunion
associee a un sous-ensemble dierent de {q1 , . .., qn}.
5. Soient q1 , . .., qn les etats de E et, pour chaque i, ui un mot de LA menant
E de son etat initial a qi . Soit E 0 un automate deterministe quelconque
reconnaissant LA et q0i letat de E 0 atteint a partir de son etat initial par la
suite de transitions indexee par ui. Les langages de sortie des qi dans E sont
deux a deux distincts donc il en est de m^eme pour les langages de sortie des
q0i dans E 0 . En particulier les etats q0i sont deux a deux distincts et E 0 a au
moins autant detats que E.
Ainsi E est un automate deterministe equivalent a A, minimal en nombre detats. On peut demontrer en prolongeant le raisonnement precedent
que si E 0 a autant detats que E alors E et E 0 sont isomorphes par la correspondance qi 7 q0i .
Exercice 11-7
Si L = F + G(an ) alors L est regulier. Si L est ni, L = L + (a0 ) . Si L est
Exercice 11-10
257
Exercice 11-8
Soit A un automate ni reconnaissant L. Si x est un etat de A, on note Ix le
langage menant de letat initial de A a x et Fx le langage menant
de x a un etat
nal de A. Alors Ix et Fx sont reguliers (thm. de Kleene) et L est la reunion
pour tous les etats x de A des langages reguliers Ix Fx.
(w1M)M .
sont les residuels de M : u M =
u=vw
vM
Exercice 11-10
1.
let v
erifie(v) =
let n = vect_length(v) and i = ref(0) and j = ref(0) in
while (!i < n) & (v.(!i) = a) do i := !i+1 done;
j := !i;
while (!j < n) & (v.(!j) = b) do j := !j+1 done;
(!i*2 = n) & (!j = n)
;;
258
Exercice 11-11
Lautomate ci-contre reconna^t le langage L5 qui est
donc un langage regulier (le numero dun etat correspond a la dierence |x|a |x|b mod 5, o
u x est le
prexe dej
a lu du mot a analyser). Par contre, pour
tous n, p N avec n 6= p on a bn (an )1 L et
bn
/ (ap )1 L donc les residuels (an )1L sont deux
a deux distincts ce qui prouve lirregularite de L.
b
a
4
a
a
2
3
b
Exercice 11-12
1. Si n, p N alors parmi les residuels (an b)1 L, seul (ap b)1 L contient cp+1 ,
donc ces residuels sont distincts et en nombre inni.
2. On construit un automate (( additionneur )) qui eectue laddition en binaire
des nombres m et n et verie au fur et a mesure que le chire de p correspondant est le bon. Les etats de lautomate ci-dessous sont notes N (pas de
retenue, on attend un chire de m), Nx (pas de retenue, on a lu le chire
x de m et on attend celui de n), Nxy (pas de retenue, on a lu les chires x
de m et y de n) et de m^eme pour R, Rx et Rxy lorsquil y a une retenue en
attente.
1
0
N10
N0
0
N00
0
0
1
N
0
1
N11
1
N1
R1
0
0
1
R
1
1
R11
Exercice 11-13
On montre que L verie le lemme de letoile avec n = 3. Soit u = p~
pq avec
p A+ et q A . On decompose u sous la forme u = xyz avec |xy| 6 3, |y| > 1,
et xykz L pour tout k N de la maniere suivante :
{ Si |p| = 1 alors on choisit x = p~
p, y = la premiere lettre de q (qui existe
puisque |u| > 3) et z = le reste de q. Donc xyk z = p~
pyk z L pour tout
k N.
{ Si |p| > 2 alors on choisit x = , y = la premiere lettre de p et z = le reste
de u. On a p = yr avec r A+ donc xy0z = r~ryq L, xy1z = u L et si
k > 2 alors xyk z = yk r~ryq L car y est une lettre.
Ainsi, L verie le lemme de letoile. Pourtant L nest pas regulier, car si a, b
sont deux lettres distinctes alors les residuels Ln = (abn )1L sont deux a deux
distincts quand n decrit N : Ln est le seul de ces residuels a contenir le mot bn a.
Exercice 11-14
On montre par recurrence sur la taille de E que levaluation de E 0 retourne :
0 si et seulement si L = ,
1 si et seulement si L = ,
2 si et seulement si L est ni dierent de et ,
si et seulement si L est inni.
260
Question 1-a
a0 = a mod 2.
Question 1-b
ba/2c = a1 + 2a2 + 4a3 + . .. + 2n2an1 .
Question 1-c
let rec bit_r p a = if p = 0 then a mod 2 else bit_r (p-1) (a/2);;
let bit_i p a =
let x = ref(a) in
for i = 0 to p-1 do x := !x/2 done;
!x mod 2
;;
el
ements
etant conserv
e dans chaque groupe.
Question 2-b
let permute v =
let n = vect_length(v) in
let w = make_vect n 0 in
let i = ref(0) and j = ref(0) in
for k = 0 to n-1 do
if v.(k) mod 2 = 0 then begin v.(!i) <- v.(k); i := !i+1 end
else begin w.(!j) <- v.(k); j := !j+1 end;
done;
for k = 0 to !j-1 do v.(!i+k) <- w.(k) done
;;
261
Question 2-c
a + 2b.
Question 2-d
Remplacer le test : if v.(k) mod 2 = 0 par : if (bit p v.(k)) = 0.
Question 3-b
let tri
let n
let M
let K
for p
;;
v
=
=
=
=
=
vect_length(v) in
ref(v.(0)) in for i = 1 to n-1 do M := max !M v.(i)
done;
ref(0)
in while !M > 0
do K := !K+1; M := !M/2 done;
0 to !K-1 do permute p v done
Question 3-c
Si la suite (v0 mod 2p , .. ., vn1 mod 2p ) est croissante, alors les sous-suites de
(v0 , . . ., vn1) determinees par permute p v sont elles aussi croissantes (( modulo
2p )) puisque permute conserve lordre relatif des elements. On place en t^ete de v
les elements ayant un bit de rang p nul, cest-
a-dire ceux compris entre 0 et 2p 1
p+1
modulo 2
, puis les elements compris entre 2p et 2p+1 1 modulo 2p+1 donc
la suite (v0 mod 2p+1 , . . ., vn1 mod 2p+1 ) est bien croissante.
Question 3-d
La complexite est O(n) ou plus precisement O(n ln M).
Interpolation de Lagrange
et multiplication rapide
Question 1
rner vu en cours :
On utilise lalgorithme de Ho
Valeur(P, z) : calcule la valeur du polyn^
ome P au point z.
n longueur(P)
r 0
pour i = n 1...0 faire : r r z + P.(i)
retourner r
n
Validite : a la sortie de la boucle on a linvariant : r = ai + . .. + an1zni1.
Complexite : n multiplications et n additions, soit T (n) = 2n.
262
Question 2
On itere le calcul de P(xi ) pour chaque i :
Liste valeurs(P, X) : calcule la liste des valeurs P(xi).
n longueur(X)
Y vecteur de longueur n
pour i = 0...n 1 faire : Y.(i) Valeur(P, X.(i))
retourner Y
n
Complexite : n appels a Valeur, soit T (n) = 2n2.
Question 3
Fonctions auxiliaires de calcul sur les polyn^
omes :
Combinaison(P, Q, a, b) : calcule aP + bQ
p longueur(P)
q longueur(Q)
r max(p, q)
R [|0; ...; 0|] (r fois zero)
pour i = 0...p 1 faire : R.(i) a P.(i)
pour i = 0...q 1 faire : R.(i) R.(i) + b Q.(i)
retourner R
n
Complexite : T (p, q) = p + 2q.
Produit(P, a, b) : calcule P(z) (az + b).
n longueur(P)
R vecteur de longueur n + 1
pour i = 1...n 1 faire : R.(i) b P.(i) + a P.(i 1)
R.(0) b P.(0)
R.(n) a P.(n 1)
retourner R
n
Complexite : T (n) = 3n 1.
Formule de Lagrange
On calcule pour chaque i le polyn^
ome Li et on cumule les polyn^
omes yiLi dans le
resultat :
Lagrange(X, Y) :
calcule le polyn^
ome P tel que P{X} = Y par la formule de Lagrange
n longueur(X)
P [|0; ...; 0|] (n fois zero)
pour i = 0...n 1 faire :
L [|Y.(i)|] (polyn^
ome constant)
pour j = 0...n 1 si j 6= i faire :
263
a 1/(X.(i) X.(j))
b X.(i) a
L Produit(L, a, b)
n pour j
P Combinaison(P, L, 1, 1)
n pour i
retourner P
n
Complexite : dans la boucle pour j il est fait 4 operations pour calculer a et b et
3k1 operations pour calculer Produit(L, a, b) o
u k est la longueur courante de L.
Cette longueur prend les valeurs 1, 2, .. ., n donc le nombre total doperations pour
calculer yiLi est :
n
X
(3k + 3) = 32 n2 + 92 n.
k=1
15 2
2 n
= O(n3 ).
Formule de Newton
On calcule recursivement P et U :
Newton aux(X, Y, i) :
calcule le polyn^
ome P pour x0 , .. ., xi et le polyn^
ome V(z) = (zx0). ..(zxi ).
si i = 0 alors retourner ([|Y.(0)|], [| X.(0); 1|])
sinon :
(Q, U) Newton aux(X, Y, i 1)
c (Y.(i) Valeur(Q, X.(i)))/Valeur(U, X.(i))
P Combinaison(Q, U, 1, c)
V Produit(U, 1, X.(i))
retourner (P, V)
n sinon
n
Newton(X, Y) :
n longueur(X)
(P, V) Newton aux(X, Y, n 1)
retourner P
n
Complexite : soit Taux (i) le temps necessaire au calcul de Newton aux(X, Y, i). On
a la relation de recurrence :
Taux (0) = 1;
Taux (i) = Taux (i 1) + 10i + 9.
264
n1
X
i=0
Formule dAitken
La formule donnee contient deux appels recursifs, ce qui conduit a calculer plusieurs
fois les polyn^
omes intermediaires et a une complexite totale exponentielle. Il faut
donc memoriser les calculs eectues :
Aitken(X,Y) :
calcule tous les polyn^
omes Pa,b et renvoie le dernier.
n longueur(X)
table tableau n n de polyn^
omes vides
pour i = 0...n 1 faire : table.(i).(i) Y.(i)
pour k = 1...n 1 faire :
pour i = 0...n k 1 faire :
a 1/(X.(i) X.(i + k))
b X.(i + k) a
c a
d X.(i) a
P Produit(table.(i).(i + k 1), a, b)
Q Produit(table.(i + 1).(i + k), c, d)
table.(i).(i + k) Combinaison(P, Q, 1, 1)
n pour i
n pour k
retourner T.(0).(n 1)
n
Complexite : le calcul de table.(i).(i + k) requiert 9k + 7 operations (car les polyn^
omes table.(i).(i + k 1) et table.(i + 1).(i + k) sont de longueur k). On obtient :
T (n) =
n1
X nk1
X
(9k + 7) =
k=1
i=0
n1
X
k=1
(n k)(9k + 7) = 32 n3 + 72 n2 5n = O(n3 ).
265
Question 4-b
Interpole(Y) :
calcule le polyn^
ome dinterpolation de Y aux racines de lunite.
n longueur(Y)
si n = 1 retourner [|Y.(0)|]
sinon :
diviser Y en deux parties Y0 , Y1 comme d
eni dans l
enonc
e
P0 Interpole(Y0)
P1 Interpole(Y1)
calcul du polyn^
ome P1 (xe2i/n)
z 1
pour k = 0...n/2 1 faire :
P1 .(k) P1 .(k) z
z z e2i/n
n pour k
combine P0 et P1
R vecteur de longueur n
pour k = 0...n/2 1 faire :
R.(k) (P0 .(k) + P1 .(k))/2
R.(k + n/2) (P0.(k) P1 .(k))/2
n pour k
retourner R
n sinon
n
Question 4-c
Si lon excepte les appels recursifs, Interpole eectue un nombre doperations
complexes lineaire en n. On a donc lequation T (2 ) = 2T (21 ) + a2 + b que
lon resout en :
T (21 )
T (2 )
=
+ a + b2 ,
2
21
T (1)
T (2 )
+ ( 1)a + b( 12 2 ),
=
2
1
T (2 ) a2 = O(n ln n) pour n .
Question 4-d
Le principe est le m^eme : on divise P en deux polyn^
omes
(( entrelaces )) :
266
temps total de calcul suit une relation de recurrence similaire a celle etablie pour
lalgorithme dinterpolation.
Question 5
On calcule les listes des valeurs de P et Q pour les racines 2n-emes de lunite
en O(n ln n) operations, on multiplie terme a terme ces deux listes en O(n)
operations, ce qui donne la liste des valeurs du produit PQ pour les racines 2n-emes
de lunite. Cette liste permet de reconstituer PQ par interpolation en O(n ln n)
operations.
Le choix des racines de lunite permet donc de multiplier deux polyn^
omes
en O(n ln n) operations, au lieu de n2 multiplications et n(n 1) additions complexes pour la multiplication par distributivite et (nlog2 (3) ) pour la multiplication
recursive de Karatsuba. Cependant cet algorithme, appele multiplication par
transformation de Fourier rapide, necessite deectuer des calculs en nombres
complexes, donc approches. On obtient alors une approximation du produit. Sil
sagit de polyn^
omes a coecients entiers, sachant que le resultat est a coecients
entiers on peut arrondir le resultat approche : Knuth demontre que lincertitude
sur les coecients de PQ est de lordre de (n ln n) o
u est lincertitude sur une
operation. Donc, pour n ln n 1018, il sut de faire les calculs (( avec une vingtaine de chires apres la virgule )) pour ^etre s^
ur davoir un arrondi correct. Par
ailleurs, le gain en vitesse nest reel que pour de tres grandes valeurs de n compte
tenu des complications de lalgorithme et de la necessite de garantir la precision des
calculs intermediaires. La multiplication par transformation de Fourier rapide
est utilisee pour les calculs sur des tres grands nombres (plusieurs milliers de
chires).
Question 1-a
On parcourt simultanement A et C en
quil appara^t dans A.
267
de A alors il existe une suite dindices 0 6 i0 < i1 < . .. < iq1 < n tels que
ck = aik pour tout k. Donc, si c0 6= a0 , alors i0 > 1 et C est une sous-sequence
de (a1 , . .., an1). Lorsque c0 = a0 on a (c1 , .. ., cq1) = (ai1 , . . ., aiq1 ) qui est
une sous-sequence de (a1 , . .., an1) car i1 > 1.
Reciproquement, si c0 = a0 et si (c1 , .. ., cq1) est une sous-sequence de
(a1 , . .., an1) alors il existe des indices 1 6 i1 < . .. < iq1 < n tels que ck = aik
pour k > 1, et cette relation a encore lieu pour k = 0 en posant i0 = 0, donc
C est une sous-sequence de A. Enn, si c0 6= a0 et C est une sous-sequence de
(a1 , . .., an1) alors C est evidement une sous-sequence de A.
Ceci prouve que, si lappel sous_sequence a c termine, alors il renvoie le bon
resultat. Et il y a terminaison car la longueur de largument a diminue dune unite
a chaque appel recursif.
Question 1-b
On reprend lalgorithme precedent en accumulant les indices des elements de A
non apparies a ceux de C. La construction de la liste des indices nest pas terminee
lorsque C = () car il faut constituer la liste des indices des elements restant dans A.
let rec indices_`
a_supprimer(a,c,i) =
if a = [] then []
else if (c = []) or ((hd a) <> (hd c))
then i :: (indices_`
a_supprimer(tl a, c, i+1))
else indices_`
a_supprimer(tl a, tl c, i+1)
;;
(* utilisation *)
indices_`
a_supprimer(a,c,0);;
Question 2-a
Si ai1 = bj1 : si C = (c0 , .. ., cq1) est une plsc a Ai1 et Bj1 alors la liste
C0 = (c0 , .. ., cq1, ai1) est une sous-sequence commune a Ai et Bj . Ceci prouve
que `i,j > 1 + `i1,j1. Si C = (c0 , . .., cq1) est une plsc a Ai et Bj avec q > 2
alors C0 = (c0 , .. ., cq2) est une sous-sequence commune a Ai1 et Bj1 , quelle
que soit la valeur de cq1. Ceci prouve que `i1,j1 > `i,j 1 dans le cas `i,j > 2
et linegalite est egalement vraie si `i,j = 1.
Si ai1 6= bj1 : toute plsc a Ai1 et Bj est une sous-sequence commune a Ai
et Bj donc `i,j > `i1,j. De m^eme, `i,j > `i,j1 et donc `i,j > max(`i,j1, `i1,j).
Inversement, si C = (c0 , .. ., cq1) est une plsc a Ai et Bj , alors cq1 6= ai1 ou
cq1 6= bj1 donc C est une sous-sequence commune a Ai1 et Bj ou a Ai et Bj1.
Dans le premier cas on obtient : `i,j 6 `i1,j et dans le second cas : `i,j 6 `i,j1
do
u, dans tous les cas : `i,j 6 max(`i,j1, `i1,j).
Question 2-b
On choisit ici de representer A et B par des vecteurs pour acceder en temps
constant a ai1 et bj1 :
268
269
Question 2-c
` = l.(n).(p) est la longueur dune plsc a A et B. Si an1 = bp1 alors dapres
2a il existe une plsc a A et B obtenue en placant an1 au bout dune plsc a
An1 et Bp1 . Si an1 6= bp1 , alors on cherche une plsc a An1 et Bp ou a
An et Bp1 suivant que l.(n 1).(p) > l.(n).(p 1) ou non. On traite ici le cas
dune representation de A et B par des vecteurs :
let plsc(a,b,l) =
let n = vect_length(a) and p = vect_length(b) in
let q = l.(n).(p) in
let c = make_vect q a.(0) in
let i = ref(n) and j = ref(p) and k = ref(q) in
while !k > 0 do
if a.(!i-1) = b.(!j-1)
then begin
c.(!k-1) <- a.(!i-1);
i := !i - 1;
j := !j - 1;
k := !k - 1
end
else if l.(!i-1).(!j) > l.(!i).(!j-1)
then i := !i-1
else j := !j-1
done;
c
;;
Question 3-a
On cree deux vecteurs booleens, EA et EB , indexes par les elements de E (convertis
en nombres entiers au besoin) tels que :
{ EA .(x) = true si est seulement si x appara^t dans A ;
{ EB .(x) = true si est seulement si x appara^t dans B.
Ensuite on parcourt A en extrayant les elements x tels que EB .(x) vaut true et on
parcourt B en extrayant les elements x tels que EA .(x) vaut true. Ceci donne les
listes A0 et B0 .
(* On suppose les e
l
ements de E sont num
erot
es de 0 a
` r-1 *)
let cr
ee_tableau(a) =
let e_a = make_vect r false in
for i = 0 to vect_length(a) - 1 do
e_a.(num
ero(a.(i))) <- true
done;
e_a
;;
270
let extrait(a,e_b) =
let a = make_vect (vect_length a) a.(0) in
let k = ref 0 in
for i = 0 to vect_length(a) - 1 do
if e_b.(num
ero(a.(i))) then begin
a.(!k) <- a.(i);
k := !k + 1
end
done;
sub_vect a !k
;;
Question 3-b
On passe en revue les listes At et Bt comme pour une fusion, en notant les indices
des elements communs a A et B. On constitue alors A0 et B0 a partir de ces notes.
let intersection(a,b,at,bt) =
let
let
and
let
271
let extrait(a,dans_b) =
let a = make_vect (vect_length a) a.(0) in
let k = ref 0 in
for i = 0 to vect_length(a) - 1 do
if dans_b.(i) then begin
a.(!k) <- a.(i);
k := !k + 1
end
done;
sub_vect a !k
;;
Question 4
Premier cas : soit r le cardinal de E. La creation de e_a se fait en O(r) operations,
le remplissage en O(n) operations et lextraction de a a partir de a et e_b en O(n)
operations. La complexite du pre-traitement est donc O(n + p + r).
Second cas : le calcul de at a partir de a se fait en O(n ln(n)) operations si lon
emploie un algorithme de tri par fusion (le quicksort a aussi cette complexite, mais
en moyenne seulement) ; le calcul des vecteurs dans_a et dans_b a la complexite
dune fusion : O(n + p) et lextraction de a a partir de a et dans_b se fait en O(n)
operations. La complexite du pre-traitement est donc O(n ln(n) + p ln(p)).
En supposant n = p et r petit devant n dans 3a, on a donc une complexite de
pre-traitement O(n) ou O(n ln(n)) ce qui est negligeable devant la complexite de
calcul de la plsc : O(n2 ). On peut donc toujours proceder au pre-traitement, ce
nest asymptotiquement pas penalisant. Cependant, lutilite de ce pre-traitement
est discutable : dans le cas 3a, si E est petit et A, B sont grandes, alors il est probable que presque tous les elements de E gurent au moins une fois dans chacune
des listes, et le pre-traitement ne diminue pas notablement les longueurs des listes
a traiter. Dans le cas 3b, si A et B sont aleatoires, independantes, et de longueur
petite devant card(E) alors elles sont probablement (( presque disjointes )) et le
pre-traitement peut ^etre ecace. Par contre, si A et B ne sont pas independantes
(en particulier sil sagit de versions successives dun chier), il est probable que
le pre-traitement ne permettra de retirer que quelques elements seulement.
Enn, si n et p sont (( petits )), le temps de pre-traitement ne peut plus ^etre
considere comme negligeable. . . En conclusion, je deconseille ce pre-traitement.
Compl
ement
Le systeme Unix possede une commande diff listant les dierences entre
deux chiers texte suivant un algorithme inspire de la recherche dune plsc : la
distance entre deux chiers A et B consideres comme des listes de lignes est le
nombre delements de A et de B ne faisant pas partie dune plsc a A et B. Elle
est notee d(A, B). On determine cette distance en comparant A et B par les deux
bouts : on progresse alternativement dune unite de distance a partir des debuts
de A et B, puis dune unite a partir des ns de A et B, jusqu
a un point milieu,
cest-
a-dire un couple (i, j) tel que d(Ai , Bj) = bd(A, B)/2c. Le nombre de couples
272
Arbres de priorit
e
equilibr
es
Question 1
Par recurrence sur H(a).
Question 2
let rec insertion(a,e) = match a with
| B_vide
-> B_noeud(e,B_vide,B_vide)
| B_noeud(r,g,d) -> if e >= r then B_noeud(e, insertion(d,r), g)
else B_noeud(r, insertion(d,e), g)
;;
Arbres de priorit
e
equilibr
es
273
Question 3
let rec transforme(a1) = match a1 with
| B_vide -> a1
| B_noeud(e,B_vide,B_vide) -> a1
| B_noeud(e,g,d) ->
(* compare les racines de g et d si elles existent *)
let g_plus_grand_que_d =
match (g,d) with
| (B_noeud(x,_,_), B_noeud(y,_,_)) -> x >= y
| _ -> true (* une des branches est vide, cest donc d *)
in
(* compare e au plus grand fils *)
if g_plus_grand_que_d then match g with
| B_vide -> a1
| B_noeud(e,g,d) ->
if e >= e then a1
else B_noeud(e, transforme(B_noeud(e,g,d)), d)
else match d with
| B_vide -> a1
| B_noeud(e,g,d) ->
if e >= e then a1
else B_noeud(e, g, transforme(B_noeud(e,g,d)))
;;
match a with
-> failwith "arbre vide"
-> (B_vide,r)
-> let (g,e) = retire_gauche(g) in
(B_noeud(r,d,g),e)
;;
let extraction(a) = let (a,e) = retire_gauche(a) in
match a with
| B_vide
-> (a,e)
| B_noeud(r,g,d) -> (transforme(B_noeud(e,g,d)), r)
;;
Complexite : O(H(a)).
274
Question 5
Le temps de constitution de lAPE verie la relation de recurrence :
Tn = Tn1 + O(ln(n)).
Donc Tn = O(ln 1 + ln 2 + .. . + ln n) = O(n ln n). Le temps dextraction de
tous les noeuds de lAPE verie la m^eme relation, donc est aussi O(n ln n) et le
temps de constitution de la liste nale, non compris les extractions dans lAPE,
est O(n) car on eectue des insertions en t^ete de liste. Le temps total du tri est
donc O(n ln n).
275
Question 3-a
Algorithme :
{ une constante c est compil
ee en empile_c c ;
{ une variable v est compil
ee en empile_v v ;
{ pour compiler op1 (g), compiler g et ins
erer unaire op1 en queue du code
obtenu ;
{ pour compiler g op2 h, compiler s
epar
ement g et h, soient g et h les
codes obtenus, puis comparer N(g) et N(h).
Si N(g) < N(h) alors retourner le code : h ; g ; binaire_inv op2 ,
sinon retourner le code : g ; h ; binaire op2 .
Le calcul de N(g) et N(h) dans le dernier cas peut ^etre eectue par parcours
des formules g et h en appliquant les relations obtenues a la question precedente.
Le programme ci-dessous evite le double parcours en retournant a la fois le code
compile et le nombre de niveaux de pile utilises par ce code.
type a
| Const
| Var
| Op1
| Op2
;;
formule =
of a
of string
of string * (a formule)
of string * (a formule) * (a formule)
type a instruction =
| Empile_c
of a
| Empile_v
of string
| Unaire
of string
| Binaire
of string
| Binaire_inv of string
;;
let rec compile(f) = (* retourne le code de f et N(f) *)
match f with
| Const(c)
-> ([Empile_c c], 1)
| Var(v)
-> ([Empile_v v], 1)
| Op1(op1,g) -> let (code,n) = compile(g) in (code @ [Unaire op1], n)
| Op2(op2,g,h) ->
let (codeg,ng) = compile(g)
and (codeh,nh) = compile(h) in
if
ng > nh then (codeg @ codeh @ [Binaire op2],
ng)
else if ng < nh then (codeh @ codeg @ [Binaire_inv op2], nh)
else
(codeg @ codeh @ [Binaire op2],
1+ng)
;;
276
Question 3-b
On peut transformer la formule a compiler en un arbre dinstructions par un
premier parcours en profondeur, chaque nffud etant remplace par linstruction
correspondante, puis mettre ces instructions en liste par un deuxieme parcours en
profondeur en inserant les instructions en t^ete dune liste initialement vide.
Question 4
Soit k(n) le nombre minimal de nffuds dune formule non calculable avec n niveaux
de pile. Pour n > 2, une telle formule est de la forme f = g op2 h avec N(g) 6 n,
N(h) 6 n (sinon f nest pas minimale) et donc N(g) > n 1, N(h) > n 1 (sinon
N(f) 6 n). On en deduit k(n) = 2k(n 1) + 1 et k(1) = 3 do
u k(n) = 2n+1 1.
En particulier, k(8) = 511.
in
& (!i + !j < vect_length(t)) do
:= 0 end
!i else failwith "non trouv
e"
277
Question 1-c
Pour k, i N on note N(k, i) le nombre de mots m de longueur ` pour lesquels on
eectue k comparaisons de lettres dans () avant de conclure a la presence de m
dans t ou de passer a la position suivante i + 1. Alors :
(t, `) =
|t|1 `
1 X X
kN(k, i).
|A|` i=0 k=0
On a :
N(k, i) = 1
N(k, i) = (|A| 1)|A|`k
N(k, i) = |A|`k
N(k, i) = 0
Do
u:
(t, `) 6
|t|1 `1
X X
i=0
k=0
si k = `,
si k < ` et i + k < |t|,
si k < ` et i + k = |t|,
sinon.
6 |t|(|A| 1)
X
k|A|k
k=0
|A|
|t|.
|A| 1
Question 1-d
Par un calcul similaire on obtient
~ (`, m) 6
|A|
|m|.
|A| 1
Question 2-a
automate non deterministe :
0
a,b,c
apres determinisation :
c
b,c
0
01
a
b,c
012
a
b,c
b
b,c
a
03
014
b
a
a
b,c
a
0125
06
278
Question 2-b
On convient de representer Am par une matrice de transition a telle que a.(i).(j)
donne le numero de letat succedant a letat i lorsquon lit la lettre j, et par un
vecteur de booleens f tel que f.(i) = true si et seulement si letat i est un etat nal.
Letat initial de Am est par convention letat 0 (i, j sont des entiers, lautomate
est suppose deterministe complet).
let position a f m texte =
let e
tat = ref 0
(* num
ero de l
etat courant *)
and i
= ref 0 in (* indice dans le texte
*)
while not(f.(!
etat)) & (!i < vect_length(texte)) do
e
tat := a.(!
etat).(texte.(!i));
i := !i + 1
done;
if f.(!
etat) then !i - vect_length(m) - 1 else failwith "non trouv
e"
;;
279
Exemple :
m
a
a
b
a
a
c
u
0
1
2
3
4
5
6
v
0
1
0
1
2
0
a
1
2
2
4
5
2
1
b c
0 0
0 0
3 0
0 0
0 0
3 6
0 0
Question 2-f
Comme tout automate deterministe reconnaissant Lm a au moins autant detats
que Lm a de residuels, il sut de prouver que Lm a au moins |m| + 1 residuels
distincts. Soient u et uv deux prexes de m (m = uvw) avec v 6= . Alors le
langage residuel de uv contient w ce qui nest pas le cas du langage residuel de u.
Donc les langages residuels des prexes de m sont deux a deux distincts et il y en
a |m| + 1.
Question 3-b
Comme k p < k, on a p > 1 donc le mot m est decale vers la n de t. Il
faut seulement justier que si p > 1 on ne risque pas de manquer des positions
dapparition de m dans t : si on decale m de q positions avec q < p alors la lettre
akq est mise en correspondance avec bi+k donc il y a non concordance.
La complexite dans le pire des cas est la m^eme quau 1-a car on peut seulement armer que k > 0 et p > 1 donc on peut avoir a comparer chaque lettre de
m avec chaque lettre de t (sauf pour les dernieres lettres de t).
Question 3-c
De facon a eviter de recalculer lentier p a chaque comparaison negative, on precalcule la fonction de decalage dans une matrice mat indexee par les positions dans m
et les lettres de A :
(* p est la taille de lalphabet, retourne *)
(* la matrice de d
ecalage associ
ee au mot m *)
let matrice p m =
let n
= vect_length(m)
in
let mat = make_matrix n p 1 in
for i = 1 to n-1 do
for a = 0 to p-1 do mat.(i).(a) <- mat.(i-1).(a) + 1 done;
mat.(i).(m.(i-1)) <- 1
done;
mat
;;
280
let position mat m texte =
let n
= vect_length(m)
in
let imax = vect_length(texte) - n in
let i = ref 0 and j = ref(n-1)
in
Question 3-d
Oui. Au lieu de chercher la derniere occurrence de bi+k dans a1 .. .ak1 , on
peut chercher la derniere occurrence du mot bi+k ak+1 .. .a|m|1 dans a1 . . .ak1
et decaler m en consequence. Ceci garantit que chaque lettre de t ne sera examinee
quune fois dans le pire des cas, et 1/|m| fois en general. La construction de la
table de decalage est cependant plus compliquee.
Solutions des
travaux pratiques
282
Chemins dans Z2
2. D
etection et
elimination des boucles
(* d
etecte les points multiples (algorithme en O(n^2)) *)
let rec multiples points = match points with
| []
-> false
| p::suite -> (mem p suite) or (multiples suite)
;;
(* liste dassociation (point, pr
ed
ecesseur) *)
let rec pr
ed
ecesseurs points = match points with
| u::v::suite -> (v,u) :: pr
ed
ecesseurs (v::suite)
| _
-> []
;;
(* e
limine les boucles *)
let sans_boucle points =
let z0
= hd(points)
in
let pred = pr
ed
ecesseurs(points) in
let l
= ref([hd(rev points)]) in
while hd(!l) <> z0 do l := (assoc (hd !l) pred) :: !l done;
!l
;;
3. Remplissage
(* ordonn
ees extr^
emes *)
let rec extr^
emes points = match points with
| []
-> failwith "liste vide"
| [(x,y)] -> (y,y)
| (x,y)::suite -> let (y1,y2) = extr^
emes(suite)
in (min y1 y, max y2 y)
;;
(* intersections avec une horizontale *)
let rec intersecte y0 points = match points with
| (x1,y1)::(x2,y2)::suite ->
if (min y1 y2 = y0) & (max y1 y2 > y0)
then x1 :: intersecte y0 ((x2,y2)::suite)
else intersecte y0 ((x2,y2)::suite)
| _ -> []
;;
(* remplissage *)
let remplit points =
let (ymin,ymax) = extr^
emes(points) in
for y = ymin to ymax-1 do
let l = ref(sort__sort (prefix <=) (intersecte y points)) in
while !l <> [] do match !l with
| x1::x2::suite -> noircit (x1,y) (x2,y+1); l := suite
| _ -> failwith "cas impossible"
done
done
;;
1. Impl
ementation des files dattente
(* cr
eation, inspection *)
let nouv_file() = {avant = []; arri`
ere = []};;
let est_vide f = (f.avant = []) & (f.arri`
ere = []);;
let longueur f = list_length(f.avant) + list_length(f.arri`
ere);;
283
284
2. La suite de Hamming
a)
(* initialisation *)
let h2 = nouv_file();; ajoute h2 2;;
let h3 = nouv_file();; ajoute h3 3;;
let h5 = nouv_file();; ajoute h5 5;;
(* extrait lentier de Hamming suivant
let suivant() =
let x2 = premier(h2)
and x3 = premier(h3)
and x5 = premier(h5) in
let x = min (min x2 x3) x5 in
if x = x2 then (let _ = retire h2 in
if x = x3 then (let _ = retire h3 in
if x = x5 then (let _ = retire h5 in
ajoute h2 (2*x);
ajoute h3 (3*x);
ajoute h5 (5*x);
x
;;
b)
*)
());
());
());
(* extraction optimis
ee *)
let suivant() =
let x2 = premier(h2)
and x3 = premier(h3)
and x5 = premier(h5) in
let x = min (min x2 x3) x5 in
if x = x2 then (let _ = retire h2 in ());
if x = x3 then (let _ = retire h3 in ());
if x = x5 then (let _ = retire h5 in ());
ajoute h5 (5*x);
if x mod 5 > 0 then begin
ajoute h3 (3*x);
if x mod 3 > 0 then ajoute h2 (2*x)
end;
x
;;
285
Etude
de 5Hn+1 : 5Hn+1 est insere dans h5 et cest un nouvel element car
avant cette insertion h2, h3 et h5 ne contenaient que des nombres inferieurs
ou egaux a 5Hn.
Etude
de 3Hn+1 : si lentier Hn+1 est divisible par 5, Hn+1 = 5Hp , alors
3Hn+1 = 5(3Hp) = 5Hq et q < n + 1 car Hq = 35 Hn+1 < Hn+1 donc 3Hn+1
est present dans une et une seule des les h2, h3 , h5 avant lextraction de
Hn+1 et il nest pas reinsere lors de cette extraction.
Si Hn+1 nest pas divisible par 5 alors 3Hn+1 nappartient a aucune des
les h2 , h3, h5 avant linsertion eectuee lors de lextraction de Hn+1. En
eet, on ne peut avoir 3Hn+1 = 5Hk puisque Hn+1 nest pas divisible par 5
et on na pas non plus 3Hn+1 = 3Hk ou 3Hn+1 = 2Hk avec k 6 n car ces
relations impliquent Hk > Hn+1 > Hn. Donc 3Hn+1 est bien present dans
une et une seule des les h2, h3, h5 a lissue du (n + 1)-eme appel a suivant.
Etude
de 2Hn+1 : en distinguant les cas (( Hn+1 divisible par 5 )), (( Hn+1
non divisible par 5 mais divisible par 3 )) et (( Hn+1 divisible ni par 5 ni
par 3 )), on demontre de m^eme que 2Hn+1 est present dans une et une seule
des les h2 , h3 , h5 a lissue du (n + 1)-eme appel a suivant. Ceci acheve la
demonstration de validite de suivant.
c)
(* initialisation *)
let h2 = nouv_file();;
let h3 = nouv_file();;
let h5 = nouv_file();;
ajoute h2 (1,0,0);;
ajoute h3 (0,1,0);;
ajoute h5 (0,0,1);;
286
287
Recherche de contradictions
par la m
ethode des consensus
3. Programmation de l
etape 1
(* compare deux clauses *)
let implique (p1,n1) (p2,n2) =
(subtract p1 p2 = []) & (subtract n1 n2 = []);;
(* teste si une
let rec present
| []
->
| x::suite ->
e
liminant *)
*)
with
(* simplifie un syst`
eme *)
let simplifie s =
let rec simpl s1 s2 = match s2 with
| []
-> s1
| c::suite -> simpl (ajoute c s1) suite
in simpl [] s
;;
288
4. Programmation des
etapes 2 et 3
(* ajoute au syst`
eme le consensus e
ventuel de deux clauses *)
let ajoute_cons (p1,n1) (p2,n2) syst =
match (intersect p1 n2, intersect p2 n1) with
| ([x],[]) ->
ajoute (union (except x p1) p2, union n1 (except x n2)) syst
| ([],[x]) ->
ajoute (union p1 (except x p2), union (except x n1) n2) syst
| _ -> syst
;;
(* ajoute a
` l tous les consensus entre c et une clause du syst`
eme *)
let rec ajoute_consensus c syst l = match syst with
| [] -> l
| c1::suite -> ajoute_consensus c suite (ajoute_cons c c1 l)
;;
(* cl^
ot un syst`
eme par consensus *)
let rec cloture s =
let rec consensus s1 s2 = match s1 with
| [] -> s2
| c::suite -> consensus suite (ajoute_consensus c s s2)
in
let t = simplifie(consensus s s) in
if (subtract s t = []) & (subtract t s = []) then s else cloture t
;;
6. Affichage des
etapes dune contradiction
(* "ajoute", "simplifie", "ajoute_consensus", "cloture" sont inchang
ees *)
let
and
and
and
;;
prefix
prefix
prefix
prefix
=>
=>~
~=>
~=>~
a
a
a
a
b
b
b
b
=
=
=
=
([b], [a],
([],
[a;b],
([a;b],[],
([a], [b],
H)
H)
H)
H)
(*
(*
(*
(*
a => b
a => non b
non a => b
non a => non b
*)
*)
*)
*)
let string_of_clause(p,n,_) =
(if n = [] then "" else (concat "." n)^" => ") ^
(if p = [] then "Faux" else concat "+" p)
;;
let print_clause(c) = format__print_string(string_of_clause c);;
install_printer "print_clause";;
(* compare deux clauses *)
let implique (p1,n1,_) (p2,n2,_) =
(subtract p1 p2 = []) & (subtract n1 n2 = []);;
Mod
elisation dun tableur
289
(* ajoute au syst`
eme le consensus e
ventuel de deux clauses *)
let ajoute_cons (p1,n1,_ as c1) (p2,n2,_ as c2) syst =
match (intersect p1 n2, intersect p2 n1) with
| ([x],[]) ->
ajoute (union (except x p1) p2, union n1 (except x n2), D(c1,c2)) syst
| ([],[x]) ->
ajoute (union p1 (except x p2), union (except x n1) n2, D(c1,c2)) syst
| _ -> syst
;;
(* explique les e
tapes dune d
eduction *)
let explique clause =
let vus = ref [] in
let rec expl (p,n,r as c) =
if not(mem c !vus) then match r with
| H -> print_string "Jai lhypoth`
ese : ";
print_string (string_of_clause c);
print_newline();
vus := c :: !vus
| D((p1,n1,r1 as c1),(p2,n2,r2 as c2)) ->
if r1 = H then (expl c2; expl c1) else (expl c1; expl c2);
print_string "De "; print_string(string_of_clause c1);
print_string " et "; print_string(string_of_clause c2);
print_string " je d
eduis : "; print_string(string_of_clause c);
print_newline();
vus := c :: !vus
in expl clause
;;
Mod
elisation dun tableur
1. Tri topologique
let d
ependances(t) =
for i = 0 to t.n-1 do for j = 0 to t.p-1 do
t.suc.(i).(j) <- []
done done;
for i = 0 to t.n-1 do for j = 0 to t.p-1 do match t.f.(i).(j) with
| Rien
-> t.dep.(i).(j) <- 0
| Somme(liste) ->
t.dep.(i).(j) <- list_length(liste);
do_list (fun (k,l) -> t.suc.(k).(l) <- (i,j)::t.suc.(k).(l)) liste
done done
;;
290
;;
let tri_topo(t) =
d
ependances(t);
t.lt <- [];
for i = 0 to t.n-1 do for j = 0 to t.p-1 do
if t.f.(i).(j) = Rien then place t (i,j)
done done;
t.lt <- rev(t.lt);
if list_length(t.lt) < t.n*t.p then failwith "tri impossible"
;;
2. Calcul du tableau
let calc t (i,j) = match t.f.(i).(j) with
| Rien -> ()
| Somme(liste) ->
t.v.(i).(j) <- 0;
do_list (fun (k,l) -> t.v.(i).(j) <- t.v.(i).(j) + t.v.(k).(l)) liste
;;
let calcule t = do_list (calc t) t.lt;;
3. Compl
ement
On ajoute dans la structure tableau une nouvelle matrice contenant pour chaque
cellule la liste des cellules qui en dependent, liste triee par ordre topologique.
Cette liste sobtient par fusion des listes des cellules dependant des successeurs de
la cellule consideree. On est ainsi ramene au probleme du calcul dun tableau en
ordre topologique inverse, il sut de conduire les calculs dans lordre donne par
rev(t.lt).
Analyse syntaxique
2. Analyse lexicale
(* d
ecoupe une chaine en lex`
emes *)
let lex`
emes s =
let i
= ref 0
(* indice pour s
*)
and res = ref []
(* liste des lex`
emes trouv
es *)
and l
= string_length s in
Analyse syntaxique
291
symboles *)
!res; i := !i+1
!res; i := !i+1
!res; i := !i+1
!res; i := !i+1
i := !i+1
i := !i+1
i := !i+1
(* reconna^
t - et -> *)
| - -> if (!i+1 < l) & (s.[!i+1] = >)
then begin res := Fl`
eche :: !res;
i := !i+2 end
else begin res := Opr(2,-) :: !res; i := !i+1 end
(* ignore les espaces *)
| | \t | \n -> i := !i+1
(* refuse les autres caract`
eres *)
| _ -> failwith ("caract`
ere ill
egal : " ^ (make_string 1 s.[!i]))
done;
rev !res
;;
292
3. Analyse syntaxique
(* empile un lex`
eme ou une expression et *)
(* simplifie la pile autant que possible *)
let rec empile e pile =
(* priorit
e de e *)
let p = match e with
| L(In) | L(Then) | L(Else) | L(ParF) -> 0
| L(Opr(p,_)) -> p
| _
-> 5 (* > priorit
e maximum *)
in
(* conversion des nombres et identificateurs *)
let e = match e with
| L(Nombre x) -> E(Const x)
| L(Ident x) -> E(Var
x)
| _ -> e
in
match e, pile with
(* application de fonction *)
| (E x), (E f)::suite -> empile (E(Appl(f,x))) suite
(* parenth`
eses *)
| (L ParF), (E a)::(L ParO)::suite -> empile (E a) suite
(* op
eration prioritaire en instance *)
| _, (E b)::(L(Opr(q,o)))::(E a)::suite
when p <= q -> empile e (empile (E(Bin(a,o,b))) suite)
(* d
efinition de fonction *)
| _, (E a)::(L Fl`
eche)::(E(Var x))::(L Fun)::suite
when p = 0 -> empile e (empile (E(Fct(x,a))) suite)
(* liaison locale *)
| _, (E b)::(L In)::(E a)::(L Egal)::(E(Var x))::(L Let)::suite
when p = 0 -> empile e (empile (E(Letin(x,a,b))) suite)
(* test *)
| _, (E c)::(L Else)::(E b)::(L Then)::(E a)::(L If)::suite
when p = 0 -> empile e (empile (E(Test(a,b,c))) suite)
(* pas de simplification possible *)
| _, _ -> e::pile
;;
Analyse syntaxique
293
4. Evaluation
(* e
valuation *)
let rec valeur env expr = match expr with
| Const c -> Int c
| Var
x -> assoc x env
| Fct(x,e) -> Cloture(env,expr)
| Bin(e1,op,e2) ->
let v1 = match valeur env e1 with
| Int x -> x | _ -> failwith "valeur non enti`
ere" in
let v2 = match valeur env e2 with
| Int x -> x | _ -> failwith "valeur non enti`
ere" in
let v = match op with
| + -> v1 + v2
| - -> v1 - v2
| * -> v1 * v2
| / -> v1 / v2
| % -> v1 mod v2
| _
-> failwith "op
erateur inconnu"
in Int v
| Appl(f,e) ->
let env1,x,code = match valeur env f with
| Cloture(env1,Fct(x,code)) -> env1,x,code
| _ -> failwith "valeur non fontionnelle"
in valeur ((x,valeur env e) :: env1) code
| Test(e1,e2,e3) ->
let v = match valeur env e1 with
| Int x -> x | _ -> failwith "valeur non enti`
ere"
in valeur env (if v = 0 then e2 else e3)
| Letin(x,e1,e2) ->
(* attention : si e1 s
evalue en une fonction, il faut
*)
(* introduire une liaison pour x dans la cloture de cette *)
(* fonction pour le cas o`
u la fonction serait r
ecursive *)
let v = match valeur env e1 with
| Int(c)
-> Int(c)
| Cloture(env2,code) -> let rec y = Cloture((x,y)::env2,code) in y
in valeur ((x, v) :: env) e2
;;
Annexes
Bibliographie
295
Bibliographie
[Aho]
Aho, Ullman
Concepts fondamentaux de linformatique
Dunod, 1993
[Froid]
[Knuth] Knuth
The art of computer programming
Addison-Wesley, 1973
[Leroy]
Leroy, Weis
Le langage Caml
InterEditions,
1993
[Mehl]
Mehlhorn
Data Structures and Algorithms
Springer-Verlag, 1984
[Sedg]
Sedgewick
Algorithmes en langage C
Intereditions, 1991
[Stern]
Stern
Fondements math
ematiques de linformatique
Ediscience, 1994
296
Annexes
Aide m
emoire de caml
D
eclarations et instructions
commentaires . . . . . . . . . . . . . . . . . . . .
denition dune valeur . . . . . . . . . . . .
recursive . . . . . . . . . . . . . . .
locale . . . . . . . . . . . . . . . . . . .
denitions paralleles . . . . . . . . . . . . . .
successives . . . . . . . . . . . .
variable modiable . . . . . . . . . . . . . . .
valeur dune reference . . . . . . . . . . . .
modication dune reference . . . . . .
fonction sans argument . . . . . . . . . . .
fonction a un argument . . . . . . . . . . .
fonction a n arguments . . . . . . . . . . .
expression conditionnelle . . . . . . . . .
choix multiple . . . . . . . . . . . . . . . . . . . .
ne rien faire . . . . . . . . . . . . . . . . . . . . . .
calculs en sequence . . . . . . . . . . . . . . .
boucle croissante . . . . . . . . . . . . . . . . .
boucle decroissante . . . . . . . . . . . . . . .
boucle conditionnelle . . . . . . . . . . . . .
declencher une erreur . . . . . . . . . . . . .
Expressions bool
eennes
vrai, faux . . . . . . . . . . . . . . . . . . . . . . . . .
et, ou, non . . . . . . . . . . . . . . . . . . . . . . .
comparaison . . . . . . . . . . . . . . . . . . . . . .
booleen 7 cha^ne . . . . . . . . . . . . . .
cha^ne 7 booleen . . . . . . . . . . . . .
Expressions enti`
eres
operations arithmetiques . . . . . . . . . .
modulo . . . . . . . . . . . . . . . . . . . . . . . . . . .
(* ... *)
let v = expression
let rec v = ...
let v = ... in expression
expression where v = ...
let v = ... and w = ...
let v = ... in let w = ...
let v = ref(expression)
!v
v := ...
let f() = ...
let f x = ...
let f x1 .. xn = ...
if ... then expr-vrai else expr-faux
match valeur with
| motif-1 -> expression-1
| motif-2 -> expression-2
...
| motif-n -> expression-n
-> expression-par-d
efaut
|
()
begin ... end
for i = d
ebut to
fin do ... done
for i = d
ebut downto fin do ... done
while condition do ... done
failwith "message"
true false
& or not
< <= = <> >=
string of bool
bool of string
+ mod
>
Aide m
emoire de caml
valeur absolue . . . . . . . . . . . . . . . . . . . .
entier precedent, suivant . . . . . . . . . .
minimum et maximum . . . . . . . . . . .
operations bit a bit . . . . . . . . . . . . . . .
decalage de bits . . . . . . . . . . . . . . . . . .
entier 7 cha^ne . . . . . . . . . . . . . . . .
cha^ne 7 entier . . . . . . . . . . . . . . . .
entier aleatoire entre 0 et n 1 . . .
Expressions r
eelles
operations arithmetiques . . . . . . . . . .
puissance . . . . . . . . . . . . . . . . . . . . . . . . .
minimum et maximum . . . . . . . . . . .
fonctions mathematiques . . . . . . . . .
reel
7 cha^ne . . . . . . . . . . . . . . . .
reel
7 entier . . . . . . . . . . . . . . . .
cha^ne 7 reel . . . . . . . . . . . . . . . . . .
entier 7 reel . . . . . . . . . . . . . . . . . .
reel aleatoire entre 0 et a . . . . . . . . .
Expressions rationnelles
utiliser les rationnels . . . . . . . . . . . . .
operations arithmetiques . . . . . . . . . .
comparaison . . . . . . . . . . . . . . . . . . . . . .
minimum et maximum . . . . . . . . . . .
valeur absolue . . . . . . . . . . . . . . . . . . . .
numerateur, denominateur . . . . . . . .
simplier une fraction . . . . . . . . . . . .
simplication automatique . . . . . . . .
partie entiere . . . . . . . . . . . . . . . . . . . . .
rationnel 7 cha^ne . . . . . . . . . . . . .
rationnel 7 entier . . . . . . . . . . . . . .
rationnel 7 reel . . . . . . . . . . . . . . . .
cha^ne
7 rationnel . . . . . . . . . . .
entier
7 rationnel . . . . . . . . . . .
reel
7 rationnel . . . . . . . . . . .
Listes
liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
liste vide . . . . . . . . . . . . . . . . . . . . . . . . .
t^ete et queue . . . . . . . . . . . . . . . . . . . . .
longueur dune liste . . . . . . . . . . . . . .
concatenation . . . . . . . . . . . . . . . . . . . .
297
abs
pred succ
min a b, max a b
land lor lxor lnot
lsl lsr asr
string of int
int of string
random int(n)
+. -. *. /.
** ou **.
min a b, max a b
abs float exp log sqrt sin cos tan
sinh cosh tanh asin acos atan atan2
string of float
int of float
float of string
float of int
random float(a)
#open "num"
+/ -/ */ // **/
minus num quo num mod num square num
</ <=/ =/ <>/ >=/ >/
min num a b, max num a b
abs num
numerator num denominator num
normalize num
arith status set normalize ratio true
floor num round num ceiling num
string of num
int of num
float of num
num of string
num of int
num of float
[x; y; z; ... ]
[ ]
hd tl, x :: suite
list length
@
298
image miroir . . . . . . . . . . . . . . . . . . . . .
appliquer une fonction . . . . . . . . . . . .
iterer un traitement . . . . . . . . . . . . . .
test dappartenance . . . . . . . . . . . . . . .
test de presence . . . . . . . . . . . . . . . . . .
recherche dun element . . . . . . . . . . .
operations ensemblistes . . . . . . . . . . .
tri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
association . . . . . . . . . . . . . . . . . . . . . . .
iterer une operation . . . . . . . . . . . . . .
Vecteurs
vecteur . . . . . . . . . . . . . . . . . . . . . . . . . . .
vecteur vide . . . . . . . . . . . . . . . . . . . . . .
i-eme element . . . . . . . . . . . . . . . . . . . .
modication . . . . . . . . . . . . . . . . . . . . . .
longueur dun vecteur . . . . . . . . . . . .
creation . . . . . . . . . . . . . . . . . . . . . . . . . .
creation dune matrice . . . . . . . . . . . .
extraction . . . . . . . . . . . . . . . . . . . . . . . .
concatenation . . . . . . . . . . . . . . . . . . . .
copie . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
appliquer une fonction . . . . . . . . . . . .
iterer un traitement . . . . . . . . . . . . . .
vecteur 7 liste . . . . . . . . . . . . . . . . .
liste
7 vecteur . . . . . . . . . . . . . .
Annexes
rev
map fonction liste
do list traitement liste
mem e
l
ement liste
exists pr
edicat liste
for all pr
edicat liste
index e
l
ement liste
union intersect subtract
sort sort ordre liste
assoc b [(a,x); (b,y); (c,z); ... ] = y
it list op a [x; y; z]
= op (op (op a x) y) z
list it op [x; y; z] a
= op x (op y (op z a))
[|x; y; z; ... |]
[| |]
v.(i)
v.(i) <- qqch
vect length
make vect longueur valeur
make matrix n p valeur
sub vect vecteur d
ebut longueur
concat vect
copy vect
map vect fonction vecteur
do vect traitement vecteur
list of vect
vect of list
Chanes de caract`
eres
caractere . . . . . . . . . . . . . . . . . . . . . . . . .
cha^ne de caracteres . . . . . . . . . . . . . .
i-eme caractere . . . . . . . . . . . . . . . . . . .
modication . . . . . . . . . . . . . . . . . . . . . .
longueur dune cha^ne . . . . . . . . . . . .
creation . . . . . . . . . . . . . . . . . . . . . . . . . .
caractere 7 cha^ne . . . . . . . . . . . . .
extraction . . . . . . . . . . . . . . . . . . . . . . . .
concatenation . . . . . . . . . . . . . . . . . . . .
x
"xyz... "
cha^
ne.[i]
cha^
ne.[i] <- qqch
string length
make string longueur caract`
ere
make string 1 caract`
ere
sub string cha^
ne d
ebut longueur
ch1 ^ ch2, concat [ch1; ch2; ch3; ... ]
Graphisme
utiliser le graphisme . . . . . . . . . . . . . .
initialiser la fen^etre graphique . . . .
refermer la fen^etre . . . . . . . . . . . . . . . .
#open "graphics"
open graph ""
close graph()
Aide m
emoire de caml
eacer la fen^etre . . . . . . . . . . . . . . . . . .
position du crayon . . . . . . . . . . . . . . . .
changer la couleur du crayon . . . . .
couleurs . . . . . . . . . . . . . . . . . . . . . . . . . .
changer lepaisseur du crayon . . . . .
tracer un point . . . . . . . . . . . . . . . . . . .
deplacer, crayon leve . . . . . . . . . . . . .
crayon baisse . . . . . . . . . . .
tracer un cercle . . . . . . . . . . . . . . . . . . .
ecrire un texte . . . . . . . . . . . . . . . . . . . .
peindre un rectangle . . . . . . . . . . . . . .
un polygone . . . . . . . . . . . . . .
un disque . . . . . . . . . . . . . . . .
attendre un evenement . . . . . . . . . . .
Entr
ees-sorties au terminal
impression de valeurs . . . . . . . . . . . . .
changer de ligne . . . . . . . . . . . . . . . . . .
impression formattee . . . . . . . . . . . . .
lecture de valeurs . . . . . . . . . . . . . . . . .
Entr
ees-sorties dans un fichier
ouverture en lecture . . . . . . . . . . . . . .
en ecriture . . . . . . . . . . . . .
lecture . . . . . . . . . . . . . . . . . . . . . . . . . . .
ecriture . . . . . . . . . . . . . . . . . . . . . . . . . .
fermeture
........................
Commande de linterpr
eteur
tracer une fonction . . . . . . . . . . . . . . .
ne plus tracer . . . . . . . . . . . . . . . .
utiliser une fonction dimpression .
ne plus lutiliser . . . . . . . . . . . . . .
charger un chier source . . . . . . . . . .
charger un module compile . . . . . . . .
nom completement qualie . . . . . . .
utiliser les noms courts dun module
ne plus les utiliser . . . . . . . . . . . .
ajouter un repertoire de recherche
quitter linterpreteur . . . . . . . . . . . . .
299
clear graph()
current point()
set color couleur
black white red green blue yellow cyan
magenta, rgb r g b
set line width e
paisseur
plot x y
moveto x y
lineto x y
draw circle x y rayon
draw string "texte"
fill rect x y largeur hauteur
fill poly [| (x0,y0); (x1,y1); ... |]
fill circle x y rayon
read key()
wait next event [ev1; ev2; ... ]
trace "fonction"
untrace "fonction"
install printer "fonction"
remove printer "fonction"
load "nom", include "nom"
load object "nom"
module nom
#open "module"
#close "module"
directory "chemin"
quit()
300
Annexes
Index
+
::
@
de
bc
133
27,30
31
133
61
61
56,186
18
18
133
81
132
A
additionneur 1-bit 65,68,74
{ modulo 3 224
{ n-bits 65,74
Aitken 160
algorithme 9
{ recursif 14
algorithmique 10
alphabet 132
ambigute 58,59
analyse syntaxique 184
anc^etre 87
arbre
{ binaire 88,90
{ binaire de recherche 109
{ binaire parfait 91,104
{ construit aleatoirement 103,111
{ de decision 88,99,108,110
{ de priorite 163
{ denombrement 101,107
{ dynastique 88,105
{ equilibre en hauteur 100,107
{ equilibre en poids 107
{ general 87,92
{ hauteur 87,99
{ largeur 95
{ ordonne 88
{ representation ascendante 93
{ syntaxique 70
{ taille 87,99
ascendant 87
ascenseur 138,154
automate
{ complet 138
{ determinisation 146
{ deterministe 138
{
{
{
{
{
{
{
equivalent 140
ni 138
indexe par des expressions regulieres 149
produit 154
reconnaisseur 139
sequentiel 154
simulation 141
B
B noeud 90
B vide 90
bascule RS 64
branche dun arbre 88
{ droite, gauche, vide 90
C
Carroll 180
Catalan 102
C
esaro 81
champ 54
circuit
{ combinatoire 63
{ logique 63
{ sequentiel 63
CL 118
coecients du bin^
ome 15,21,89
combinaison lineaire 118
comparaison
{ dalgorithmes 76,85,86
{ relation 34
{ temps moyen 85
compilateur 131
compilation
{ dune expression 166
{ dune formule inxe 59
complexit
e
{ asymptotique 77
{ dans le pire des cas 77
{ en moyenne 77,108
{ equation de recurrence 79,82,84
{ intrinseque 99
{ spatiale 76
{ temporelle 76
concat vect 31
concat
enation
{ de langages 133
{ de listes 31
{ de mots 132
conjonction 61
Index
connecteur logique 60,65,69
{ ternaire 73
consensus 176
constructeur 90,120,246
contradiction 176
D
Davis et Putnam 72
de Morgan 62,73
d
ecision
{ algorithmes 151
{ arbre 88,99,108,110
degre dun nffud 87
depiler 53
derecursication 52
derivation dune expression 120
descendant 87
determinant 84
determinisation 146,154
dichotomie 36
dierence densembles 50
disjonction 61
distribution de verite 71
diviser pour regner 17,78,82
do list 27,32
do vect 27
E
elements equivalents 34
empiler 53
equation de degre deux 9,89
EQUIV 34
et 61
etat accessible 155
{ coaccessible 155
{ rebut 151,155
etiquette 88
etoile dun langage 133
{ lemme 153
evaluation
{ dun arbre 97
{ dun polyn^
ome 12
{ dune formule inxe 59
{ dune formule logique 71
{ dune formule postxe 56
exponentiation 11,14,17,22
expression
{ arithmetique 115,141
{ conditionnelle 58
{ normalisee 118
{ reguliere 134
F
facteur dun mot 133
faux 60
feuille 87
Fibonacci 22,79,101
le dattente 174
ls 87
301
{ droit, gauche 88
{ gauche - frere droit 94,104
fonction 9
{ booleenne 61,65,68,73
{ de transition 138
for^et 88
forme normale
{ normale conjonctive 69,72,73
{ normale disjonctive 68
{ normale exclusive 74
formule
{ derivation 120
{ inxe 55,59
{ logique 69,74
{ mathematique 55
{ postxe 55,56,59
{ prexe 55,59
{ representation 116
{ simplication 124
{ valeur 55
Fourier 266
frere 87
fusion
{ darbres de recherche 114
{ de listes cha^nees 39
{ de vecteurs 38
{ multiple 50
{ sans repetition 50
G
G noeud 92
graphe 122
H
Hamming 174
Hanoi 80
hauteur dun arbre 87,99
hd 26
rner 13,20
Ho
I
image miroir 32,133
implication 61
indice de boucle 11
infixe
{ formule 55,59
{ ordre 95,104,109
insertion
{ a la racine 112,114
{ aux feuilles 103,111,114
{ dans un arbre de priorite 164
{ dans un arbre de recherche 111
{ dans une liste 30
{ dans une liste triee 34
{ sans repetition 50
interpolation de Lagrange 159,197
interpreteur 131
intersection densembles 50
invariant de boucle 13
302
Annexes
inversion 41
iteration 11
K
Karatsuba 20,23,266
Kleene 147
Knuth 18,266
L
Lagrange 160,197
langage 132
{ des parentheses 134,137,152,155
{ non regulier 152
{ reconnaissable 145
{ regulier 134
{ residuel 152
largeur dun arbre 95
Lazard 133
lemme de letoile 153,156
lettre 132
Levi 136
lexeme 55,130
lexical 131
lexicographique 61,120,191,218,220
liste 24
{ a double entree 33
{ cha^nee 26
{ parenthesee 105
{ presque triee 51
{ triee 34
litteral 67
logique ternaire 73
longueur du chemin externe 103,108
{ du chemin interne 103,240
M
machine parallele 78
{ sequentielle 78
maple 244
matrice de transition 141
merge 51
minterme 67
mon^
ome 67
mot 132
multiplication
{ de Karatsuba 20
{ de Knuth 18
{ de polyn^
omes 18
{ matricielle 84
{ par transformation de Fourier rapide 266
{ rapide 23,159
mutable 54
Myers 272
N
n-uplet 25
Newton 160
nffud 87
{ interne 87
{ terminal 87
nombre de Catalan 102
{ parfait 20
non 61
O
operations
{ sur les ensembles 50
{ sur les langages 133
ordre
{ inxe 95,104,109
{ lexicographique 61,120,191,218,220
{ postxe 95,104
{ prexe 95,104
{ sur les expressions 119
{ symetrique 95
ou 61
oubien 61
P
parcours
{ dun arbre 94,104
{ dune formule 70
{ dune liste 27
{ de graphe 144,243
{ en largeur dabord 95,98,144
{ en profondeur dabord 95,144
partage 124,129
pere 87,93
PG 118
pile 53,56,59,166
{ dexecution 54
PLUSGRAND 34
PLUSPETIT 34
pointeur 11
polyn^
ome creux 50
porte logique 63
postfixe
{ formule 55,59
{ ordre 95,104
predicat 33
pr
efixe
{ facteur 133
{ formule 55,59
{ ordre 95,104
priorite 59
produit booleeen 61
{ generalise 118
profondeur
{ dun circuit 64
{ dun nffud 87,102,103
programme 9
{ dun automate 138
proposition 60
{ identique 60
Q
queue dune liste 24
quicksort 46
Index
R
racine carree 21
{ carree dun langage 155
{ dun arbre 87
recherche
{ dune cha^ne de caracteres 167
{ dune sous-liste 33
{ dans un arbre binaire de recherche 110
{ dans une liste 28
{ dans une liste triee 35
{ par dichotomie 36
record 54
r
ecursivit
e
{ mutuelle 16,143
{ simple 14
{ terminale 110,199,231,232
reduction 56,58,186
reference 11
regulier 134
relation de comparaison 34
rev 32
rotation dune liste 32
S
satisabilite 69,71
segmentation 46
semantique 130,151
serie generatrice 101,102
simplification
{ dun automate 155
{ dune formule 124,129
{ dune formule logique 74
somme booleenne 61
{ de langages 133
sommet de pile 53
sort 51
sortance 64
Strassen 84
structure FIFO 175
{ LIFO 53
substitution 129
suxe 133
suppression
{ dans un arbre 113
{ dans une liste 30
syntaxique 131
T
table de verite 61,71
303
taille dun arbre 87,99
tautologie 60,69,71,74
temps
{ de propagation 64
{ de separation-recombinaison 80
{ moyen dune comparaison 85
terminaison 11
t^ete dune liste 24
Thompson 147
tl 26
tours de Hanoi 80
transition generalisee 139
transitions dun automate 138
tri
{ a bulles 41,50,51
{ complexite en moyenne 108
{ complexite intrinseque 99
{ dune liste 39
{ en arbre 165
{ par comparaisons 40,99,108
{ par distribution 158
{ par fusion 42
{ par fusion naturelle 52
{ par selection 80
{ rapide 46,52,114
{ stable 40
{ topologique 182
Turbo-Pascal 137
U
Ukkonen 272
union densembles 50
V
valeur dune formule 55
{ de verite 60
variable propositionnelle 61
vect length 26
vecteur 26
{ circulaire 33
{ dindexation 49
vrai 60
W
Wallis 102
Warshall 251