Planche 1
Planche 2
Plan
- Connexité
- Algorithmes avec matrices de connexion
- Plus court chemin
- Exploration
- de Java vers C
- Gestion de la mémoire
- Exercices
Planche 3
Sortie de labyrinthe
Exemple de depth-first search.
On cherche un chemin de d à s.
let rec chemin d s =
num.(d) <- true;
let p = ref [] in
List.iter (function x ->
if x = s then p := [s];
if not num.(x) && !p = [] then
p := chemin x s)
graphe.(d);
if (!p = []) || (d = s) then !p else d :: !p;;
Comment faire la sortie par le chemin le plus court?
Comment trouver et imprimer tous les chemins?
Planche 4
Sortie de labyrinthe -- Java
static ListeNoeuds chemin (int d, int s) {
num[d] = true;
for (ListeNoeuds y = graphe[d]; y != null; y = y.suivant) {
int x = y.nom;
if (x == s)
return new ListeNoeuds (s, null);
if (!num[x]) {
ListeNoeuds p = chemin x s;
if (p != null)
return new ListeNoeuds (d, p);
}
}
return null;
}
Planche 5
Bi-connectivité
Dans un graphe non orienté, existe-t-il 2 chemins différents entre
toute paire de noeuds? Un point d'articulation est un point qui
sépare le graphe en parties non connexes si on l'enlève. Un graphe
sans point d'articulation est un graphe bi-connexe. La fonction
suivante (en dfs) imprime les points d'articulation.
let min = ref nMax;;
let rec visit k =
incr id; num.(k) <- !id; min := !id;
List.iter (function x ->
if num.(x) = -1 then begin
let m = visit x in
if m < !min then min := m;
if m >= num.(k) then printf "%d " k
end else
if num.(x) < !min then min := num.(x))
graphe.(k);
!min;;
Planche 6
Composantes fortement connexes
Dans un graphe non orienté, on calcule facilement la connexité. Mais
dans un graphe orienté? Commne trouver les composantes fortement
connexes? Ie les parties où toute paire de noeuds distincts est reliée
par un chemin.

Planche 7
Points d'attache
Dans le ch5 du poly, on décrit la notion de point d'attache dans un
graphe:

