Skip to content

🌐 ÉnoncĂ© du problĂšme / Cadre d'Ă©tude

🌐 ÉnoncĂ© du problĂšme / Cadre d’étude

Section titled “🌐 ÉnoncĂ© du problĂšme / Cadre d’étude”

Dans le cadre de l’étude de la complexitĂ© des algorithmes, on s’intĂ©resse aux classes de complexitĂ© P\text{P} et NP\text{NP}, ainsi qu’à la notion de rĂ©duction polynomiale et de complĂ©tude. Cet exercice propose d’étudier un problĂšme classique de graphes, le problĂšme du Chemin Hamiltonien.

Soit G=(S,A)G = (S, A) un graphe non orientĂ©, oĂč SS est l’ensemble des sommets et AA l’ensemble des arĂȘtes. Un chemin hamiltonien dans GG est un chemin simple qui visite chaque sommet de SS exactement une fois.

On définit le problÚme décisionnel HAMILTONIAN-PATHH\text{AMILTONIAN-\text{P}\text{ATH}} (HP) de la maniÚre suivante :

  • EntrĂ©e : Un graphe non orientĂ© G=(S,A)G = (S, A), un sommet de dĂ©part s∈Ss \in S et un sommet d’arrivĂ©e t∈St \in S.
  • Question : Existe-t-il un chemin hamiltonien dans GG allant de ss Ă  tt ?

On rappelle qu’un problĂšme de dĂ©cision Π\Pi appartient Ă  la classe NP\text{NP} s’il existe un algorithme dĂ©terministe polynomial en temps (le vĂ©rifieur) qui, Ă©tant donnĂ© une instance II de Π\Pi et un certificat cc de taille polynomiale en la taille de II, vĂ©rifie en temps polynomial si cc est une solution valide pour II.

