Planche 1

PC10
Jean-Jacques.Levy@inria.fr
http://www.polytechnique.fr/poly/~levy/
INRIA -- Rocquencourt
tel: 01 39 63 56 89


secrétariat: Catherine Bensoussan
cb@lix.polytechnique.fr
Aile 00,
LIX
tel: 34 67


http://w3.edu.polytechnique.fr/informatique/


Planche 2

Plan

  1. Connexité
  2. Algorithmes avec matrices de connexion
  3. Plus court chemin
  4. Exploration
  5. de Java vers C
  6. Gestion de la mémoire
  7. 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


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:


Planche 19

Cursus d'informatique

Þ sociétés de technologie


Planche 20

Exercices en TD


This document was translated from LATEX by HEVEA.