Centrale Informatique MPI 2023Sujet, corrigé et rapport du jury
- Graphes (complexité, réductions, NP-complétude)
- Algorithmes gloutons (algorithme de Kruskal)
- Programmation en langage C (pointeurs, allocation dynamique de mémoire)
- Programmation en OCaml (types récursifs, listes d'adjacence)
- Preuves de correction et de terminaison d'algorithmes
Téléchargements
Présentation du sujet
Difficulté moyenneAlgorithmique des graphes : le problème du voyageur de commerce (NP-complétude, algorithme de Christofides en C) et les espaces d'arbres binaires non racinés (OCaml)Afficher ou masquer la section
Présentation du sujet
Difficulté moyenneLe sujet comporte deux parties indépendantes de graphes. La première étudie le problème du voyageur de commerce, sa complexité, sa NP-complétude et propose l'algorithme d'approximation de Christofides à implémenter en C. La seconde étudie des graphes dont les sommets sont des arbres binaires non racinés reliés par des opérations d'édition (NNI, SPR), à implémenter en OCaml.
- 1I.A : prise en main du problème et appartenance à NPIntroduction du problème du voyageur de commerce et transformation en problème de décision appartenant à NP.
- 2I.B : étude de la complexitéRéductions successives menant à la NP-complétude du problème et preuve de l'absence de 1+epsilon-approximation si P différent de NP.
- 3I.C : algorithme de ChristofidesConstruction d'un arbre couvrant minimal (Kruskal), d'un couplage parfait et d'un cycle eulérien, implémentation en C et preuve que l'algorithme est une 3/2-approximation sous l'inégalité triangulaire.
- 4II.A à II.B : prise en main des espaces d'arbres et étude de G_NNI(5)Étude des opérations d'édition NNI et SPR sur des arbres binaires non racinés et dénombrement des arbres et de leurs voisins.
- 5II.C : construction de G_NNI(n) en OCamlImplémentation en OCaml d'arbres binaires et de graphes par listes d'adjacence pour construire le graphe des voisinages NNI.
- 6II.D : G_SPR(n) est hamiltonienDémonstration par récurrence de l'existence d'un circuit hamiltonien dans le graphe des mouvements SPR.
Difficulté moyenne. Le jury se dit globalement satisfait du niveau atteint, avec de bonnes compétences en programmation, mais les résultats aux questions théoriques (preuves, réductions) sont plus variables ; sur 52 questions, les candidats en ont traité 25 en moyenne.
L'épreuve en chiffres
Moyenne 9,44 / 20 · écart-type 3,9 · 569 présents · où vous situez-vous ?Afficher ou masquer la section
L'épreuve en chiffres
- Moyenne
- 9,44/ 20
- Écart-type
- 3,9
- Présents
- 569
- Coefficient
- 16
- Durée
- 4 h
- 1er quartile
- 6,6
- Médiane
- 9,2
- 3e quartile
- 11,9
Votre note sur 20 à ce sujet, en conditions de concours.
Source : document officiel du concours, épreuve du 10 mai 2023. Notes publiées par le concours (après harmonisation le cas échéant). Courbe : estimation par une loi normale.
Ce qu'a observé le jury
5 erreurs relevéesImplémentation de l'algorithme de Kruskal peu maîtrisée · Question à plusieurs volets partiellement traitée · Question simple délaisséeAfficher ou masquer la section
Ce qu'a observé le jury
5 erreurs relevéesLes candidats ont démontré de bonnes compétences en programmation, à la fois en C et en OCaml, et les questions impliquant de la programmation ont été plébiscitées. Les résultats aux questions théoriques sont plus variables, certains candidats les évitant, et les questions de cours ont donné des résultats mitigés. Le jury est globalement satisfait du niveau atteint par les candidats de cette première session MP2I/MPI.
Les erreurs les plus sanctionnées
- 1Implémentation de l'algorithme de Kruskal peu maîtriséeQ16
L'implémentation de l'algorithme de Kruskal en temps limité a donné des résultats mitigés.
« Les résultats sont mitigés, les candidats qui ont traité cette question ont, en moyenne, obtenu à peu près la moitié des points correspondants. »
- 2Question à plusieurs volets partiellement traitéeQ19
La question combinant calcul de taille de tableau, allocation dynamique et écriture du résultat via un pointeur n'a été totalement réussie que par une minorité de candidats malgré un taux de traitement élevé.
« mais seulement 35% ont donné un résultat totalement juste. »
- 3Question simple délaisséeQ20
Une question sans difficulté majeure n'a été traitée que par un candidat sur quatre.
« Cette question n’a été traitée que par un candidat sur quatre. »
- 4Manque d'illustrations par des schémasQ5, Q6, Q7
De nombreux candidats décrivent uniquement en texte les réductions et constructions de graphes, là où un schéma aurait clarifié le raisonnement.
« De trop nombreux candidats ont préféré tout décrire sous forme de texte là où un schéma aurait rendu le discours plus clair. »
- 5Preuves de constructions incorrectes prétendues correctesQ5, Q6, Q7
Certains candidats paraphrasent leur construction au lieu de vérifier réellement sa correction, ce qui les mène à prétendre prouver des constructions en réalité incorrectes.
« Un certain nombre de copies ont donné des « preuves » qu’une construction incorrecte était juste. »
Ce qui a été bien réussi
- La majorité des candidats (60 %) a bien traité la question de cours consistant à transformer le problème d'optimisation en problème de décision (Q4).
- 86 % des candidats ont traité correctement la question demandant un esprit de synthèse sur le graphe A et ont obtenu le maximum des points (Q8).
- La question 18, qui ne présentait pas de réelle difficulté, a été parfaitement traitée par 79 % des candidats.
- Les candidats savent rédiger des preuves et, pour la plupart, savent faire preuve de concision.
- Les questions de programmation en OCaml (Q41 à Q49) ont été bien réussies par les candidats qui les ont traitées.
Conseils du jury
- Vérifier que la fonction programmée satisfait entièrement sa spécification, et pas seulement une partie de celle-ci.
- Illustrer les réductions et constructions de graphes par des schémas plutôt que par du texte seul.
- Une preuve doit vérifier qu'un résultat est vrai plutôt que le paraphraser : se demander si la même démarche aurait permis de prouver un résultat faux.
- Traiter tous les points demandés dans une question à plusieurs volets, sans en négliger certains.
- Faire preuve de concision dans la rédaction : un manque de concision est associé à davantage d'erreurs dans les preuves.
Synthèse rédigée par WikiPrépa à partir du rapport officiel du jury (à télécharger en PDF). Les citations sont extraites du rapport.
Ces sujets peuvent vous intéresser
Lecture du sujet en ligne
L'énoncé complet, avec les formules et les figures, sans ouvrir le PDF.Afficher ou masquer la section
Lecture du sujet en ligne
I Problème du voyageur de commerce
Un chemin est une suite de sommets reliés par des arêtes. On dit qu'un chemin passe par un sommet si ce sommet appartient au chemin. Un circuit est un chemin qui commence et se termine au même sommet. Un chemin hamiltonien est un chemin qui passe une et une seule fois par chaque sommet du graphe. Un circuit hamiltonien est un circuit qui passe par chaque sommet une et une seule fois.
Le problème du voyageur de commerce consiste, étant donnée une liste de villes toutes reliées entre elles, à trouver le circuit le plus court qui passe une et une seule fois par chacune des villes.
Plus formellement, on considère un graphe complet non orienté, dont les arêtes sont étiquetées avec des nombres entiers strictement positifs, appelés poids, et on cherche le circuit passant par chacun des sommets du graphe qui minimise la somme des poids des arêtes. On appellera poids d'un circuit la somme des poids des arêtes empruntées par ce circuit. Une solution au problème du voyageur de commerce est un circuit hamiltonien de poids minimal.
Dans cette partie, on représente les graphes en C par des matrices d'adjacence. Le poids d'une arête est représenté par un int, une arête absente étant représentée par un 0 . On représente un graphe par une structure de données avec deux attributs : son nombre de sommets V et un pointeur adj vers sa matrice d'adjacence de taille
struct Graphe {
int V;
int* adj;
};
struct Graphe alloue_graphe(int V) {
int* adj = malloc(V * V * sizeof(int));
struct Graphe g = {.V = V, .adj = adj};
return g;
}
void libere_graphe(struct Graphe g) {
free(g.adj);
}
On définit également une structure Chemin qui représente un chemin par un attribut longueur et un attribut l_sommets, pointeur vers un tableau à longueur éléments. Si C est un chemin et k un entier naturel strictement plus petit que C.longueur, alors C.l_sommets [k] est le k-ième sommet du chemin C. De même que pour les graphes, on définit aussi des fonctions permettant d'allouer un chemin et de libérer un chemin dont on n'a plus besoin, et qui sont supposées travailler en temps constant.
struct Chemin {
int longueur;
int* l_sommets;
};
struct Chemin alloue_chemin(int longueur) {
int* l_sommets = malloc(longueur * sizeof(int));
struct Chemin c = {.longueur = longueur, .l_sommets = l_sommets};
return c;
}
void libere_chemin(struct Chemin c) {
free(c.l_sommets);
}
I.A - Prise en main du problème et appartenance à NP

Q 2. Donner le nombre de circuits hamiltoniens sur un graphe complet de
Q 3. Écrire une fonction
int poids_chemin(struct Graphe g, struct Chemin c);
qui prend en arguments un graphe et un chemin et renvoie le poids de ce chemin. Donner la complexité de cette fonction.
Q 4. Le problème du voyageur de commerce est un problème d'optimisation ; à l'aide d'un seuil, transformer ce problème en un problème de décision. Montrer que ce nouveau problème, que nous appellerons par la suite «problème de décision du voyageur de commerce», appartient à la classe de complexité NP.
I.B - Étude de la complexité
I.B.1) NP-complétude
Q 6. Montrer que le problème du circuit hamiltonien se réduit au problème de décision du voyageur de commerce.
Q 7. Montrer que le problème du chemin hamiltonien orienté se réduit au problème du chemin hamiltonien. Le problème 3-SAT consiste à déterminer la satisfiabilité d'une formule logique sous forme normale conjonctive avec exactement 3 littéraux : pour

