Chapitre 14 — Retour sur trace
Explorer systématiquement, revenir sur un choix et élaguer les impasses CHOISIR → TESTER → AVANCER → IMPASSE ? → ANNULER → ESSAYER AUTREMENT |
Fiche pédagogique du chapitre
Objectifs d’apprentissage
À la fin de ce chapitre, l’étudiant devra être capable de :
- expliquer le principe du retour sur trace et le distinguer de la recherche exhaustive naïve ;
- représenter un problème de décision par un arbre de recherche ;
- identifier les états, les choix possibles, les contraintes et les cas de succès ou d’échec ;
- construire une solution progressivement puis annuler proprement un choix ;
- concevoir des conditions de validité partielle pour détecter rapidement les impasses ;
- appliquer la méthode aux permutations, aux N reines, aux labyrinthes, au Sudoku et à la somme de sous-ensembles ;
- améliorer une recherche grâce à l’élagage, à l’ordre des choix et à la mémorisation des états ;
- analyser la terminaison, la correction et la complexité d’un algorithme de retour sur trace.
Prérequis
- fonctions, procédures et récursivité ;
- tableaux, matrices, piles, ensembles et dictionnaires ;
- arbres et parcours en profondeur ;
- complexité temporelle et spatiale ;
- notions de contrainte, invariant et solution partielle.
Organisation indicative
Partie | Contenu | Durée indicative |
|---|---|---|
| 14.1 | Principe général, choix, annulation et schéma générique | 2 h |
| 14.2 | Arbre de recherche, états, impasses et élagage | 2 h |
| 14.3 | Cinq exemples classiques et traces d’exécution | 5 h |
| 14.4 | Optimisations, heuristiques et mémorisation | 2 h |
| TD / TP | Conception, justification et expérimentation | 4 h |
| Idée directrice |
| Le retour sur trace construit une solution étape par étape. Lorsqu’un choix rend la solution partielle impossible, l’algorithme revient au dernier point de décision, annule ce choix et explore une autre branche. Il ne conserve donc pas une décision irréversible contrairement à une stratégie gloutonne. |
14.1 Principe
Définition générale
Le retour sur trace, souvent appelé backtracking, est une méthode de recherche systématique adaptée aux problèmes où une solution doit être construite par une succession de décisions. Chaque décision étend une solution partielle. Dès qu’une contrainte est violée ou qu’aucune continuation n’est possible, la dernière décision est annulée.
La méthode repose sur une exploration en profondeur de l’espace des solutions. La pile des appels récursifs mémorise naturellement les décisions prises, ce qui permet de revenir à l’état précédent lorsque la branche courante échoue.
| Différence essentielle |
| Une recherche exhaustive génère parfois toutes les solutions complètes avant de les tester. Le retour sur trace teste la validité dès la construction et abandonne immédiatement les préfixes qui ne peuvent conduire à aucune solution. |
Construction progressive d’une solution
La solution est représentée par un état partiel : un préfixe de permutation, des reines déjà placées, un chemin partiel dans un labyrinthe, quelques cases remplies d’un Sudoku ou un sous-ensemble en cours de construction.
Élément | Rôle dans la recherche | Exemple avec les N reines |
|---|---|---|
| État | Description de la solution partielle | Reines placées sur les premières lignes |
| Choix | Décision disponible depuis l’état courant | Choisir une colonne pour la prochaine reine |
| Transition | Application du choix | Placer la reine dans la case choisie |
| Test de validité | Vérification des contraintes | Aucune reine sur la même colonne ou diagonale |
| Cas de succès | Solution complète valide | N reines placées |
| Cas d’échec | Aucun choix valide restant | Toutes les colonnes sont interdites |
Test d’une possibilité
Pour chaque état, l’algorithme énumère les choix candidats. Un candidat peut être testé avant son application, après son application, ou aux deux moments. Tester avant évite une modification inutile ; tester après peut simplifier le code lorsque la validation porte sur l’état obtenu.
- Un choix admissible respecte les contraintes locales connues.
- Un choix prometteur possède encore une possibilité de mener à une solution.
- Un choix complet produit une solution lorsque tous les éléments attendus sont fixés.
- Un choix impossible doit être rejeté avant d’explorer ses descendants.
Annulation d’un choix
L’annulation restaure exactement l’état qui existait avant le choix. Cette propriété est fondamentale. Une variable, une case, une marque de visite ou une structure auxiliaire modifiée doit retrouver sa valeur précédente.
| Invariant de restauration |
| Après le retour d’un appel récursif, l’état courant doit être identique à l’état précédant l’essai du candidat. Une annulation incomplète entraîne des erreurs discrètes : des choix valides peuvent être rejetés ou des solutions invalides peuvent être acceptées. |
ZONE DE PSEUDO-CODE — Schéma générique du retour sur trace Fonction Explorer(etat) : Booléen Si EstSolution(etat) Alors EnregistrerOuAfficher(etat) Retourner Vrai // ou continuer pour toutes les solutions FinSi
Pour chaque choix dans Candidats(etat) Faire Si EstAdmissible(etat, choix) Alors Appliquer(etat, choix) succes ← Explorer(etat) Annuler(etat, choix)
Si succes Alors Retourner Vrai // retirer ce test pour tout énumérer FinSi FinSi FinPour
Retourner Faux FinFonction |
Exploration d’une autre possibilité
Lorsqu’une branche échoue, la boucle reprend avec le candidat suivant. L’ordre de cette boucle ne change pas l’ensemble des solutions théoriquement accessibles, mais il peut modifier fortement le temps nécessaire pour trouver la première solution.
Objectif | Comportement après une solution | Résultat |
|---|---|---|
| Trouver une solution | Arrêt immédiat et propagation de Vrai | Une solution quelconque |
| Trouver toutes les solutions | Poursuite après enregistrement | Liste ou nombre de solutions |
| Trouver la meilleure solution | Poursuite avec comparaison et borne | Solution optimale |
| Décider l’existence | Arrêt dès le premier succès | Vrai ou Faux |
Récursivité et pile explicite
La récursivité exprime naturellement la profondeur de l’arbre de recherche. Chaque appel correspond à un nœud et mémorise l’état local. Une version itérative peut utiliser une pile explicite contenant les états à explorer, mais l’annulation doit alors être remplacée par la création ou la copie d’états indépendants.
Approche | Avantages | Limites |
|---|---|---|
| Récursive | Proche de la définition, code concis, annulation naturelle | Risque de dépassement de pile, état partagé à gérer |
| Itérative avec pile | Contrôle explicite de la mémoire, reprise possible | États à copier ou encoder, code plus complexe |
| Générateur / itérateur | Produit les solutions à la demande | Implémentation dépendante du langage |
14.2 Arbre de recherche
Nœud de décision
Un nœud représente un état partiel. La racine correspond à l’état initial, avant toute décision. La profondeur indique le nombre de choix déjà réalisés. Une feuille peut être une solution complète, une impasse ou un état terminal ne nécessitant plus de décision.
| Lecture d’un nœud |
| Pour comprendre un arbre de recherche, il faut préciser ce que mémorise un nœud, quels choix créent ses enfants et quelle condition distingue une solution d’une impasse. |
Branche
Une branche est une séquence de décisions allant de la racine vers un nœud. Elle décrit donc une solution partielle. L’exploration en profondeur suit une branche aussi loin que possible avant de revenir vers un ancêtre possédant encore un enfant non exploré.
ZONE DE PSEUDO-CODE — Parcours en profondeur avec une pile explicite Procédure ExplorerAvecPile(etatInitial) pile ← PileVide() Empiler(pile, etatInitial)
TantQue NON EstVide(pile) Faire etat ← Depiler(pile) Si EstSolution(etat) Alors Afficher(etat) Sinon Pour chaque choix admissible de etat Faire suivant ← Copier(etat) Appliquer(suivant, choix) Empiler(pile, suivant) FinPour FinSi FinTantQue FinProcédure |
Solution partielle
Une solution partielle doit contenir suffisamment d’informations pour poursuivre la recherche et vérifier les contraintes. Elle ne doit pas nécessairement stocker tout l’historique si certaines informations peuvent être reconstruites ou maintenues dans des structures auxiliaires.
Problème | Solution partielle | Informations auxiliaires utiles |
|---|---|---|
| Permutation | Préfixe de valeurs choisies | Tableau utilisé |
| N reines | Colonne choisie pour chaque ligne traitée | Colonnes et diagonales occupées |
| Labyrinthe | Chemin courant | Cases visitées |
| Sudoku | Grille partiellement remplie | Chiffres autorisés par ligne, colonne et bloc |
| Sous-ensembles | Décisions inclure / exclure | Somme courante et bornes restantes |
Impasse
Une impasse est un état non complet qui ne peut être prolongé vers une solution. Elle apparaît lorsqu’aucun candidat n’est admissible, lorsqu’une contrainte est déjà violée ou lorsqu’une borne prouve qu’un objectif ne peut plus être atteint.
- Dans les N reines, une ligne sans colonne sûre constitue une impasse.
- Dans un labyrinthe, une case dont toutes les voisines sont bloquées ou déjà visitées est une impasse.
- Dans un Sudoku, une case vide sans chiffre possible révèle une contradiction.
- Dans la somme de sous-ensembles à valeurs positives, une somme courante supérieure à la cible peut être abandonnée.
Élagage
L’élagage supprime une branche sans visiter tous ses descendants. Il est correct uniquement si l’on peut démontrer qu’aucun descendant supprimé ne peut produire une solution recherchée ou une solution meilleure que la meilleure déjà connue.
Type d’élagage | Question posée | Exemple |
|---|---|---|
| Par contrainte | La solution partielle est-elle encore valide ? | Deux reines se menacent |
| Par impossibilité | Peut-on encore compléter la solution ? | Case de Sudoku sans candidat |
| Par borne | Cette branche peut-elle battre la meilleure solution ? | Coût partiel déjà trop élevé |
| Par symétrie | Cette branche est-elle équivalente à une déjà explorée ? | Première reine reflétée horizontalement |
| Par mémorisation | Cet état a-t-il déjà été résolu ? | Même position et mêmes ressources restantes |
| Attention terminologique |
| L’élagage ne consiste pas à supprimer arbitrairement des choix pour accélérer le programme. Chaque branche éliminée doit être justifiée par une propriété du problème, une borne sûre ou une équivalence d’états. |
Exemple d’arbre de recherche
Pour former des suites de longueur 3 avec les symboles A et B, chaque nœud choisit le prochain symbole. Si l’on interdit deux B consécutifs, les branches contenant le préfixe BB sont immédiatement élaguées.
ZONE DE PSEUDO-CODE — Schéma de l’arbre des suites sans « BB » ε / \ A B / \ / \ AA AB BA BB × / \ / \ / \ AAA AAB ABA ABB× BAA BAB
× : branche élaguée dès que le préfixe contient deux B consécutifs. |
Profondeur, facteur de branchement et taille de l’espace
Si chaque nœud possède au plus b enfants et si la profondeur maximale est d, l’arbre brut peut contenir de l’ordre de b^d feuilles. Cette croissance exponentielle explique pourquoi les vérifications anticipées et les heuristiques d’ordre sont essentielles.
Paramètre | Signification | Effet sur le coût |
|---|---|---|
| b | Nombre moyen de choix par état | Une petite réduction de b peut produire un gain exponentiel |
| d | Nombre de décisions nécessaires | Détermine la profondeur de récursion |
| k | Nombre de branches effectivement visitées | Dépend directement de l’efficacité de l’élagage |
| s | Taille de l’état sauvegardé | Influence la mémoire et le coût d’annulation |
14.3 Exemples
Exemple 1 — Génération de permutations
Une permutation de n éléments est un ordre possible contenant chaque élément exactement une fois. Le retour sur trace choisit successivement une valeur non encore utilisée. Lorsque la longueur du préfixe atteint n, une permutation complète est obtenue.
Étape | Préfixe | Éléments disponibles | Décision possible |
|---|---|---|---|
| 0 | [ ] | {A, B, C} | A, B ou C |
| 1 | [A] | {B, C} | B ou C |
| 2 | [A, B] | {C} | C |
| 3 | [A, B, C] | ∅ | Permutation complète |
ZONE DE PSEUDO-CODE — Permutations avec tableau « utilisé » Procédure Permuter(valeurs, position, resultat, utilise) n ← Longueur(valeurs) Si position = n Alors Afficher(resultat) Retourner FinSi
Pour i ← 0 à n - 1 Faire Si NON utilise[i] Alors resultat[position] ← valeurs[i] utilise[i] ← Vrai
Permuter(valeurs, position + 1, resultat, utilise)
utilise[i] ← Faux // annulation du choix FinSi FinPour FinProcédure |
Pour n éléments distincts, il existe n! permutations. L’algorithme ne peut donc pas être asymptotiquement plus rapide que Θ(n · n!) si chaque permutation complète doit être affichée, car l’écriture d’une solution coûte Θ(n).
| Gestion des doublons |
| Si le tableau contient des valeurs identiques, il faut trier les valeurs et ignorer un candidat égal au précédent lorsque le précédent n’a pas été utilisé au même niveau. Cette règle évite de générer plusieurs fois la même permutation. |
Exemple 2 — Problème des N reines
Le problème demande de placer N reines sur un échiquier N × N sans que deux reines partagent une ligne, une colonne ou une diagonale. En plaçant exactement une reine par ligne, l’algorithme ne doit choisir qu’une colonne pour chaque ligne.
Structure | Index utilisé | Interprétation |
|---|---|---|
| colonnes[c] | c | Une reine occupe la colonne c |
| diag1[l - c + N - 1] | l - c | Une diagonale descendante est occupée |
| diag2[l + c] | l + c | Une diagonale montante est occupée |
| position[l] | l | Colonne de la reine placée sur la ligne l |
ZONE DE PSEUDO-CODE — Résolution des N reines Fonction PlacerReine(ligne, N, position, colonnes, diag1, diag2) : Booléen Si ligne = N Alors AfficherEchiquier(position) Retourner Vrai FinSi
Pour colonne ← 0 à N - 1 Faire d1 ← ligne - colonne + N - 1 d2 ← ligne + colonne
Si NON colonnes[colonne] ET NON diag1[d1] ET NON diag2[d2] Alors position[ligne] ← colonne colonnes[colonne] ← Vrai diag1[d1] ← Vrai diag2[d2] ← Vrai
Si PlacerReine(ligne + 1, N, position, colonnes, diag1, diag2) Alors Retourner Vrai FinSi
colonnes[colonne] ← Faux diag1[d1] ← Faux diag2[d2] ← Faux FinSi FinPour
Retourner Faux FinFonction |
Le pire cas reste exponentiel, mais les tableaux de colonnes et de diagonales transforment le test de sécurité en O(1). Une version naïve qui parcourt toutes les reines déjà placées effectuerait un test en O(N) à chaque candidat.
Réduction par symétrie
Pour compter les solutions, on peut limiter la première reine à la moitié des colonnes, puis doubler les solutions obtenues par réflexion. Si N est impair, la colonne centrale doit être traitée séparément. Cette réduction exploite une symétrie sûre sans perdre de solutions distinctes à réflexion près.
Exemple 3 — Résolution d’un labyrinthe
Le labyrinthe est modélisé par une matrice. Une case peut être libre, bloquée, visitée, appartenir au chemin courant ou constituer la sortie. Depuis une case, l’algorithme essaie les déplacements disponibles dans un ordre choisi.
Symbole | Signification |
|---|---|
| 0 | Case libre |
| 1 | Mur |
| 2 | Case du chemin courant |
| 3 | Case visitée puis abandonnée |
| S | Départ |
| E | Sortie |
ZONE DE PSEUDO-CODE — Recherche d’un chemin dans un labyrinthe Fonction ResoudreLabyrinthe(grille, ligne, colonne, sortie) : Booléen Si (ligne, colonne) = sortie Alors grille[ligne][colonne] ← 2 Retourner Vrai FinSi
Si HorsLimites(ligne, colonne) OU grille[ligne][colonne] ≠ 0 Alors Retourner Faux FinSi
grille[ligne][colonne] ← 2
Pour chaque (dl, dc) dans [(0,1), (1,0), (0,-1), (-1,0)] Faire Si ResoudreLabyrinthe(grille, ligne + dl, colonne + dc, sortie) Alors Retourner Vrai FinSi FinPour
grille[ligne][colonne] ← 3 Retourner Faux FinFonction |
| Visité ou chemin courant ? |
| Une case du chemin courant doit être restaurée lorsqu’une branche échoue. Pour une simple recherche d’existence, une case déjà visitée peut rester définitivement marquée si l’état futur ne dépend que de la position. Si l’état inclut d’autres ressources, la position seule ne suffit plus pour mémoriser un échec. |
Pour trouver le chemin le plus court dans un labyrinthe non pondéré, le parcours en largeur est généralement préférable. Le retour sur trace convient à la recherche d’un chemin quelconque, à l’énumération de tous les chemins ou à des variantes comportant des contraintes supplémentaires.
Exemple 4 — Sudoku simplifié
Un Sudoku 4 × 4 utilise les chiffres 1 à 4 et des blocs 2 × 2. Le principe est identique à celui d’un Sudoku 9 × 9 : choisir une case vide, essayer chaque chiffre autorisé, poursuivre, puis effacer le chiffre si une contradiction apparaît.
Vérification | Contrainte |
|---|---|
| Ligne | Le chiffre ne doit pas apparaître dans la ligne |
| Colonne | Le chiffre ne doit pas apparaître dans la colonne |
| Bloc | Le chiffre ne doit pas apparaître dans le bloc 2 × 2 |
| Domaine | Chaque case reçoit un chiffre compris entre 1 et 4 |
ZONE DE PSEUDO-CODE — Sudoku simplifié Fonction ResoudreSudoku(grille) : Booléen case ← ChoisirCaseVide(grille) Si case = AUCUNE Alors Retourner Vrai FinSi
(ligne, colonne) ← case Pour valeur ← 1 à Taille(grille) Faire Si Autorisee(grille, ligne, colonne, valeur) Alors grille[ligne][colonne] ← valeur
Si ResoudreSudoku(grille) Alors Retourner Vrai FinSi
grille[ligne][colonne] ← 0 FinSi FinPour
Retourner Faux FinFonction |
Heuristique de la case la plus contrainte
Choisir la première case vide est correct mais parfois inefficace. L’heuristique MRV, Minimum Remaining Values, sélectionne la case possédant le moins de chiffres autorisés. Une contradiction est alors détectée plus tôt et le facteur de branchement est réduit.
| Propagation de contraintes |
| Après avoir placé un chiffre, on peut retirer ce chiffre des domaines des cases de la même ligne, colonne et bloc. Si un domaine devient vide, la branche est abandonnée. Si un domaine contient une seule valeur, celle-ci peut parfois être imposée. |
Exemple 5 — Somme de sous-ensembles
Étant donné un tableau de nombres et une cible, il faut déterminer s’il existe un sous-ensemble dont la somme vaut la cible. Pour chaque élément, deux décisions sont possibles : l’inclure ou l’exclure.
ZONE DE PSEUDO-CODE — Somme de sous-ensembles — version booléenne Fonction ExisteSousEnsemble(T, indice, sommeCourante, cible) : Booléen Si sommeCourante = cible Alors Retourner Vrai FinSi
Si indice = Longueur(T) Alors Retourner Faux FinSi
// Branche 1 : inclure T[indice] Si ExisteSousEnsemble(T, indice + 1, sommeCourante + T[indice], cible) Alors Retourner Vrai FinSi
// Branche 2 : exclure T[indice] Retourner ExisteSousEnsemble(T, indice + 1, sommeCourante, cible) FinFonction |
Sans élagage, l’arbre comporte jusqu’à 2^n feuilles. Si tous les nombres sont positifs, une branche peut être abandonnée lorsque la somme courante dépasse la cible. On peut également utiliser la somme des éléments restants pour détecter une cible devenue inatteignable.
ZONE DE PSEUDO-CODE — Version avec solution et bornes positives Fonction Chercher(T, i, somme, reste, cible, choix) : Booléen Si somme = cible Alors Afficher(choix) Retourner Vrai FinSi
Si i = Longueur(T) OU somme > cible OU somme + reste < cible Alors Retourner Faux FinSi
Ajouter(choix, T[i]) Si Chercher(T, i + 1, somme + T[i], reste - T[i], cible, choix) Alors Retourner Vrai FinSi RetirerDernier(choix)
Retourner Chercher(T, i + 1, somme, reste - T[i], cible, choix) FinFonction |
| Limite de la borne « somme > cible » |
| Cette règle n’est correcte que lorsque les valeurs restantes sont non négatives. Avec des nombres négatifs, une somme actuellement trop grande pourrait ensuite diminuer et atteindre la cible. |
Comparaison des exemples
Problème | Décision à chaque niveau | Profondeur maximale | Élagage principal |
|---|---|---|---|
| Permutations | Choisir un élément non utilisé | n | Éviter doublons et valeurs déjà utilisées |
| N reines | Choisir une colonne | N | Colonnes et diagonales occupées |
| Labyrinthe | Choisir un déplacement | Nombre de cases | Murs et états déjà visités |
| Sudoku | Choisir un chiffre autorisé | Nombre de cases vides | Contraintes et domaines vides |
| Sous-ensembles | Inclure ou exclure un élément | n | Bornes sur la somme |
14.4 Optimisations
Vérification anticipée
Une vérification anticipée détecte une contradiction immédiatement après une décision, avant de descendre plus profondément. Elle réduit la taille de l’arbre sans modifier les solutions valides.
Niveau de vérification | Principe | Exemple |
|---|---|---|
| Avant le choix | Tester si le candidat est admissible | Colonne libre pour une reine |
| Après le choix | Tester les conséquences immédiates | Domaine vide dans le Sudoku |
| Avant la récursion | Tester une borne globale | Somme maximale restante insuffisante |
| À chaque niveau | Vérifier un invariant | Aucune valeur utilisée deux fois |
Réduction des possibilités
La réduction de domaine consiste à supprimer les candidats incompatibles avec les décisions déjà prises. Elle peut être appliquée explicitement au moyen d’ensembles de candidats ou implicitement grâce à des tableaux de disponibilité.
- Maintenir les colonnes et diagonales occupées au lieu de rescanner l’échiquier.
- Pré-calculer les voisins accessibles d’une case de labyrinthe.
- Maintenir les chiffres disponibles pour chaque unité d’un Sudoku.
- Trier les éléments d’un problème de somme afin d’obtenir des bornes plus fortes.
- Exploiter les symétries pour ne visiter qu’un représentant de chaque classe équivalente.
Ordre des choix
L’ordre des candidats n’affecte pas la correction lorsque toutes les branches restent explorables, mais il peut déterminer si une solution est trouvée rapidement ou après une exploration très longue.
Heuristique | Idée | Application |
|---|---|---|
| Variable la plus contrainte | Choisir l’état ayant le moins de possibilités | Case MRV dans le Sudoku |
| Valeur la moins contraignante | Essayer le choix qui préserve le plus d’options | Affectation de ressources |
| Choix proche de l’objectif | Explorer d’abord les candidats prometteurs | Labyrinthe avec distance à la sortie |
| Valeurs décroissantes | Atteindre rapidement une somme ou une borne | Somme de sous-ensembles |
| Ordre aléatoire | Diversifier les recherches répétées | Problèmes possédant de nombreuses solutions |
| Heuristique versus preuve |
| Une heuristique d’ordre change la vitesse moyenne mais ne permet pas d’éliminer une branche. Un élagage, au contraire, doit être justifié pour garantir qu’aucune solution pertinente n’est perdue. |
Mémorisation des états
Deux chemins différents peuvent conduire au même état abstrait. Recalculer cet état répète inutilement le même sous-problème. Une table de mémorisation associe alors une représentation canonique de l’état à son résultat.
ZONE DE PSEUDO-CODE — Retour sur trace avec mémoïsation des échecs Fonction ExplorerMemo(etat, memoire) : Booléen cle ← Encoder(etat) Si cle appartient à memoire Alors Retourner Faux FinSi
Si EstSolution(etat) Alors Retourner Vrai FinSi
Pour chaque choix admissible Faire Appliquer(etat, choix) Si ExplorerMemo(etat, memoire) Alors Annuler(etat, choix) Retourner Vrai FinSi Annuler(etat, choix) FinPour
Ajouter(memoire, cle) // état démontré sans solution Retourner Faux FinFonction |
La clé doit contenir toutes les informations influençant les décisions futures. Mémoriser uniquement la position dans un labyrinthe est correct si aucune autre ressource n’existe ; ce serait incorrect si le joueur possède des clés, une énergie ou des portes déjà ouvertes.
Branch and bound
Pour un problème d’optimisation, le retour sur trace peut maintenir la meilleure solution trouvée. Une borne estime la meilleure valeur encore théoriquement atteignable depuis un état. Si cette borne ne peut pas améliorer le meilleur résultat courant, la branche est abandonnée.
Élément | Minimisation | Maximisation |
|---|---|---|
| Solution courante | Coût déjà accumulé | Gain déjà obtenu |
| Meilleure solution | Plus petit coût connu | Plus grand gain connu |
| Borne | Sous-estimation du coût final | Surestimation du gain final |
| Élagage | Borne ≥ meilleur coût | Borne ≤ meilleur gain |
Coût des optimisations
Une vérification plus forte réduit le nombre de nœuds mais demande davantage de calcul par nœud. L’optimisation pertinente minimise le coût total, et non uniquement le nombre de branches.
Technique | Gain possible | Coût / risque |
|---|---|---|
| Structures auxiliaires | Tests en O(1) | Mémoire et mises à jour lors de l’annulation |
| Propagation de contraintes | Réduction importante du domaine | Implémentation et restauration complexes |
| Mémorisation | Évite les sous-problèmes répétés | Table volumineuse et coût d’encodage |
| Heuristiques | Première solution trouvée plus tôt | Effet dépendant des instances |
| Symétries | Réduction parfois spectaculaire | Preuve d’équivalence nécessaire |
Analyse de la complexité
La complexité du retour sur trace s’exprime souvent en fonction du nombre de nœuds explorés. Dans le pire cas, l’élagage peut être inefficace et l’algorithme visite l’ensemble de l’espace de recherche.
Problème | Taille brute de l’espace | Remarque |
|---|---|---|
| Permutations | n! | Chaque ordre est une solution candidate |
| Sous-ensembles | 2^n | Deux décisions par élément |
| N reines | Au plus N^N, puis N! avec colonnes uniques | Les diagonales élaguent fortement |
| Sudoku | Jusqu’à 9^k pour k cases vides | Les contraintes réduisent les domaines |
| Labyrinthe | Exponentielle dans le nombre de cases | Dépend de la structure du graphe |
La mémoire récursive est généralement O(d), où d représente la profondeur, à laquelle s’ajoutent les structures de l’état. Lorsqu’une copie complète de l’état est créée à chaque appel, le coût mémoire peut devenir O(d × s).
Méthode de conception d’un algorithme de retour sur trace
1. Définir précisément une solution complète et les contraintes qu’elle doit satisfaire.
2. Choisir une représentation compacte de la solution partielle.
3. Identifier les décisions disponibles à chaque niveau.
4. Écrire le cas de succès et les cas d’échec immédiat.
5. Définir l’application et l’annulation exactes d’un choix.
6. Construire un test d’admissibilité aussi précoce que possible.
7. Choisir un ordre de candidats pertinent sans compromettre l’exhaustivité.
8. Ajouter progressivement des bornes, symétries ou mémorisations sûres.
9. Tester sur des cas vides, impossibles, uniques et possédant plusieurs solutions.
10. Mesurer le nombre de nœuds explorés en plus du temps d’exécution.
| Checklist avant validation |
| À chaque retour récursif, l’état a-t-il été restauré ? Le cas de base est-il atteignable ? Toutes les décisions possibles sont-elles couvertes ? Chaque élagage est-il sûr ? Une solution complète est-elle vérifiée avant d’être acceptée ? |
Applications guidées
Application 1 — Générer les mots binaires sans deux 1 consécutifs
La solution partielle est un préfixe. Le chiffre 0 est toujours admissible. Le chiffre 1 est admissible uniquement si le préfixe est vide ou si son dernier chiffre vaut 0.
ZONE DE PSEUDO-CODE — Mots binaires contraints Procédure Generer(prefixe, n) Si Longueur(prefixe) = n Alors Afficher(prefixe) Retourner FinSi
Ajouter(prefixe, 0) Generer(prefixe, n) RetirerDernier(prefixe)
Si prefixe est vide OU Dernier(prefixe) = 0 Alors Ajouter(prefixe, 1) Generer(prefixe, n) RetirerDernier(prefixe) FinSi FinProcédure |
Application 2 — Coloration d’un graphe
Chaque sommet doit recevoir une couleur différente de celles de ses voisins. Le retour sur trace choisit un sommet non coloré, essaie les couleurs autorisées et annule la couleur en cas d’échec.
ZONE DE PSEUDO-CODE — Coloration avec au plus K couleurs Fonction Colorier(sommet, graphe, couleurs, K) : Booléen Si sommet = NombreSommets(graphe) Alors Retourner Vrai FinSi
Pour couleur ← 1 à K Faire Si CouleurAutorisee(sommet, couleur, graphe, couleurs) Alors couleurs[sommet] ← couleur Si Colorier(sommet + 1, graphe, couleurs, K) Alors Retourner Vrai FinSi couleurs[sommet] ← 0 FinSi FinPour
Retourner Faux FinFonction |
Application 3 — Affectation de salles
Pour chaque cours, il faut choisir une salle compatible avec la capacité et l’horaire. L’heuristique consiste à traiter d’abord le cours possédant le moins de salles compatibles. Une salle déjà utilisée au même horaire est retirée des candidats.
Application 4 — Itinéraire avec contraintes
Un voyageur doit atteindre une destination avec une quantité limitée de carburant et sans revisiter certaines villes. L’état inclut la ville courante, le carburant restant et les villes visitées. La mémorisation doit utiliser l’ensemble de ces informations, et pas seulement la ville.
Travaux dirigés
TD 1 — Identifier les composants d’une recherche
Pour chacun des problèmes suivants, préciser l’état, les candidats, le cas de succès, les impasses et l’annulation : permutations, N reines, labyrinthe et somme de sous-ensembles.
TD 2 — Trace d’une permutation
Tracer les appels de l’algorithme de permutations pour [A, B, C]. Indiquer les valeurs du préfixe et du tableau utilisé avant et après chaque annulation.
TD 3 — Arbre des sous-ensembles
Construire l’arbre de recherche pour T = [3, 5, 6] et cible = 8. Marquer les branches qui atteignent la cible et celles qui se terminent sans solution.
TD 4 — N reines
Pour N = 4, représenter les colonnes choisies pour la première solution trouvée lorsque les colonnes sont essayées de gauche à droite. Montrer les retours sur trace nécessaires.
TD 5 — Labyrinthe
Expliquer pourquoi une case visitée doit être marquée. Donner un exemple de boucle infinie obtenue si cette marque est oubliée.
TD 6 — Sudoku
Comparer le choix de la première case vide avec l’heuristique MRV. Expliquer sur une grille partielle pourquoi MRV peut détecter une contradiction plus tôt.
TD 7 — Correction de l’annulation
L’algorithme place une valeur dans un tableau et ajoute cette valeur à un ensemble utilisé, mais lors du retour il efface seulement le tableau. Identifier l’erreur et ses conséquences.
TD 8 — Élagage sûr ou dangereux
Classer chaque règle : sûre, sûre sous condition ou incorrecte. a) arrêter si somme > cible ; b) ignorer les symétries des N reines ; c) abandonner un Sudoku si une case n’a aucun candidat ; d) ne jamais revenir sur une case de labyrinthe déjà visitée.
TD 9 — Complexité
Donner la taille maximale de l’espace de recherche pour n décisions binaires, une permutation de n éléments et une affectation de n variables possédant chacune k valeurs.
TD 10 — Concevoir une recherche
Concevoir un algorithme générant toutes les combinaisons de k éléments parmi n. Préciser les bornes permettant d’abandonner une branche lorsqu’il ne reste pas assez d’éléments.
Corrigés indicatifs des travaux dirigés
Correction du TD 1
Problème | État | Candidats | Succès | Impasse |
|---|---|---|---|---|
| Permutation | Préfixe + utilisés | Éléments non utilisés | Longueur n | Aucun candidat avant longueur n |
| N reines | Colonnes des lignes placées | Colonnes sûres | N lignes traitées | Aucune colonne sûre |
| Labyrinthe | Position + chemin / visites | Voisins accessibles | Sortie atteinte | Aucun voisin valide |
| Sous-ensembles | Indice + somme + choix | Inclure / exclure | Somme cible | Fin du tableau ou borne impossible |
Correction du TD 2
L’ordre des solutions est ABC, ACB, BAC, BCA, CAB, CBA si les candidats sont parcourus dans l’ordre du tableau. Après l’affichage de ABC, C est désélectionné, puis B est désélectionné ; le candidat C est ensuite choisi en deuxième position. Chaque retour restaure exactement la disponibilité du candidat annulé.
Correction du TD 3
ZONE DE PSEUDO-CODE — Arbre partiel pour [3, 5, 6] et cible 8 somme 0 / inclure 3 \ exclure 3 somme 3 somme 0 / +5 \ -5 / +5 \ -5 somme 8 ✓ somme 3 somme 5 somme 0 / \ / \ / \ +6 -6 +6 -6 +6 -6
La branche {3,5} atteint immédiatement la cible. |
Correction du TD 4
Une solution est [1, 3, 0, 2] en indices commençant à 0. En essayant d’abord la colonne 0 pour la première ligne, les lignes suivantes finissent dans une impasse ; la première reine est retirée, puis la colonne 1 est essayée. La restauration concerne la colonne et les deux diagonales.
Correction du TD 5
Sans marque de visite, deux cases voisines A et B peuvent s’appeler mutuellement : A explore B, puis B réexplore A, ce qui répète indéfiniment les appels. La marque de visite empêche de revenir sur la même case dans le chemin courant.
Correction du TD 6
La première case vide peut avoir quatre candidats et créer quatre branches. Une autre case peut n’avoir qu’un seul candidat, ou aucun. MRV choisit cette seconde case : la valeur forcée est appliquée, ou l’impasse est détectée sans créer de branches inutiles.
Correction du TD 7
L’ensemble utilisé doit être restauré en retirant la valeur. Sinon, cette valeur reste interdite dans les branches sœurs. L’algorithme perd alors des solutions valides et peut conclure à tort qu’aucune solution n’existe.
Correction du TD 8
Règle | Classement | Justification |
|---|---|---|
| Somme > cible | Sûre sous condition | Uniquement si toutes les valeurs restantes sont non négatives |
| Ignorer les symétries | Sûre sous condition | Il faut définir l’équivalence et ajuster le comptage |
| Case Sudoku sans candidat | Sûre | Aucune complétion ne peut satisfaire cette case |
| Ne jamais revenir sur une case visitée | Dépend de l’état | Sûr si la position détermine tout ; incorrect avec ressources ou portes |
Correction du TD 9
- Décisions binaires : 2^n feuilles.
- Permutation : n! feuilles.
- n variables avec k valeurs : k^n affectations complètes.
- Ces bornes brutes peuvent être fortement réduites par les contraintes.
Correction du TD 10
ZONE DE PSEUDO-CODE — Combinaisons de k éléments parmi n Procédure Combinaisons(T, debut, k, courant) Si Longueur(courant) = k Alors Afficher(courant) Retourner FinSi
manque ← k - Longueur(courant) Pour i ← debut à Longueur(T) - manque Faire Ajouter(courant, T[i]) Combinaisons(T, i + 1, k, courant) RetirerDernier(courant) FinPour FinProcédure |
La borne Longueur(T) - manque garantit qu’après le choix de i, il restera suffisamment d’éléments pour atteindre une combinaison de taille k.
Travail pratique — Laboratoire de retour sur trace
Objectif
Développer une petite bibliothèque de résolution par retour sur trace et mesurer l’influence des optimisations. Le langage peut être Python, C ou Java, mais l’analyse doit être formulée indépendamment du langage.
Travail demandé
1. Implémenter le schéma générique avec instrumentation du nombre de nœuds explorés.
2. Implémenter les permutations et vérifier que n! solutions sont obtenues pour des valeurs distinctes.
3. Résoudre le problème des N reines et compter les solutions pour plusieurs valeurs de N.
4. Résoudre un labyrinthe en affichant le chemin trouvé et les cases abandonnées.
5. Implémenter le Sudoku 4 × 4, puis comparer première case vide et MRV.
6. Résoudre la somme de sous-ensembles avec et sans bornes.
7. Mesurer le temps, le nombre d’appels et la profondeur maximale.
8. Rédiger une conclusion expliquant quelle optimisation apporte le meilleur gain selon le problème.
Instrumentation conseillée
Mesure | Description |
|---|---|
| nœuds | Nombre d’états visités |
| choix_testes | Nombre total de candidats examinés |
| elagages | Nombre de branches rejetées sans récursion |
| profondeur_max | Plus grand nombre de décisions simultanées |
| solutions | Nombre de solutions complètes |
| temps | Durée d’exécution dans les mêmes conditions |
Jeux d’essai minimaux
Module | Cas à tester | Résultat attendu |
|---|---|---|
| Permutations | n = 0, 1, 3 ; valeurs dupliquées | 1, 1, 6 solutions distinctes selon la convention |
| N reines | N = 1, 2, 3, 4 | 1, 0, 0, 2 solutions |
| Labyrinthe | sortie directe, impasse, plusieurs chemins | succès, échec, un chemin valide |
| Sudoku | grille résolue, grille valide, grille contradictoire | succès, solution, échec immédiat |
| Sous-ensembles | cible 0, cible atteignable, impossible | ensemble vide, solution, Faux |
Grille d’évaluation proposée
Critère | Points |
|---|---|
| Correction des algorithmes et restauration des états | 6 |
| Qualité des tests d’admissibilité et des élagages | 4 |
| Instrumentation et comparaison expérimentale | 3 |
| Analyse de complexité et interprétation | 3 |
| Lisibilité, modularité et documentation | 2 |
| Jeux de tests et gestion des cas particuliers | 2 |
Erreurs fréquentes et bonnes pratiques
Erreur fréquente | Conséquence | Bonne pratique |
|---|---|---|
| Oublier le cas de base | Récursion infinie ou aucune solution reconnue | Définir succès et échec avant les choix |
| Annulation incomplète | Contamination des branches sœurs | Restaurer toutes les structures modifiées |
| Tester trop tard | Exploration inutile de sous-arbres impossibles | Vérifier les contraintes dès qu’elles deviennent évaluables |
| Élagage non prouvé | Perte de solutions valides | Énoncer la condition de sûreté |
| État mal mémorisé | Réutilisation de résultats incorrects | Encoder toutes les informations futures pertinentes |
| Copier tout l’état | Coût mémoire et temps excessifs | Modifier puis annuler lorsque cela reste simple |
| Confondre chemin courant et visité global | Solutions manquées dans certains graphes | Adapter la marque au modèle d’état |
| Afficher sans copier | Toutes les solutions semblent identiques | Copier la solution avant de l’enregistrer |
Synthèse du chapitre
- Le retour sur trace explore en profondeur un arbre de décisions.
- Une solution est construite progressivement à partir de choix admissibles.
- Chaque choix doit pouvoir être annulé afin de restaurer exactement l’état précédent.
- Une impasse déclenche le retour vers le dernier nœud possédant un candidat non exploré.
- L’élagage correct supprime les branches incapables de produire une solution pertinente.
- L’ordre des choix, la propagation et la mémorisation peuvent réduire fortement le temps moyen.
- Le pire cas reste souvent exponentiel ou factoriel.
- La qualité de la représentation de l’état conditionne la correction et les performances.
| Méthode en une phrase |
| Choisir un candidat, vérifier qu’il reste possible, appliquer le choix, poursuivre récursivement, puis annuler le choix avant d’essayer le candidat suivant. |
Glossaire
Terme | Définition |
|---|---|
| Retour sur trace | Méthode explorant des choix et revenant en arrière après un échec |
| État | Représentation des décisions déjà prises et des informations utiles |
| Solution partielle | État respectant les contraintes mais encore incomplet |
| Candidat | Choix pouvant prolonger l’état courant |
| Impasse | État non complet ne pouvant mener à aucune solution |
| Annulation | Restauration de l’état précédant un choix |
| Arbre de recherche | Arbre dont les nœuds sont des états et les arêtes des décisions |
| Élagage | Suppression justifiée d’un sous-arbre inutile |
| Facteur de branchement | Nombre moyen de choix disponibles par nœud |
| Propagation | Déduction de conséquences réduisant les domaines futurs |
| Mémoïsation | Stockage du résultat d’états déjà rencontrés |
| MRV | Heuristique choisissant la variable ayant le moins de valeurs restantes |
| Branch and bound | Retour sur trace avec bornes pour un problème d’optimisation |
| Symétrie | Transformation produisant un état équivalent à un autre |
Auto-évaluation
Je peux… | Oui | À revoir |
|---|---|---|
| définir le retour sur trace et expliquer le rôle de l’annulation | ☐ | ☐ |
| identifier l’état, les candidats, le succès et les impasses | ☐ | ☐ |
| dessiner un arbre de recherche simple | ☐ | ☐ |
| écrire un pseudo-code générique correct | ☐ | ☐ |
| résoudre un problème de permutations | ☐ | ☐ |
| expliquer les contraintes des N reines | ☐ | ☐ |
| marquer et restaurer un chemin dans un labyrinthe | ☐ | ☐ |
| appliquer MRV à un Sudoku simplifié | ☐ | ☐ |
| concevoir des bornes pour une somme de sous-ensembles | ☐ | ☐ |
| justifier qu’un élagage est sûr | ☐ | ☐ |
| distinguer heuristique d’ordre et règle d’élagage | ☐ | ☐ |
| analyser la complexité brute d’un espace de recherche | ☐ | ☐ |
| Conclusion |
| Le retour sur trace transforme une explosion combinatoire aveugle en exploration structurée. Il ne supprime pas toujours la difficulté intrinsèque du problème, mais il permet d’exploiter immédiatement les contraintes, de restaurer les décisions et de concentrer le calcul sur les branches encore prometteuses. |