Planche 8
Calcul des composantes fortement connexes
let rec cf_connexe k =
incr id; num.(k) <- !id;
Pile.empiler k p;
let min = ref !id in
List.iter (function x ->
let m = if num.(x) = -1 then cf_connexe (x) else num.(x) in
if m < !min then
min := m)
graphe.(k);
if !min = num.(k) then
(try while true do
printf "%d " (Pile.sommet p);
num.(Pile.sommet p) <- nMax;
Pile.depiler p;
if Pile.sommet p = k then raise Exit
done
with Exit -> printf "\n");
!min;;
Planche 9
Fermeture transitive
Dans un graphe dirigé, trouver toutes les paires de noeuds reliés par
un chemin. On le fait en manipulant des matrices d'adjacences.
[Warshall]
let fermeture_transitive m =
let r = Array.copy m and n = Array.length m in
for k = 0 to n - 1 do
for i = 0 to n - 1 do
for j = 0 to n - 1 do
r.(i).(j) <- r.(i).(j) || (r.(i).(k) && r.(k).(j));
done;
done;
done;
r;;
Complexité ?
[La méthode avec n multiplications de matrices est elle en O(n4).]
Planche 10
Plus courts chemins
G=(V,E) muni d'une fonction de valuation sur les réels w: E ®
R. Trouver les plus courts chemins. Idem à fermeture
transitive en changeant une ligne. [Floyd]
let plus_courts_chemins m =
let r = Array.copy m and n = Array.length m in
for k = 0 to n - 1 do
for i = 0 to n - 1 do
for j = 0 to n - 1 do
r.(i).(j) <- min (r.(i).(j), (r.(i).(k) + r.(k).(j)));
done;
done;
done;
r;;
Programmation dynamique (contrôle/optimisation, Bellman): on met en
table beaucoup de résultats intermédiaires pour résoudre plus
rapidement le problème final. (cf. ch 8)
Planche 11
Plus court chemin entre deux noeuds
Le plus court chemin entre tous les points est un problème différent
du plus court chemin entre 2 noeuds donnés.
Si les poids sont tous positifs, l'algorithme de Dijkstra le résoud
par une exploration avec un algorithme glouton et une file de
priorité en O((V+E) log V).
Si les poids peuvent être négatifs, l'algorithme de Ford-Bellman
marche en O(V E). [Il n'y a pas de solution si un cycle négatif est
accessible depuis la source.]
Planche 12
Exploration -- Branch and Bound
Dans un graphe non dirigé, trouver un circuit Hamiltoniens, ie un
circuit simple passant par tous les points. Pb NP-complet.
On peut le résoudre par une recherche exhaustive:
let rec hamiltonien k s =
incr id; num.(k) <- !id;
let p = ref [] in
List.iter (function x ->
if num.(x) = 0 && num.(k) = nMax - 1 then p := [s];
if num.(x) = -1 && !p = [] then
p := hamiltonien x s)
graphe.(k);
decr id; num.(k) <- -1;
if (!p = []) || (!p = [s]) then !p else k :: !p;;
Planche 13
Exploration -- les 8 reines
Mettre huit reines non en prise sur un échiquier:
let nReines n =
let pos = Array.make n 0 in
let conflit i1 j1 i2 j2 = i1 = i2 || j1 = j2 ||
abs(i1 - i2) = abs (j1 - j2) in
let compatible i j =
try for k = 0 to i-1 do
if conflit i j k pos.(k) then raise Exit
done;
true with Exit -> false in
let rec reines i = if i >= n then
imprimerSolution pos
else
for j = 0 to n-1 do
if compatible i j then begin pos.(i) <- j; reines (i+1) end
done in
reines 0;;
Planche 14
Exploration -- stratégies dans les jeux
La recherche exhaustive correspond à des algorithmes en temps
exponentiel. La programmation récursive permet de gérer les choix et
les retours en arrières (backtracking). D'un point de vue
algorithmique, elle ne présente que peu d'intérêt. Toutefois, elle est
bien utile dans les jeux résolus par force brute (exemple Deep Blue
pour les échecs).
Pour les jeux, on utilise des fonctiosn alpha-beta: on a une méthode
rapide d'évaluation d'une configuration (par exemple un état de
l'échiquier, Deep Blue le fait en ~ 1/200000 sec). Puis on gère
une recherche exhaustive pour trouver le meilleur coup contre le pire
coup de l'adversaire, qui venait de réagir à son meilleur coup,
lui-même réponse de son pire coup, etc. Typiquement, aux échecs on
fait 7-8 niveaux d'alpha-beta.
Planche 15
Quelques graphes utiles sur les programmes
- Les données dans la mémoire d'un ordinateur. Arc d'une donnée à une
autre s'il existe une référence de l'une vers l'autre. Ainsi des
listes, des arbres correspondent à des graphes.
Le glaneur de cellule (GC) parcourt ce graphe pour détecter les
données inaccessibles, et donc récupérables.
- Le graphe des appels de procédures dans un programme. Un arc
entre deux procédures si une appelle l'autre.
- Le graphe (non dirigé) des durée de vie des variables. Deux
variables ont un arc entre elles ssi elles existent simultanément.
- Le graphe de dépendances entre modules pour refabriquer un
paquetage. (Données des makefile).
- etc.
Planche 16
De Java au langage C
La syntaxe de Java vient de celle de C. Donc beaucoup d'instructions se
ressemblent.
Les structures de données sont différentes.
Les tableaux en C ne sont pas créés dynamiquement. On déclare leur taille
à la compilation. Ainsi:
int t[10]; /* tableau de 10 entiers */
Il n'y a pas d'objets. On utilise des enregistrements (structures).
struct { /* cellule de liste */
int contenu;
struct liste *suivant; /* adresse d'une cellule de liste */
} liste;
struct liste *a, *b;
typedef struct liste *Liste;
Liste c, d;
Planche 17
De Java au langage C -- bis
En C, il y a une race de variables inconnues en Java: les pointeurs
int x;
int *p = &x; /* l'adresse de x est rangée dans p */
int y = *p; /* le contenu de ce qui est pointé par p est mis dans y */
La gestion de la mémoire est manuelle
Liste nouvelleListe (int x, Liste a)
{
Liste b = (Liste) malloc (sizeof (struct liste));
b -> contenu = x;
b -> suivant = a;
return b;
}
b -> suivant est une abréviation pour *(b).suivant
C ne fait aucune vérification à l'exécution (sortie de tableau,
pointeur non initialisé, etc). Le système Unix est écrit en C.
Planche 18
Problèmes non traités
Le cours n'est qu'une introduction aux méthodes algorithmiques et à la
programmation. Il contient 2 cours habituels dans un cursus normal
d'université: programmation et structures de données élémentaires,
introduction à l'algorithmique. Les 2 parties peuvent se décliner plus
longuement vers la logique et la validation de programme, ou vers la
complexité et l'analyse de performances.
Nous n'avons pas vu quelques problèmes classiques:
- algorithmes géométriques
- algorithmes semi numériques (FFT)
- NP complétude
- algorithmes probabilistes
- asynchronisme (fortement ou faiblement couplé)
- programmation objet
Planche 19
Cursus d'informatique
- majeure math-info
- majeure d'informatique
- DEA (par exemple, Algo ou SPP)
- recherche en informatique = un des domaines scientifiques les
plus actifs du moment
Þ sociétés de technologie
Planche 20
Exercices en TD
- Calculer les composantes connexes dans un graphe non orienté
- Sortie de labyrinthe
This document was translated from LATEX by HEVEA.