Section titled “On rappelle qu’un problĂšme de dĂ©cision Π\PiΠ appartient Ă  la classe NP\text{NP}NP s’il existe un algorithme dĂ©terministe polynomial en temps (le vĂ©rifieur) qui, Ă©tant donnĂ© une instance III de Π\PiΠ et un certificat ccc de taille polynomiale en la taille de III, vĂ©rifie en temps polynomial si ccc est une solution valide pour III.”
  1. (Rappels et dĂ©finitions) PrĂ©ciser la dĂ©finition de la classe P\text{P} et de la classe NP\text{NP}. Quelle est l’inclusion triviale entre ces deux classes ? Quel est le plus grand dĂ©fi thĂ©orique ouvert associĂ© Ă  ces classes ?

  2. (Appartenance à NP) Démontrer que le problÚme HAMILTONIAN-PATH\text{H}\text{AMILTONIAN-\text{P}\text{ATH}} appartient à la classe NP\text{NP}. Précisez clairement la nature du certificat et la complexité du vérifieur associé.

  3. (RĂ©duction polynomiale) Soit Π1\Pi_1 et π2\pi_2 deux problĂšmes de dĂ©cision. Rappeler la dĂ©finition de « Π1\Pi_1 se rĂ©duit polynomialement Ă  Π2\Pi_2 » (notĂ© Π1≀pΠ2\Pi_1 \le_p \Pi_2). Quel est l’intĂ©rĂȘt fondamental de cette notion pour l’étude des problĂšmes NP\text{NP}-complets ?

  4. (Étude d’un problĂšme restreint) On considĂšre un sous-problĂšme de HP oĂč le graphe est un DAG (Directed Acyclic Graph) orientĂ©, notĂ© \text{DAG-\text{L}\text{ONGEST-\text{P}\text{ATH}}.

    • Montrer que le problĂšme du plus long chemin dans un graphe gĂ©nĂ©ral est NP\text{NP}-difficile.
    • Expliquer pourquoi, curieusement, ce mĂȘme problĂšme se rĂ©sout en temps polynomial O(∣S∣+∣A∣)\mathcal{O}(|S| + |A|) si le graphe est un DAG (en utilisant un tri topologique).
  5. (Algorithmique - ImplĂ©mentation Python) Écrire une fonction Python rĂ©cursive avec mĂ©moĂŻsation (ou programmation dynamique sur un DAG) permettant de calculer la longueur du plus long chemin Ă  partir d’un sommet ss dans un DAG pondĂ©rĂ©.


  • Pour la Q2 : Pensez Ă  ce qu’un “certificat” intuitif reprĂ©sente pour un chemin : une liste ordonnĂ©e de sommets. Évaluez le temps nĂ©cessaire pour vĂ©rifier si cette liste forme un chemin valide (arĂȘtes existantes) et visite chaque sommet une et une seule fois.
  • Pour la Q3 : La rĂ©duction doit ĂȘtre calculable par une machine de Turing en temps polynomial. Si Π1≀pΠ2\Pi_1 \le_p \Pi_2 et que Π2∈P\Pi_2 \in \text{P}, alors Π1∈P\Pi_1 \in \text{P}.
  • Pour la Q4 : Pour les DAGs, l’absence de cycles permet d’appliquer une structure d’ordre (tri topologique) idĂ©ale pour la programmation dynamique, Ă©vitant l’explosion combinatoire propre aux graphes gĂ©nĂ©raux.
  • Pour la Q5 : Utilisez un dictionnaire pour stocker les rĂ©sultats intermĂ©diaires (mĂ©moĂŻsation) lors de l’exploration des successeurs dans le DAG.

  • La classe P\text{P} (Polynomial time) regroupe tous les problĂšmes de dĂ©cision qui peuvent ĂȘtre rĂ©solus par une machine de Turing dĂ©terministe (ou un algorithme classique) en un temps O(nk)O(n^k) pour un entier kk fixĂ©, oĂč nn est la taille de l’entrĂ©e.
  • La classe NP\text{NP} (Nondeterministic Polynomial time) regroupe les problĂšmes de dĂ©cision pour lesquels une solution (un certificat) peut ĂȘtre vĂ©rifiĂ©e en temps polynomial par un algorithme dĂ©terministe.
  • Inclusion : On a trivialement P⊆NP\text{P} \subseteq \text{NP}, car si on sait rĂ©soudre un problĂšme en temps polynomial, on peut aussi vĂ©rifier une solution en temps polynomial (en ignorant le certificat et en rĂ©solvant directement le problĂšme).
  • ProblĂšme ouvert : Le problĂšme fondamental non rĂ©solu en informatique thĂ©orique est de savoir si P=NP\text{P} = \text{NP} ou P≠NP\text{P} \neq \text{NP}.

2. Appartenance de HAMILTONIAN-PATH\text{H}\text{AMILTONIAN-\text{P}\text{ATH}} Ă  NP\text{NP}

Section titled “2. Appartenance de HAMILTONIAN-PATH\text{H}\text{AMILTONIAN-\text{P}\text{ATH}}HAMILTONIAN-PATH à NP\text{NP}NP”

Pour montrer que HAMILTONIAN-PATH∈NP\text{H}\text{AMILTONIAN-\text{P}\text{ATH}} \in \text{NP}, construisons le vérifieur :

  • Certificat cc : Une suite ordonnĂ©e de sommets c=(v1,v2,
,vk)c = (v_1, v_2, \dots, v_k).
  • Taille du certificat : La taille est de l’ordre de ∣S∣|S|, ce qui est polynomial par rapport Ă  la taille de l’instance du graphe G=(S,A)G=(S,A).
  • VĂ©rification : Le vĂ©rifieur effectue les contrĂŽles suivants en temps polynomial :
    1. Vérifier que v1=sv_1 = s et vk=tv_k = t.
    2. Vérifier que k=∣S∣k = |S| (le chemin visite tous les sommets).
    3. VĂ©rifier que les sommets du certificat sont tous distincts (utilisation d’un ensemble/hashset en O(∣S∣)\mathcal{O}(|S|)).
    4. Pour tout i∈{1,
,k−1}i \in \{1, \dots, k-1\}, vĂ©rifier que l’arĂȘte (vi,vi+1)(v_i, v_{i+1}) appartient bien Ă  AA (en O(∣A∣)\mathcal{O}(|A|) ou via une matrice d’adjacence en O(1)\mathcal{O}(1) par test). L’ensemble de ces vĂ©rifications s’exĂ©cute en O(∣S∣2)\text{O}(|S|^2), soit un temps polynomial. Par consĂ©quent, HAMILTONIAN-PATH∈NP\text{H}\text{AMILTONIAN-\text{P}\text{ATH}} \in \text{NP}.

3. Définition et utilité de la réduction polynomiale

Section titled “3. DĂ©finition et utilitĂ© de la rĂ©duction polynomiale”
  • DĂ©finition : Soit Π1\Pi_1 et Π2\Pi_2 deux problĂšmes de dĂ©cision. On dit que Π1\Pi_1 se rĂ©duit polynomialement Ă  Π2\Pi_2 (notĂ© Π1≀pΠ2\Pi_1 \le_p \Pi_2) s’il existe une fonction ff calculable par une machine de Turing en temps polynomial telle que, pour toute instance II : Instance I est positive pour Π1  âŸș  f(I) est une instance positive pour Π2\text{Instance } I \text{ est positive pour } \Pi_1 \iff f(I) \text{ est une instance positive pour } \Pi_2
  • UtilitĂ© : Si Π1≀pΠ2\Pi_1 \le_p \Pi_2 et que Π2∈P\Pi_2 \in \text{P}, alors Π1∈P\Pi_1 \in \text{P}. De mĂȘme, cela permet de propager la NP\text{NP}-complĂ©tude : si Π1\Pi_1 est NP\text{NP}-difficile et Π1≀pΠ2\Pi_1 \le_p \Pi_2, alors Π2\Pi_2 est Ă©galement NP\text{NP}-difficile.

4. Étude du plus long chemin : Graphe gĂ©nĂ©ral vs DAG

Section titled “4. Étude du plus long chemin : Graphe gĂ©nĂ©ral vs DAG”
  • Graphe gĂ©nĂ©ral : Le problĂšme gĂ©nĂ©ral du plus long chemin est NP\text{NP}-difficile (il contient le problĂšme du voyageur de commerce ou le problĂšme du chemin hamiltonien comme cas particuliers lorsque la longueur maximale recherchĂ©e est ∣S∣−1|S|-1).
  • Cas du DAG : Dans un DAG (graphe orientĂ© sans cycle), l’absence de cycles permet d’utiliser un tri topologique des sommets. On peut dĂ©finir une relation de rĂ©currence optimale sur les sous-problĂšmes, menant Ă  un algorithme de programmation dynamique s’exĂ©cutant en O(∣S∣+∣A∣)\mathcal{O}(|S| + |A|).

5. Implémentation Python pour le plus long chemin dans un DAG

Section titled “5. ImplĂ©mentation Python pour le plus long chemin dans un DAG”

Voici l’algorithme utilisant la programmation dynamique avec mĂ©moĂŻsation (descendante) :

def longest_path_dag(graph, weights, start):
"""
Calcule la longueur du plus long chemin Ă  partir du sommet 'start' dans un DAG.
- graph : dict représentant les listes d'adjacence {u: [v1, v2, ...]}
- weights : dict associant un poids Ă  chaque arĂȘte {(u, v): poid}
- start : sommet de départ
"""
memo = {}
def dfs(u):
if u in memo:
return memo[u]
# Si le sommet n'a pas de successeurs
if not graph.get(u):
return 0
max_dist = 0
for v in graph[u]:
dist = weights.get((u, v), 0) + dfs(v)
if dist > max_dist:
max_dist = dist
memo[u] = max_dist
return max_dist
return dfs(start)