Objectifs du chapitre
À la fin de ce chapitre, vous serez capable de:
- passer d'un problème d'optimisation à sa version décisionnelle et retour, et dire pourquoi la théorie se construit sur la seconde;
- mesurer la taille d'une instance par la longueur de son codage, et reconnaître un algorithme pseudo-polynomial — celui du sac à dos au chapitre 10 en est un;
- définir et définir par les certificats et le vérificateur, exhiber un certificat pour chacun des problèmes du catalogue, et démontrer ;
- écrire une réduction polynomiale , énoncer sans vous tromper de sens ce qu'elle permet de conclure, et l'appliquer pour transporter la -complétude;
- construire en entier la réduction de 3-SAT vers la couverture par sommets et en démontrer les deux sens;
- choisir une stratégie face à un problème -complet — exact avec élagage, complexité paramétrée, heuristique, approximation — et démontrer la garantie d'un algorithme 2-approché.
La question que dix chapitres ont laissée ouverte
Depuis le chapitre 1, la démarche de ce cours est invariable: on pose un problème, on conçoit un algorithme, on compte ses opérations et on range le compte dans une classe de croissance. Le tri par insertion était en comparaisons dans le pire des cas, le tri fusion en , et le chapitre 3 a même démontré que ce second résultat est optimal: aucun tri par comparaisons ne peut faire mieux que . Dijkstra, au chapitre 7, calcule les plus courts chemins en ; Kruskal, au chapitre 8, un arbre couvrant minimal en . Chaque fois, la question «existe-t-il un algorithme efficace?» a reçu une réponse, et cette réponse était oui.
Le chapitre 10 a été le premier à hésiter. Le sac à dos 0/1 y est résolu par une table de programmation dynamique en opérations, où est la capacité. Sur l'instance du cours — capacité , quatre objets, optimum 13 — la table se remplit en un clin d'œil. Sur une instance où les poids sont des entiers de quarante bits, la même table compte cases, soit pour cent objets environ cases, alors que l'instance elle-même tient en quatre mille bits. Quelque chose ne va pas dans notre manière de compter, et ce chapitre commence par le dire.
Il y a plus dérangeant. Pour certains problèmes qui ressemblent beaucoup à ceux que nous avons résolus, personne n'a jamais trouvé d'algorithme polynomial. Trouver un arbre couvrant minimal est facile; trouver un cycle hamiltonien, c'est-à-dire un circuit qui passe une fois et une seule par chaque sommet, résiste depuis soixante ans. Trouver un plus court chemin est facile; trouver la plus courte tournée qui visite toutes les villes résiste tout autant. Décider si un graphe est connexe est facile; décider s'il possède une clique de taille donnée résiste.
Ce chapitre est la théorie de cette résistance. Elle ne dit pas — et c'est le point le plus important du chapitre — que ces problèmes sont insolubles. Elle dit quelque chose de plus subtil et de plus utile: ils sont tous le même problème. Un algorithme polynomial pour l'un en donnerait un pour tous les autres. Cette solidarité, découverte au début des années 1970, transforme une collection d'échecs individuels en une question unique, ouverte, et dotée depuis l'an 2000 d'une récompense d'un million de dollars.
Décider plutôt qu'optimiser
Trois formes d'un même problème
Prenons la couverture par sommets, qui sera le fil de tout le chapitre.
Ce problème se pose sous trois formes, et la distinction n'est pas un raffinement de logicien.
- Forme d'optimisation: étant donné , calculer .
- Forme de recherche: étant donné , produire une couverture de taille .
- Forme de décision: étant donnés et un entier , répondre par oui ou non à la question « possède-t-il une couverture par sommets de taille au plus ?».
Toute la théorie qui suit se bâtit sur la troisième. La raison est technique et elle est solide: un problème de décision est un ensemble de mots — l'ensemble des codages d'instances dont la réponse est oui — et les ensembles se comparent, s'intersectent, se réduisent les uns aux autres. Une fonction qui rend un entier ou un sous-ensemble ne se prête pas à ce traitement. On perd en apparence de la généralité; la proposition suivante montre qu'on n'en perd aucune.
Démonstration. L'implication est immédiate — on produit une couverture minimum et on compte ses éléments — et l'est tout autant: on calcule et on le compare à . Reste , qui est la seule direction instructive.
Supposons donc disposer d'un sous-programme polynomial qui répond à la question de décision. Notons .
Étape 1: trouver la valeur optimale. La fonction est croissante au sens où elle vaut non jusqu'à un certain seuil puis oui après: si une couverture de taille existe, toute sur-ensemble de taille en est encore une. On peut donc dichotomiser sur exactement comme au chapitre 2, et obtenir en appels.
Étape 2: reconstruire une couverture. Posons et , et répétons tant qu'il reste une arête. Pour chaque sommet du graphe courant, notons le graphe obtenu en supprimant et toutes les arêtes qui le touchent, et demandons .
Cette question est exactement « possède-t-il une couverture de taille contenant ?». En effet, si couvre , contient et vérifie , alors couvre et compte au plus éléments; réciproquement, si couvre avec , alors couvre — toute arête supprimée touchait — et compte au plus éléments.
Comme possède une couverture de taille et que cette couverture est non vide dès qu'il reste une arête, au moins un sommet reçoit la réponse oui. On prend le premier, on l'ajoute à , on remplace par et par , et l'invariant «le graphe courant possède une couverture de taille » est préservé. Le processus s'arrête quand il n'y a plus d'arête, et est alors une couverture de de taille au plus , donc exactement .
Coût. Chaque tour supprime un sommet, il y a donc au plus tours, et chaque tour fait au plus appels: au total appels à , plus la dichotomie. Un nombre polynomial d'appels à un sous-programme polynomial, sur des instances qui ne grossissent pas, donne un algorithme polynomial.
Cette technique porte un nom, l'auto-réductibilité: on interroge le sous-programme de décision sur des instances plus petites du même problème pour reconstruire la solution. Retenez-la, car elle a une conséquence spectaculaire que nous énoncerons plus loin: si quelqu'un trouvait un jour un algorithme polynomial répondant simplement oui ou non à la question «cette formule est-elle satisfaisable?», on saurait immédiatement construire l'affectation satisfaisante en temps polynomial.
Pourquoi la théorie de la NP-complétude est-elle construite sur les problèmes de décision plutôt que sur les problèmes d'optimisation?
La taille d'une instance: le piège du codage
La taille est la longueur de l'écriture
Le chapitre 1 avait posé la règle et annoncé qu'on y reviendrait ici: la taille d'une instance est le nombre de bits qu'il faut pour l'écrire, pas la valeur des nombres qu'elle contient.
Cette convention est ce qui donne un sens à «temps polynomial». Un algorithme est polynomial si son coût est borné par un polynôme en . Elle a une conséquence désagréable pour le chapitre 10.
Une instance de sac à dos comporte 60 objets et une capacité codée sur 30 bits, donc au plus . Combien de cases, en milliards, la table de programmation dynamique du chapitre 10 compte-t-elle au maximum? Donnez le produit exprimé en milliards.
La classe P
Deux remarques sur cette définition, toutes deux importantes.
D'abord, elle est robuste. Changer de modèle de calcul raisonnable — machine de Turing, machine RAM, langage de programmation quelconque — ne modifie le coût que d'un facteur polynomial, donc ne modifie pas . Changer de codage raisonnable non plus. C'est cette robustesse qui fait de «polynomial» une notion mathématique et non une convention d'ingénieur, et c'est ce qu'on appelle parfois la thèse de Cobham–Edmonds: «calculable efficacement» signifie «calculable en temps polynomial».
Ensuite, elle est grossière, et volontairement. Un algorithme en est polynomial et parfaitement inutilisable; un algorithme en est exponentiel et praticable jusqu'à des tailles considérables. La frontière polynomial / exponentiel n'est donc pas la frontière praticable / impraticable. Elle est choisie pour une autre raison: elle est stable — stable par composition, par itération polynomiale, par changement de modèle — et cette stabilité est ce qui permet de démontrer des théorèmes. Le fait empirique, constaté depuis soixante ans, est qu'un problème naturel qui tombe dans y tombe presque toujours avec un exposant petit, 1, 2 ou 3.
Tout ce cours, jusqu'ici, a peuplé : la recherche dichotomique, les tris du chapitre 3, les parcours du chapitre 6, Dijkstra et Bellman–Ford au chapitre 7, Kruskal et Prim au chapitre 8, Huffman au chapitre 9, la sous-séquence commune et la distance d'édition au chapitre 10. Sous forme décisionnelle — «existe-t-il un arbre couvrant de poids au plus ?», «la distance d'édition est-elle inférieure ou égale à ?» — ce sont tous des problèmes de .
La classe NP: vérifier plutôt que résoudre
Le certificat et le vérificateur
Voici l'idée centrale du chapitre, et elle est étonnamment simple. Pour beaucoup de problèmes difficiles, trouver une solution semble hors de portée, mais vérifier une solution qu'on vous tend est facile. Trouver un cycle hamiltonien dans un graphe à mille sommets, personne ne sait le faire vite; si on vous donne l'ordre des mille sommets, vérifier que c'est bien un cycle qui les visite tous une fois prend mille lectures d'adjacence.
C'est cette asymétrie que la classe formalise. Nous la définissons par les certificats, et non par les machines non déterministes dont elle tire son nom — les deux définitions sont équivalentes, et celle-ci se manipule sans avoir à introduire un modèle de machine.
Lisez la double implication dans les deux sens, car les deux comptent et l'oubli du second est une erreur fréquente.
- Complétude (de gauche à droite): si la réponse est oui, il existe un certificat que le vérificateur accepte. Il existe — on ne dit pas comment le trouver, et c'est tout le sujet du chapitre.
- Correction (de droite à gauche): si la réponse est non, aucun certificat, aussi astucieux soit-il, n'est accepté. Un vérificateur laxiste, qui accepterait un mauvais certificat sur une instance négative, ne définit rien.
Remarquez enfin l'asymétrie de la définition: elle donne une preuve courte du oui, jamais du non. Rien, dans «ce graphe n'a pas de cycle hamiltonien», ne se certifie en temps polynomial de manière évidente — et savoir si c'est possible est une autre question ouverte, celle de l'égalité entre et .
Démonstration. Soit , et soit un algorithme qui décide en temps . Construisons un vérificateur ainsi: sur l'entrée , ignore , exécute sur et renvoie la réponse de .
Vérifions les deux sens de la définition. Si est positive, alors répond oui, donc répond oui pour n'importe quel , en particulier pour le mot vide, dont la longueur est bien bornée par tout polynôme. Si est négative, répond non, donc répond non pour tout : aucun certificat n'est accepté. Enfin s'exécute en temps , qui est polynomial. Donc .
L'autre inclusion, , est la question ouverte. On sait en revanche borner par le haut, et cette borne mérite d'être énoncée parce qu'elle rassure: aucun problème de n'est insoluble.
Démonstration. Soit un vérificateur polynomial pour et le polynôme bornant la longueur des certificats. Sur une instance de taille , énumérons tous les mots de longueur au plus — il y en a sur l'alphabet binaire — et exécutons sur chacun. Par la complétude, si est positive l'un de ces mots est accepté; par la correction, si est négative aucun ne l'est. L'algorithme répond donc correctement, et son coût est le produit du nombre de certificats par le coût de , soit .
On a donc la chaîne , où est la classe des problèmes résolubles en temps . Et l'on sait, par le théorème de hiérarchie en temps, que : il existe des problèmes résolubles en temps exponentiel et démontrablement pas en temps polynomial. Il en résulte un fait souvent ignoré: On ne sait pas laquelle.
Deux mots sur la région intermédiaire, parce qu'elle est régulièrement mal citée. Le théorème de Ladner (1975) affirme que si , alors il existe dans des problèmes qui ne sont ni dans ni -complets. Il ne dit pas lesquels: il les construit artificiellement par diagonalisation. Les deux candidats naturels ont chacun un argument sérieux et aucune preuve. La factorisation (sous forme décisionnelle: « a-t-il un facteur non trivial inférieur à ?») appartient à et aussi à — un certificat de non-existence est la décomposition complète de en facteurs premiers, accompagnée d'un certificat de primalité pour chacun —, or si un problème -complet était dans , on aurait , ce que personne ne croit. L', lui, dispose depuis 2015 d'un algorithme en temps quasi-polynomial dû à László Babai, ce qui rend sa -complétude très improbable sans la réfuter.
Cette formule a cinq variables et neuf clauses; une seule des 32 affectations la satisfait. Faites glisser le premier curseur pour les essayer une par une: vous verrez vingt-six affectations satisfaire huit clauses sur neuf, ce qui ne vaut rien — «presque» n'est pas une réponse. Le second curseur ne change pas la formule affichée: il dit combien d'affectations il faudrait essayer si elle avait n variables au lieu de cinq. Le dernier affichage, lui, ne bouge jamais: vérifier une affectation coûte toujours vingt-sept lectures de littéral. C'est tout l'écart entre chercher et vérifier.
L'explorateur ci-dessus tient en une phrase tout ce que la section vient de dire. La formule a cinq variables et neuf clauses, et une seule des affectations la satisfait — c'est l'affectation numéro 14, , , , , . Balayez le premier curseur: vous rencontrerez vingt-six affectations qui satisfont clauses sur neuf, et qui ne valent rien, parce qu'une clause vide suffit à tout invalider. Pendant ce temps, le dernier affichage ne bouge jamais: vérifier une affectation coûte toujours vingt-sept lectures de littéral. C'est cette invariance qui définit , et c'est l'autre curseur qui dit le prix de la recherche: à cinquante variables, il faudrait essayer affectations pour la même vérification à vingt-sept lectures.
Écrivez le solveur SAT le plus bête possible: celui qui essaie les 32 affectations, les unes après les autres. Le programme doit afficher l'affectation satisfaisante sous forme de cinq chiffres binaires (x1 en tête), une espace, puis le nombre d'affectations examinées. Comme on veut aussi savoir s'il y en a plusieurs, n'arrêtez pas le balayage à la première trouvée.
Le contraste de tout le chapitre, en un programme. Écrivez le vérificateur de couverture par sommets: il reçoit la liste des arêtes, un certificat et un entier k, et il renvoie le couple (le certificat est-il une couverture de taille au plus k, nombre d'arêtes lues). Lisez toutes les arêtes, sans sortie anticipée, pour que le compte soit le même dans les deux cas. Le programme affiche une ligne par certificat: le certificat, oui ou non, puis le nombre d'arêtes lues.
Réductions polynomiales
Traduire un problème en un autre
Deux précisions sur la définition. La condition 2 est une équivalence, pas une implication: une «réduction» qui ne démontrerait qu'un sens ne réduit rien, et c'est l'erreur que la section suivante s'emploiera à ne pas commettre. La condition 1 entraîne au passage que est polynomial en , puisqu'un algorithme qui tourne en temps ne peut pas écrire plus de symboles.
Démonstration. Soit la réduction, calculable en temps pour un polynôme .
1. Supposons , décidé par un algorithme de coût . Voici un algorithme pour : sur l'entrée , calculer , puis exécuter et renvoyer sa réponse. Il est correct par la condition 2, dans les deux sens: si est positive alors l'est, donc répond oui; si est négative alors l'est aussi, donc répond non. Son coût est , et comme , ce coût est majoré par . La composée de deux polynômes est un polynôme, donc .
2. Même construction avec le vérificateur: si vérifie en temps polynomial, alors vérifie en temps polynomial. La complétude et la correction se transportent par l'équivalence de la condition 2.
3. C'est la contraposée du point 1: si était dans , y serait, contrairement à l'hypothèse.
Transitivité. Si réduit à en temps et réduit à en temps , alors réduit à : l'équivalence se compose, et le coût est polynomial.
Le sens, et rien que le sens
Remettez dans l'ordre les étapes d'une démonstration que le problème est -complet.
Glissez les éléments pour les mettre dans le bon ordre
- Décrire une transformation qui envoie toute instance de sur une instance de
- Montrer que appartient à , en exhibant un certificat et son vérificateur polynomial
- Choisir un problème déjà connu comme -complet
- Vérifier que se calcule en temps polynomial
- Démontrer la réciproque: si de l'instance est positive, alors l'instance de départ l'était
- Démontrer que si l'instance de est positive, alors de cette instance est positive
- Conclure que , donc que est -difficile, donc -complet
NP-difficile, NP-complet, et le théorème de Cook–Levin
La définition a une conséquence immédiate, et c'est elle qui donne toute sa force à la notion.
Démonstration. Supposons et soit quelconque. Comme est -difficile, on a ; par le point 1 du théorème 11.4, . Ceci valant pour tout , on obtient , et l'inclusion inverse est le théorème 11.2: donc . La seconde affirmation est la contraposée de la première.
Reste à savoir si de tels problèmes existent. Rien, dans la définition, ne le garantit: elle exige une réduction depuis tous les problèmes de , c'est-à-dire depuis une infinité de problèmes dont on ne sait rien d'autre que l'existence d'un vérificateur. C'est ce verrou que le théorème suivant a fait sauter.
Nous admettons ce théorème, démontré indépendamment par Stephen Cook en 1971 et Leonid Levin en 1973, et voici précisément pourquoi. Sa démonstration prend un problème quelconque, avec son vérificateur polynomial , et construit une formule booléenne dont les affectations satisfaisantes sont exactement les exécutions acceptantes de sur l'instance donnée. Pour cela il faut disposer d'un modèle de calcul formel — une machine de Turing, avec ses états, son ruban et sa fonction de transition — et coder, par des variables booléennes, le contenu de chaque case du ruban à chaque instant, puis exprimer par des clauses le fait que chaque configuration succède légalement à la précédente. La machine RAM du chapitre 1 ne se prête pas à cet encodage, et introduire la machine de Turing prendrait un chapitre entier: ce travail appartient à un cours de théorie de la complexité, pas à un cours d'algorithmique. Ce que nous retenons ici, c'est l'énoncé, qui se manipule parfaitement sans sa démonstration.
Une fois SAT tenu pour -complet, tout le reste s'obtient par réductions, grâce au lemme de transport suivant.
Démonstration. Soit quelconque. Comme est -difficile, ; par hypothèse ; par transitivité de (théorème 11.4), . Ceci valant pour tout , est -difficile. La seconde affirmation est alors la définition de la -complétude.
C'est exactement ce programme que Richard Karp a exécuté en 1972, en établissant la -complétude de vingt et un problèmes classiques à partir de SAT — dont la couverture par sommets, la clique, l'ensemble indépendant, le cycle hamiltonien, la partition et le sac à dos. Depuis, le catalogue s'est étendu à des milliers de problèmes, dans tous les domaines: ordonnancement, découpe, placement, repliement de protéines, vérification de circuits.
On démontre une réduction polynomiale de 3-SAT vers un nouveau problème X, et l'on sait par ailleurs que X appartient à NP. Qu'a-t-on établi?
Une réduction en entier: de 3-SAT à la couverture par sommets
Nous allons maintenant faire, en détail et sans rien admettre, ce que la section précédente a décrit en général. L'objectif est double: obtenir le résultat, et surtout voir à quoi ressemble la démonstration des deux sens, puisque c'est là que se juge une réduction.
La construction
Soit une formule 3-SAT à variables et clauses , chaque clause étant une disjonction de trois littéraux portant sur trois variables distinctes. On construit un graphe et un entier ainsi.
Les modules de variable. Pour chaque variable , deux sommets étiquetés et , reliés par une arête. Cela fait sommets et arêtes.
Les modules de clause. Pour chaque clause , trois sommets formant un . Cela fait sommets et arêtes.
Les arêtes de liaison. Pour chaque clause et chaque position , une arête entre le sommet de triangle et le sommet de littéral correspondant à . Cela fait arêtes.
Le seuil. On pose .
Au total, possède sommets et arêtes, et la construction se fait en parcourant une fois la formule: elle est clairement calculable en temps linéaire en la taille de , donc polynomial.
La démonstration, dans les deux sens
Commençons par le lemme de comptage, qui sert aux deux sens et qui explique le choix du seuil.
Démonstration. Les arêtes de variable et les triangles forment sous-graphes deux à deux disjoints: aucun sommet n'appartient à deux d'entre eux, puisqu'un sommet de littéral n'est dans aucun triangle et réciproquement.
Soit une couverture. Pour chaque , l'arête doit être couverte, donc contient au moins un de ses deux sommets. Pour chaque , le triangle a trois arêtes; si n'en contenait qu'un sommet au plus, l'arête joignant les deux autres ne serait pas couverte. Donc contient au moins deux sommets de chaque triangle.
Ces contributions portent sur des ensembles disjoints de sommets, donc elles s'additionnent:
Si , aucune des minorations ne peut être stricte et ne peut contenir aucun sommet supplémentaire: il y a exactement un sommet par module de variable, exactement deux par triangle, et rien d'autre.
Démonstration. Nous démontrons séparément les deux implications; aucune ne découle de l'autre.
Sens direct: satisfaisable couverture de taille . Soit une affectation satisfaisant . Construisons ainsi.
Pour chaque variable , mettons dans le sommet du littéral vrai sous : le sommet si est vrai, le sommet sinon. Cela fait sommets.
Pour chaque clause : comme satisfait , elle satisfait , donc au moins un littéral de est vrai sous ; choisissons-en un et mettons dans les sommets du triangle, pour . Cela fait sommets, et au total .
Vérifions que couvre les trois familles d'arêtes.
- Les arêtes de variable: chacune a exactement un de ses deux sommets dans , par construction. Couverte.
- Les arêtes de triangle: dans chaque triangle, un seul sommet est hors de , donc toute arête du triangle a au moins une extrémité dans . Couverte.
- Les arêtes de liaison: soit une telle arête. Si , le sommet est dans et l'arête est couverte. Si , le sommet de triangle est hors de , mais alors est sous , donc le sommet de littéral a été mis dans à la première étape. Couverte.
Donc est une couverture de taille .
Sens réciproque: couverture de taille au plus satisfaisable. Soit une couverture avec . Le théorème 11.8 donne , donc exactement, et contient exactement un sommet de chaque module de variable et exactement deux sommets de chaque triangle.
Définissons l'affectation par: est vrai si le sommet appartient à , faux si c'est le sommet qui y appartient. Cette définition est licite et non ambiguë précisément parce que contient exactement un des deux.
Montrons que satisfait chaque clause . Dans le triangle de , exactement un sommet est hors de ; notons-le et soit le littéral qu'il représente. L'arête de liaison appartient à et doit être couverte par ; comme , c'est . Par définition de , le littéral est donc vrai sous . Or est l'un des trois littéraux de : la clause est satisfaite.
Ceci vaut pour toute clause, donc satisfait .
Conclusion. La transformation se calcule en temps polynomial et l'équivalence est établie dans les deux sens: c'est une réduction, donc 3-SAT couverture par sommets. Comme 3-SAT est -difficile (théorème 11.6) et que la couverture par sommets est dans (exemple 11.2), le théorème 11.7 conclut: la couverture par sommets est -complète.
On applique la réduction du théorème 11.9 à une formule 3-SAT ayant 6 variables et 7 clauses. Combien le graphe construit compte-t-il de sommets?
Que faire quand votre problème est NP-complet
Vous avez démontré, ou trouvé dans le catalogue, que le problème posé par votre application est -complet. Cette conclusion n'est pas la fin du travail: c'est le moment où l'on cesse de chercher l'algorithme polynomial exact — et c'est déjà beaucoup, parce qu'on ne le cherche plus en vain — pour choisir l'un des quatre chemins qui restent.
Exact, mais exponentiel avec élagage
Le premier chemin garde l'exactitude et paie le prix. La force brute est rarement la bonne façon de le faire: on lui préfère une exploration arborescente qui élague, c'est-à-dire qui abandonne une branche dès qu'elle ne peut plus contenir de solution meilleure que la meilleure déjà connue. C'est la séparation et évaluation (branch and bound), et sa qualité tient entièrement à celle de la borne utilisée pour élaguer.
La programmation dynamique du chapitre 10 offre parfois un gain spectaculaire sur la force brute pure sans sortir de l'exponentiel. Pour le voyageur de commerce, l'énumération des tournées coûte , soit pour vingt villes; l'algorithme de Held et Karp, qui tabule le meilleur chemin pour chaque paire (sous-ensemble visité, ville courante), coûte , soit environ pour les mêmes vingt villes. Huit ordres de grandeur gagnés — et l'algorithme reste exponentiel, donc impraticable vers quarante villes.
Complexité paramétrée: isoler ce qui est petit
Le deuxième chemin consiste à remarquer que la difficulté ne dépend pas seulement de , mais souvent d'un paramètre qui, dans votre application, reste petit. On cherche alors un algorithme en , où toute l'explosion est confinée dans : on dit que le problème est FPT pour ce paramètre.
Démonstration. L'algorithme est une recherche arborescente bornée. Sur l'entrée : s'il n'y a plus d'arête, répondre oui — l'ensemble vide convient. Si et qu'il reste une arête, répondre non. Sinon, choisir une arête quelconque et répondre oui si l'un au moins des deux appels récursifs ou répond oui.
Correction. Toute couverture de doit contenir ou , puisque l'arête doit être couverte. Si elle contient , alors en lui retirant on obtient une couverture de de taille au plus , et réciproquement, ajouter à une couverture de de taille couvre , puisque toute arête supprimée touchait . Le même raisonnement vaut pour . L'algorithme explore donc exactement les deux cas possibles, et les cas de base sont corrects.
Coût. L'arbre des appels est binaire et de profondeur au plus , puisque décroît d'une unité à chaque descente: il compte donc au plus nœuds. Chaque nœud effectue le choix d'une arête et la suppression d'un sommet, en . D'où le coût annoncé.
Lisez ce résultat avec le tableau du chapitre 1. Pour sommets, arêtes et , le coût vaut environ opérations: c'est au bord du praticable, sur un graphe où la force brute aurait demandé sous-ensembles, un nombre à quarante et un chiffres. Le paramètre a tout changé — et il ne change rien du tout si vaut 200.
Heuristiques: renoncer à la garantie
Le troisième chemin renonce à toute garantie et mise sur le fait que vos instances ne sont pas les pires. C'est le domaine des solveurs SAT modernes, de la recherche locale, du recuit simulé, des métaheuristiques. Ces méthodes n'offrent aucune borne sur la qualité de ce qu'elles rendent ni sur le temps qu'elles mettent, et elles fonctionnent remarquablement bien sur d'immenses classes d'instances réelles.
Il faut les juger pour ce qu'elles sont. Une heuristique qui donne de bons résultats sur trois cents instances de votre banc d'essai est un outil légitime et documenté; ce n'est pas un théorème, et le chapitre 9 avait déjà posé la règle à propos des algorithmes gloutons: un algorithme qui marche sur trois exemples n'est pas démontré. La différence entre une heuristique et la section suivante tient en un mot: la garantie.
Approximation: renoncer à l'optimum, garder une garantie
Le quatrième chemin est le plus satisfaisant intellectuellement. On renonce à l'optimum, mais on démontre de combien on peut s'en écarter — dans le pire des cas, sur toutes les instances.
Insistons sur le mot toute. Un algorithme 2-approché ne promet pas d'être deux fois moins bon en moyenne: il promet de ne jamais dépasser le double de l'optimum, sur aucune instance, y compris celle qu'un adversaire aurait construite contre lui. C'est un énoncé de pire cas, de la même famille que les garanties du chapitre 1, et c'est ce qui en fait un théorème plutôt qu'une observation.
Remarquez aussi le tour de force logique: la démonstration doit comparer ce que l'algorithme rend à un optimum qu'elle ne sait pas calculer. Elle y parvient en minorant l'optimum par une quantité que l'algorithme, lui, connaît. Voyons ce mécanisme sur l'exemple canonique.
Le 2-approché de la couverture par sommets
L'algorithme tient en six lignes et il est d'une naïveté déconcertante.
def couverture_par_couplage(aretes):
"""Rend une couverture par sommets dont la taille est au plus deux fois l'optimum."""
pris = set()
couplage = []
for u, v in aretes:
if u not in pris and v not in pris:
couplage.append((u, v)) # arete ajoutee au couplage
pris.add(u)
pris.add(v) # ses DEUX extremites entrent dans la couverture
return couplage, sorted(pris)
Le coût est immédiat: une passe sur les arêtes, chacune avec deux tests d'appartenance en amorti (chapitre 4), donc opérations. L'algorithme construit un couplage maximal — un ensemble d'arêtes deux à deux disjointes auquel on ne peut plus rien ajouter — et rend les deux extrémités de chacune de ses arêtes.
La première réaction est en général l'incrédulité: prendre les deux extrémités semble un gaspillage évident, puisqu'une seule suffirait à couvrir l'arête. C'est vrai, et c'est précisément ce qui rend la garantie démontrable.
Démonstration. 1. est une couverture. Raisonnons par l'absurde et supposons qu'une arête ne soit couverte par aucun sommet de : ni ni n'appartient à . Comme est exactement l'ensemble des extrémités des arêtes de , cela signifie que ni ni n'est l'extrémité d'une arête de . L'arête est donc disjointe de toutes les arêtes de , et est encore un couplage — ce qui contredit la de . Donc toute arête est couverte.
2. . Soit une couverture minimum, de taille . Chaque arête de doit être couverte, donc contient au moins une de ses deux extrémités; choisissons-en une et notons ce sommet, pour chaque . L'application ainsi définie est : si deux arêtes distinctes de donnaient le même sommet , ce sommet appartiendrait aux deux arêtes, qui ne seraient donc pas disjointes — or les arêtes d'un couplage le sont. Une injection de dans donne .
3. Les arêtes de étant deux à deux disjointes, elles apportent sommets distincts, donc . En combinant avec le point 2:
Comme est une couverture (point 1) et que l'algorithme s'exécute en , il est bien 2-approché.
Reprenez le raisonnement et voyez où passe l'astuce. L'algorithme ne connaît pas — le calculer est précisément le problème -difficile qu'on renonce à résoudre. Mais il connaît , et le point 2 établit que ce nombre est une minoration de . On compare donc le résultat, , à une quantité connue, , elle-même sous l'optimum. C'est le schéma de presque toutes les démonstrations d'approximation: trouver une minoration calculable de l'optimum, et borner le résultat par un multiple de cette minoration.
Implémentez l'algorithme 2-approché et confrontez-le à l'optimum. Complétez la fonction pour qu'elle construise le couplage maximal en parcourant les arêtes dans l'ordre donné, puis rende le couplage et la liste triée des extrémités. Le programme affiche la couverture, la taille du couplage, la taille de la couverture, et le rapport à l'optimum arrondi à deux décimales.
Un dividende du chapitre 8: le voyageur de commerce métrique
Le plus joli exemple d'approximation de ce chapitre ne demande aucun outil nouveau: il utilise l'arbre couvrant minimal du chapitre 8.
Démonstration. Trois étapes, dont la première est la minoration calculable dont nous avons parlé.
1. . Soit une tournée optimale, de coût . Retirons-lui une arête quelconque: il reste un chemin qui passe par toutes les villes, donc un arbre couvrant, dont le poids vaut moins celui de l'arête retirée, donc au plus puisque les distances sont positives. Comme est un arbre couvrant minimal, est inférieur ou égal au poids de cet arbre-là, donc .
2. La marche qui double l'arbre coûte . Parcourons en profondeur depuis une racine quelconque et écrivons la suite des sommets rencontrés, en notant chaque sommet à l'aller et au retour. Cette marche fermée emprunte chaque arête de exactement deux fois — une fois dans chaque sens — et visite tous les sommets; son coût vaut donc exactement .
3. Les raccourcis ne coûtent rien. La marche repasse par des sommets déjà vus. Supprimons de la suite toutes les occurrences répétées, ne gardant que la première: on obtient exactement l'ordre préfixe, c'est-à-dire la tournée . Chaque suppression remplace un trajet par le trajet direct , et l'inégalité triangulaire donne : Par récurrence sur le nombre de suppressions, .
En combinant avec l'étape 1, . Le calcul de par Kruskal coûte et le parcours préfixe : l'ensemble est polynomial.
Le voyageur métrique a mieux que 2: l'algorithme de Christofides (1976) atteint le rapport en remplaçant le doublement de l'arbre par l'ajout d'un couplage parfait de poids minimum sur les sommets de degré impair. Ce a tenu quarante-quatre ans avant d'être battu, en 2020, d'une quantité infime mais non nulle — le genre de résultat qui dit surtout à quel point la question est dure.
Ce que l'approximation ne peut pas faire
Le tableau ne serait pas honnête s'il s'arrêtait aux bonnes nouvelles. Trois remarques, dans l'ordre croissant de sévérité.
Certains problèmes s'approchent aussi bien qu'on veut. Le sac à dos du chapitre 10 admet un schéma d'approximation entièrement polynomial: pour tout , un algorithme polynomial en et en rend une sélection de valeur au moins . On l'obtient en arrondissant les valeurs des objets à un multiple commun, puis en appliquant la table du chapitre 10 sur les valeurs arrondies — dont l'étendue est désormais bornée par un polynôme en . Le sac à dos est donc -complet et approchable à volonté: les deux ne sont pas contradictoires.
Certains problèmes ont une limite d'approximation démontrée. Pour la couverture par sommets, on sait qu'aucun algorithme polynomial ne peut garantir un rapport meilleur qu'environ à moins que (Dinur et Safra, 2005). L'écart entre ce 1,36 et le 2 de notre algorithme est encore ouvert. Ces résultats dits d'inapproximabilité reposent sur la théorie des preuves vérifiables probabilistiquement, développée au début des années 1990; leur démonstration est hors de portée de ce cours, mais leur forme est celle du théorème 11.5: si l'on savait approcher mieux, on saurait décider exactement, donc .
Certains problèmes ne s'approchent pas du tout. C'est le cas du voyageur de commerce général, c'est-à-dire sans inégalité triangulaire, et la démonstration est assez courte pour être donnée.
Démonstration. Supposons disposer d'un tel algorithme , et soit un graphe à sommets dont on veut décider s'il possède un cycle hamiltonien — problème -complet (Karp, 1972).
Construisons une instance du voyageur sur les mêmes villes, en posant
Cette construction est polynomiale: il y a distances à écrire, chacune sur bits.
Si possède un cycle hamiltonien, ce cycle est une tournée de coût exactement , donc , et l'algorithme rend une tournée de coût au plus .
Si n'en possède pas, toute tournée emprunte au moins une arête absente de , donc au moins une distance ; les autres coûtant au moins 1 chacune, toute tournée coûte au moins . L'algorithme, qui rend une tournée, rend donc plus que .
Il suffit alors de comparer le coût rendu par au seuil : inférieur ou égal, il y a un cycle hamiltonien; strictement supérieur, il n'y en a pas. On aurait ainsi un algorithme polynomial pour un problème -complet, d'où par le théorème 11.5.
Comparez les théorèmes 11.12 et 11.13: le même problème, à l'inégalité triangulaire près, passe d'«approchable à un facteur 2» à «inapprochable à tout facteur constant, sauf si ». L'hypothèse métrique n'est pas un détail de confort, c'est elle qui porte tout le résultat. Voilà pourquoi ce cours n'énonce jamais un théorème d'approximation sans ses hypothèses.
L'explosion, mesurée dans votre navigateur. Le programme balaie toutes les affectations de n variables pour une formule que personne ne peut satisfaire — les huit clauses sur les trois premières variables s'excluent mutuellement. Complétez le balayage pour n = 14: il doit afficher le nombre d'affectations essayées puis le nombre de solutions trouvées. Ensuite, et seulement pour voir, remplacez 14 par 26 et relancez: votre programme sera interrompu au bout de dix secondes, et la page vous le dira. Ce n'est pas une panne, c'est le sujet du chapitre.
Un collègue vous dit: «la couverture par sommets est NP-complète, donc il est inutile de chercher une solution sur mon graphe de 800 sommets». Que lui répondez-vous?
Ce que «P différent de NP» est, et ce qu'on n'en sait pas
Il reste à dire, aussi précisément que possible, où en est la question — et à distinguer ce qui est démontré de ce qui est cru.
Ce qui est démontré. (théorème 11.2). (théorème 11.3). , par le théorème de hiérarchie en temps, donc au moins l'une des deux premières inclusions est stricte. SAT est -complet (Cook–Levin), et des milliers de problèmes le sont avec lui, si bien qu'un algorithme polynomial pour l'un d'eux les résoudrait tous.
Ce qui est ouvert. L'égalité , posée sous cette forme au début des années 1970. Elle figure depuis 2000 parmi les sept problèmes du prix du millénaire de l'institut Clay, dotés chacun d'un million de dollars. Un demi-siècle d'efforts n'a produit ni démonstration ni réfutation.
Ce qui est cru, et qui n'est pas un argument. La grande majorité des spécialistes pense que . Les raisons invoquées sont sérieuses — des milliers de problèmes -complets attaqués par des milliers de chercheurs pendant cinquante ans sans qu'aucun algorithme polynomial n'émerge — mais ce sont des raisons de croire, pas des démonstrations. L'histoire des mathématiques est remplie de convictions unanimes que quelqu'un a fini par renverser.
Pourquoi c'est si difficile: trois barrières. Ce qui distingue cette question d'un problème seulement non résolu, c'est qu'on a démontré l'insuffisance de familles entières de techniques. La relativisation (Baker, Gill et Solovay, 1975) montre qu'il existe des oracles et pour lesquels et : aucune démonstration qui resterait valable en présence d'un oracle quelconque — ce qui est le cas de la diagonalisation classique — ne peut donc trancher. Les (Razborov et Rudich, 1994) montrent que la méthode combinatoire qui avait permis de minorer la taille de certains circuits ne peut pas s'étendre, sauf à contredire l'existence de fonctions à sens unique. L' (Aaronson et Wigderson, 2008) étend la première barrière aux techniques algébriques qui avaient permis de contourner la relativisation. Trois fois, la communauté a démontré que ses propres outils ne suffiraient pas.
Ce que ne dirait pas. Cinq choses, et il faut les connaître pour ne pas raconter n'importe quoi.
- Il ne dirait rien de votre instance. C'est un énoncé de pire cas sur une famille infinie; votre graphe peut être facile et vos formules SAT résolues en une seconde par un solveur industriel.
- Il n'interdirait pas les algorithmes sous-exponentiels. Rien dans n'exclut un algorithme en ou en , et de tels algorithmes existent pour des cas particuliers structurés. Les hypothèses qui les excluraient — ETH, SETH — sont des , strictement plus fortes que , et elles sont énoncées comme telles dans la littérature.
Ce que ne donnerait pas non plus. Une démonstration pourrait être non constructive, ou produire un algorithme en avec une constante astronomique: la révolution pratique qu'on imagine parfois n'est pas garantie par l'égalité elle-même. Elle serait en revanche un séisme conceptuel: par l'auto-réductibilité du théorème 11.1, elle ferait de la recherche d'une preuve mathématique courte une tâche mécanique, ce qui est à peu près la raison pour laquelle presque personne n'y croit.
Terminons par où nous avons commencé. Face à un problème nouveau, vous disposez maintenant de trois réponses possibles, et de trois seulement: j'ai un algorithme polynomial, le voici; j'ai démontré que ce problème est -difficile, voici la réduction, et je passe aux approximations; ou je ne sais pas encore. La troisième est une réponse honnête et fréquente. Ce qui ne l'est pas, c'est la quatrième, celle qu'on entend trop souvent: c'est impossible. Personne, à ce jour, n'a le droit de la prononcer.
Synthèse
- La théorie se construit sur les problèmes de décision, sans perte de généralité: décision, optimisation et recherche sont polynomialement équivalentes (théorème 11.1), par dichotomie sur le seuil puis auto-réduction en appels. La taille d'une instance est la longueur de son codage en bits, ce qui rend le du sac à dos pseudo-polynomial: pour cent objets et des poids de 40 bits, la table compte cases alors que l'instance tient en 4000 bits.
- est la classe des problèmes résolubles en temps polynomial; celle des problèmes en temps polynomial, définie par un de taille polynomiale et un vérificateur, avec ses deux obligations — un certificat existe sur toute instance positive, aucun n'est accepté sur une instance négative. , et : au moins l'une des deux inclusions est stricte, on ne sait pas laquelle.
On sait que et l'on découvre un algorithme polynomial pour . Qu'en déduit-on?
Exercices
Vous pouvez afficher le corrigé directement sous chaque énoncé après avoir cherché la solution.
Le problème de la clique maximum demande, étant donné un graphe , la taille de la plus grande clique de — une clique étant un ensemble de sommets deux à deux adjacents.
- Énoncez la version décisionnelle de ce problème.
- Donnez un certificat et décrivez son vérificateur, en précisant son coût.
- En supposant disposer d'un sous-programme polynomial pour la version décisionnelle, décrivez un algorithme polynomial qui calcule la taille de la clique maximum, et comptez les appels.
Solution
1. CLIQUE: étant donnés un graphe et un entier , existe-t-il un ensemble de sommets deux à deux adjacents?
Pour chacun des trois problèmes suivants, dites s'il appartient à ; si oui, donnez explicitement un certificat et le coût de sa vérification en fonction de et ; si vous ne savez pas, dites précisément pourquoi.
- PARTITION: étant donnée une liste de entiers positifs, peut-on la scinder en deux parts de même somme?
- NON-HAMILTONIEN: étant donné un graphe, est-il vrai qu'il n'a aucun cycle hamiltonien?
- ARBRE COUVRANT LÉGER: étant donnés un graphe pondéré et un entier , existe-t-il un arbre couvrant de poids au plus ?
Solution
On considère la formule
On compare deux algorithmes gloutons pour la couverture par sommets.
- Glouton A: tant qu'il reste une arête non couverte, choisir une telle arête et ajouter une de ses deux extrémités, choisie arbitrairement.
- Glouton B: celui du théorème 11.11, qui ajoute les deux extrémités.
- Sur une étoile à branches — un sommet central relié à sommets périphériques et rien d'autre —, donnez la couverture minimum, puis le pire résultat possible du glouton A et le résultat du glouton B.
- Le glouton A admet-il une garantie d'approximation constante? Justifiez.
- Expliquez en une phrase pourquoi le gaspillage apparent du glouton B est ce qui rend sa garantie démontrable.
Solution
1. L'étoile a arêtes, toutes incidentes au centre . La couverture minimum est , de taille .
Cet exercice demande des démonstrations complètes.
Soit un graphe non orienté à sommets. Rappelons qu'un ensemble indépendant (ou stable) est un ensemble de sommets deux à deux non adjacents, et qu'une clique est un ensemble de sommets deux à deux adjacents. On note le graphe complémentaire de : mêmes sommets, et est une arête de si et seulement si ce n'en est pas une de .
Références
- Cormen, Leiserson, Rivest & Stein, Introduction to Algorithms, 4ᵉ éd., MIT Press — chapitre 34 pour , , la -complétude et les réductions, chapitre 35 pour les algorithmes d'approximation, dont la couverture par sommets et le voyageur métrique.
- Cormen, Leiserson, Rivest & Stein, Algorithmique, 3ᵉ éd., Dunod — la traduction française des mêmes chapitres, utile pour fixer le vocabulaire: «couverture par sommets», «réduction», «vérificateur», «problème -complet».
- Kleinberg & Tardos, Algorithm Design, Pearson — chapitre 8, la meilleure présentation pédagogique des réductions, avec la distinction décision/optimisation traitée explicitement; chapitres 10 et 11 pour la complexité paramétrée et l'approximation.
- Dasgupta, Papadimitriou & Vazirani, Algorithms, McGraw-Hill — chapitre 8, court et remarquablement clair sur le catalogue des problèmes -complets et le graphe des réductions entre eux.
- Garey & Johnson, Computers and Intractability: A Guide to the Theory of NP-Completeness, Freeman — la référence historique et le catalogue de plusieurs centaines de problèmes; c'est de là que vient la réduction de 3-SAT vers la couverture par sommets présentée ici.
- Arora & Barak, Computational Complexity: A Modern Approach, Cambridge University Press — pour la démonstration du théorème de Cook–Levin, admise dans ce chapitre, et pour les barrières de relativisation, de preuves naturelles et d'algébrisation.