On se donne une instance du problème 3-SAT, pour
On construit alors le graphe orienté
- pour chaque variable
y_k on crée un sommetv_k ; - on ajoute un sommet supplémentaire
v_(m + 1) ; - pour chaque clause
C_i on ajoute une copie du grapheA , notéeA_i ; - pour chaque variable
y_k , on noteC_(k_1), …, C_(k_ℓ) les clauses dans lesquellesy_k apparait en positif. On relie alorsv_k àA_(k_1) par un arc allant dev_k verse_p dansA_(k_1) lorsquey_k est en positionp dansC_(k_1) c'est-à-dire lorsqueC_(k_1) = x_(k_1, 1) ∨ x_(k_1, 2) ∨ x_(k_1, 3) etx_(k_1, p) = y_k . On relie ensuite la sorties_p deA_(k_1) à l'entrée deA_(k_2) correspondant à la position dey_k dansC_(k_2) et ainsi de suite jusqu'au dernier dont on relie la sortie àv_(k + 1) . On appelleG_k^+ le sous-graphe constitué du sommetv_k , des graphesA_(k_1), A_(k_2), …, A_(k_ℓ) et du sommetv_(k + 1) , ainsi que des arcs que l'on vient d'ajouter entre eux en considéranty_k et les clauses dans lesquelles il apparait positivement ; - on crée de même des arcs pour chaque variable
y_k et chaque clause dans laquelley_k apparait en négatif. On noteG_k^− , le sous-graphe correspondant entrev_k etv_(k + 1) .
Q 9. Montrer que pour toute valuation de la formule il existe un chemin hamiltonien orienté dev_1 àv_(m + 1) dans le grapheG .
Q 10. Montrer, en une dizaine de lignes au maximum, que pour chaque chemin hamiltonien orienté dev_1 àv_(m + 1) il existe bien une valuation.
Q 11. En déduire que le problème du circuit hamiltonien et le problème de décision du voyageur de commerce sont NP-complets.
I.B.2) Approximation
Soit
Q 12. Montrer que si
Q 13. Montrer que si
Q 14. En déduire que, si
I.C - Algorithme de Christofides
- calculer un arbre couvrant de poids minimal
T deG ; - en notant
I l'ensemble des sommets de degré impair dansT , calculer un couplage parfaitM de poids minimum dans le sous-graphe deG induit par les sommets deI, G_(|I) ; - construire
H le multigraphe ayant pour sommet les sommets deG et comme arêtes les arêtes deM et celles deT ; - trouver un cycle eulérien dans
H ; - transformer le cycle eulérien en circuit hamiltonien en supprimant les éventuels sommets vus plusieurs fois.
I.C.1) Arbre couvrant
Pour cela, on va représenter une arête par une structure de données avec trois attributs : s1 et s2 donnent les sommets reliés par l'arête et
struct Arete {
int s1;
int s2;
int p;
};
Q 15. Écrire une fonction
struct Arete* liste_aretes(struct Graphe g);
On dispose d'une fonction
void tri_aretes(struct Arete a[], int k);
Q 16. Écrire une fonction
struct Graphe kruskal(struct Graphe g);
Q 17. Montrer la correction de cet algorithme, c'est-à-dire l'optimalité de la solution proposée pour le problème d'arbre couvrant de poids minimal.
I.C.2) Couplage
Q 18. Écrire une fonction
int degre(struct Graphe g, int i);
Q 19. Écrire une fonction
int* sommets_impairs(struct Graphe g, int* nb_sommets);
Q 20. Montrer l'existence d'un couplage parfait de poids minimal dans
On dispose des deux fonctions suivantes:
struct Graphe graphe_induit(struct Graphe g, int nb_sommets, int* liste_sommets);
struct Graphe couplage(struct Graphe g);
La fonction couplage renvoie un couplage parfait de poids minimal s'il existe, sous la forme d'un graphe représentant ce couplage, avec des 0 lorsque l'arête est absente et 1 lorsque l'arête est présente.
On supposera ces deux fonctions de complexité polynomiale.
I.C.3) Cycle eulérien
Q 21. Montrer que le multigraphe
On dispose des trois fonctions suivantes:
struct Multigraphe multigraphe(struct Graphe g1, struct Graphe g2);
struct Chemin eulerien(struct Multigraphe h);
void libere_multigraphe(struct Multigraphe h);
Q 22. Écrire une fonction
struct Chemin euler_to_hamilton(struct Chemin c);
I.C.4) Implémentation
Q 24. Écrire une fonction
struct Chemin christofides(struct Graphe g);
Q 25. Justifier que la fonction christophides renvoie bien un circuit hamiltonien.
Q 26. Montrer que la fonction christophides est de complexité polynomiale.
I.C.5) Preuve de l'approximation
Q 27. Montrer que
Q 28. Montrer que
Q 29. Montrer que la solution construite par l'algorithme est une
Q 30. Sans la supposition de l'inégalité triangulaire, cette solution est-elle toujours une
II Espaces d'arbres
La première opération, notée SPR, pour Subtree Prune and Regraft (ou découpe et greffe d'un sous-arbre), prend en entrée 2 branches

.jpg)
.jpg)
.jpg)
.jpg)
- l'arbre 1 est un arbre binaire non raciné avec ses feuilles étiquetées ;
- l'arbre 2 est obtenu à partir de l'arbre 1 par un SPR en coupant la branche
e et en la greffant sur la branchef ; - dans l'arbre 3 , où les triangles représentent des sous-arbres racinés, la branche interne
e sépare 4 sous-arbres racinésA, B, C et D ; - l'arbre 4 est obtenu à partir de l'arbre 3 par un mouvement NNI sur la branche
e en échangeant les sous-arbres B et D ; - l'arbre 5 est obtenu à partir de l'arbre 1 par un NNI sur la branche
e en échangeant le sous-arbre contenant la feuille 5 et le sous-arbre contenant les feuilles 1 et 2 .
On étudie l'espace des arbres binaires non racinés étiquetés den feuillesB(n) suivant ces deux processus d'édition. On définitG_(NNI)(n) le graphe dont les sommets sont les arbres deB(n) et dans lequel une arête relie deux arbres si l'on peut passer de l'un à l'autre par un mouvement NNI. On définit de mêmeG_(SPR)(n) avec les mouvements SPR. On va notamment s'intéresser à la structure deG_(NNI)(5) , écrire un programme permettant de construireG_(NNI)(n) et montrer queG_(SPR)(n) est hamiltonien, c'est-à-dire qu'il possède un circuit hamiltonien.
II.A - Prise en main
Q 32. Donner le nombre de branches et de nœuds d'un arbre de
Q 33. On note
Q 34. Tracer
Q 35. Combien de voisins un arbre de
On appelle arbre chenille un arbre binaire non raciné dans lequel il existe un chemin passant une et une seule fois par chaque nœud interne.
Q 36. Montrer que l'on peut passer de tout arbre de
Q 37. Montrer que tout mouvement SPR peut se décomposer en mouvements NNI, et que tous les mouvements NNI sont des mouvements SPR. En déduire que
II.B - Étude de
G_(NNI)(5)
Q 39. Montrer que tout arbre de
Q 40. Tracer
II.C - Construction de
G_(NNI)(n)
type arbre = Feuille of int
| Noeud of arbre * arbre ;;
Un arbre non raciné à
Enfin, pour assurer l'unicité de la représentation informatique d'un arbre, et ainsi simplifier les programmes, on adopte la convention, pour chaque nœud interne, que la plus grande des étiquettes du sous-arbre droit est supérieure aux étiquettes du sous-arbre gauche.
Ainsi, l'arbre 1 de la figure 3 est représenté par :
Noeud (Noeud (Feuille 3,
Noeud (Noeud (Feuille 1,
Feuille 2),
Feuille 4)),
5);;
type graphe
Q 41. Écrire une fonction feuilles qui prend en argument un arbre et renvoie la liste des étiquettes de ses feuilles.
Q 42. Écrire une fonction degres qui prend en argument un graphe implémenté par liste d'adjacence et renvoie la liste des degrés de ces nœuds.
Q 43. Écrire une fonction egaux qui teste si deux arbres sont égaux, au sens des arbres binaires non racinés étiquetés. Justifier que cette fonction est correcte.
Q 44. Étant donnés une liste d'arbres et un arbre, écrire une fonction appartient qui teste si l'arbre fait partie de la liste.
Q 45. En remarquant que parmi les 4 sous-arbres à échanger pour un mouvement de NNI autour d'une branche interne, on peut en choisir un qui restera fixe, écrire une fonction voisinsNNI qui prend en argument un arbre et renvoie tous les arbres que l'on peut obtenir à partir de celui-ci par un mouvement NNI.
Q 46. Écrire une fonction chenille qui prend en argument un entier
Q 47. Écrire une fonction insere qui prend en arguments un arbre et un graphe et ajoute l'arbre à la liste des sommets du graphe.
Q 48. Écrire une fonction relie qui prend en arguments un graphe et deux arbres et qui rajoute au graphe une arête reliant les deux sommets, si elle n'est pas déjà présente.
Q 49. Écrire une fonction grapheNNI qui prend en argument un entier
II.D
− G_(SPR)(n) est hamiltonien
On note
Q 50. Montrer que les sous-graphes
Q 51. Soient
Q 52. Démontrer par récurrence que
Questions fréquentes
4 questionsSur quels chapitres porte le sujet d'informatique MPI Centrale 2023 ?Afficher ou masquer la section
Questions fréquentes
4 questionsSur quels chapitres porte le sujet d'informatique MPI Centrale 2023 ?
Le sujet porte sur les graphes : complexité et NP-complétude avec le problème du voyageur de commerce et l'algorithme de Christofides en C, puis espaces d'arbres binaires non racinés et mouvements d'édition NNI/SPR en OCaml.
Le sujet d'informatique MPI 2023 est-il difficile ?
Le jury se dit globalement satisfait du niveau atteint : les candidats ont montré de bonnes compétences en programmation, mais les questions théoriques, en particulier les preuves et les réductions, ont donné des résultats plus variables.
Quelles sont les erreurs les plus fréquentes relevées par le jury sur ce sujet d'informatique MPI 2023 ?
Le jury relève un manque d'usage de schémas pour illustrer les réductions de graphes, des preuves qui paraphrasent la construction sans en vérifier réellement la correction, et des questions à plusieurs volets seulement partiellement traitées.
Faut-il bien maîtriser le C et OCaml pour ce sujet ?
Oui, la première partie demande de manipuler pointeurs et allocation dynamique en C, la seconde de programmer des types récursifs et des listes d'adjacence en OCaml ; le rapport indique que les candidats maîtrisent globalement bien les deux langages.
Pas de description pour le moment
