PROJET Le coloriage de carte Le problème est le suivant :
Quelle que soit la complexité d'une carte géographique, quatre couleurs suffisent pour la colorier sans que deux frontières soient de la même couleur.
Pour étudier ce problème, il convient de bien spécifier les paramètres. On dira que deux pays ont une frontière commune si leurs frontières ont plus d’un point en commun. Il faut également trouver un outil approprié. En effet la carte géographique présente des détails qui sont inutiles à notre analyse : la forme des pays, leur superficie, … Nous avons eu deux idées pour la représenter :
- Un tableau avec les pays en entrée et en sortie, si un pays est frontalier à un autre on mettra un « 1 » à l’intersection de ses deux pays.
Exemple :
Problème de cette représentation :
o Très peu d’outils mathématiques utilisables. o Pas d’équivalence tableau – carte.
- Un graphe tel que chaque pays est représenté par un sommet et que lorsque deux pays ont une frontière commune on relie les sommets entre eux.
Exemple : c a b a b c c a b a a b b c c 1 1 1
Avantages :
- Le graphe est un outil mathématique puissant - Disparition des détails inutiles
Inconvénient :
Le graphe n’est pourtant pas complètement sûr. Tous les graphes ne conviennent pas, il faut réduire notre champ d’étude pour qu’il y ait une réelle équivalence entre les graphes et les cartes. On étudiera donc les graphes connexes (à une seule composante) et planaire (que l’on peut mettre dans un plan).
¾ Réalisation en prolog
Etant donné une carte, et quatre couleurs montrons que le coloriage est possible. o Représentation d’une carte en prolog
Carte1.pl Nous avons trois prédicats :
- Le prédicat « pays » qui permet de définir un pays. - Le prédicat « couleur » qui permet de définir une couleur.
- Le prédicat « adj » qui permet de dire si un pays à une frontière commune avec un autre pays. Par exemple adj(pays1,pays2) signifie que pays1 a une frontière commune avec pays2.
o La récurrence
Notre premier programme propose donc de trouver toutes les combinaisons couleur-pays possibles pour colorier la carte proposée par récurrence.
%LES PAYS %LES COULEURS
pays(pays1). couleur(rouge). pays(pays2). couleur(vert). pays(pays3). couleur(bleu). pays(pays4). couleur(jaune). pays(pays5). %NOTION DE VOISINAGE adj(pays1,pays2). adj(pays2,pays1). adj(pays1,pays3). adj(pays3,pays1). adj(pays1,pays4). adj(pays4,pays1). adj(pays2,pays3). adj(pays3,pays2). adj(pays2,pays4). adj(pays4,pays2). adj(pays3,pays4). adj(pays4,pays3). adj(pays5,pays3). adj(pays3,pays5). adj(pays4,pays5). adj(pays5,pays4).
Une première ébauche nous donne ce résultat :
Tout d’abord on charge notre carte (carte1). Il y a en faite trois prédicats importants :
- compatible([Pays,Couleur],ListePaysCouleur) qui vérifie que le couple « pays/couleur» est compatible avec la liste de couples pays/couleur déjà trouvé. Pour chaque pays de la liste «ListePaysCouleur» on va vérifier sa position par rapport au pays à ajouter. Si ils sont adjacents (« adj(X,L1) ») on vérifie que leurs couleurs sont différentes (« L2\=Y ») et on continue la vérification sur le reste de la liste déjà formée. S’ils ne sont pas adjacents, leurs couleurs est inutiles, on continue donc directement la vérification. Le prédicat s’arrête lorsque la liste de couple pays/couleur déjà formée est vide. On enregistre alors dans un predicat (= enregistrer) le nouveau couple que l’on vient de trouver.
- colorier2(ListePCDeb) qui va chercher si il y a un pays qui n’est pas colorier et le colorier. Il parcoure l’ensemble des pays (« pays(P) ») et pour chacun d’eux vérifie qu’il n’est pas dans la liste « ListePCDeb » qui contient les couples pays/couleurs déjà trouvés. S’il n’y est pas, on choisit une couleur (« couleur(C) ») et on vérifie que le couple pays/couleur (P et C) sont compatibles avec la liste de couples déjà formée. Si tout se passe bien, on rajoute le couple à la liste déjà formée et on recommence le processus. On s’arrête lorsque tous les pays sont présents dans la liste de couples.
- colorier(R) qui se charge de rassembler les solutions. En effet le prédicat colorier2 à chaque fois qu’il trouve un couple pays/couleur valide va l’enregistrer dans le prédicat « enregistrer » (voir deuxième ligne). Lorsque colorier s’achève nous avons les solutions sous la forme :- consult(carte1).
compatible([X,Y],[]) :- assert(enregistrer([X,Y])).
%le pays à ajouter est adjacent à un des pays de la liste déjà formée compatible([X,Y],[[L1,L2]|R]) :- adj(X,L1),L2\=Y,compatible([X,Y],R). %le pays à ajouter n’est pas adjacent à un des pays de la liste déjà formée compatible([X,Y],[[L1,_]|R]) :- not(adj(X,L1)),compatible([X,Y],R). %on vérifie qu’il n’y a pas de pays non présent dans notre liste pasFini(ListeCouleur) :- pays(X),not(member([X,_],ListeCouleur)). colorier2(ListeCouleur) :- not(pasFini(ListeCouleur)).
colorier2(ListeCouleur) :- pays(P),not(member([P,_],ListeCouleur)),couleur(C), compatible([P,C],ListeCouleur), colorier2([[P,C]|ListeCouleur]). %on récupère les solutions renvoyées par solution2 et on les concatène dans une liste colorier(R) :- retractall(enregistrer(_)), colorier2([]), tout(X, enregistrer(X), R). :- dynamic temp/1.
tout(X,P,_):-P,temp(R),retractall(temp(_)),assert(temp([X|R])), fail. tout(_,_,R):-temp(R),retractall(temp(_)),assert(temp([])), !.
« enregistrer([pays1,rouge]), enregistrer([pays2,vert]), … ». colorier va rassembler toutes les solutions en une liste unique de la forme « [[pays1,rouge], [pays2,vert], […], …] ». Il utilise pour cela le prédicat « tout » donné en cours et qui fait exactement ce que l’on veut. Il faut aussi à chaque lancement du prédicat « colorier » effacer les données d’ « enregistrer» d’où le « retractall » au début de « colorier ».
• Spécification des tests
Test 1 : colorier une carte quelconque (par exemple carte1) avec quatre couleurs. Test 2 : trouver toutes les combinaisons de couleurs possibles.
• Réalisation des tests
Test 1 : nous allons colorier la carte « carte1 » qui est la suivante :
Résultat :
Ce résultat est compatible avec ce que l’on attendait. Le résultat est correct : 1 2 3 4 5 1 2 3 4 5
Test 2 : nous allons encore colorier la carte « carte1 » mais nous voulons cette fois avoir
toutes les solutions, c'est-à-dire toutes les combinaisons de pays/couleurs possibles. Pour réaliser cela, nous allons juste refuser la solution proposée et en demander une autre :
Ce résultat n’est pas celui que l’on attendait mais il correspond cependant bien à notre code. En effet lorsque l’on demande une autre solution, prolog réalise un backtracking, c'est-à-dire qu’il va faire machine arrière et revenir sur le dernier enregistrement qu’il a effectué, ici [pays5, rouge]. Il va chercher une autre solution entre autre [pays5, vert] et va l’insérer dans le prédicat « enregistrer ». Or enregistrer contient toujours les anciennes solutions (puisque l’on ne la pas effacé), donc il va concaténer « [pays5, vert] » à la précédente solution d’où notre résultat. On voit ici la « faiblesse » de l’instruction « assert ». Il permet d’enregistrer mais si un backtracking est effectué les données enregistrées ne sont pas effacées.
BILAN :
Ce premier prédicat nous permet d’avoir un résultat correct mais si nous voulons avoir toutes les solutions, il est un peu limité. De plus si nous voulons colorier une carte déjà en partie coloriée, il faut changer le code directement dans le fichier.
o La récurrence améliorée
Ceci est la version améliorée des prédicats précédents. Le prédicat « compatible » ne change pas en dehors du faite que l’on ne fait plus d’ « assert » à la fin. Ce qui change c’est le prédicat « colorier ».
- Nous passons en paramètre la liste de pays à colorier (« [L|R] »). Nous prenons les pays l’un après l’autre ce qui nous permet à tout moment de savoir où on en est du coloriage. En effet quand un pays est colorié, on le retire de la liste (ça se fait :- consult(carte1).
compatible(_,[]).
compatible([X,Y],[[L1,L2]|R]) :- adj(X,L1),L2\=Y,compatible([X,Y],R). compatible([X,Y],[L1|R]) :- not(adj(X,L1)),compatible([X,Y],R).
colorier([],ListeCouleur,ListeCouleur).
colorier([L|R],ListeCouleur,Z) :- pays(X), member(L,X), couleur(C),
automatiquement grâce à la récurrence). Le critère de fin est donc que la liste soit vide. Dans cette configuration, le prédicat « pays » n’a plus aucune raison d’être si on ne le change pas. On va donc effacer tout les prédicats « pays(_) » et les remplacer par une unique ligne : « pays([pays1,pays2,pays3,pays4,pays5]). » qui permet de dire qu’un objet est un pays si il appartient à la liste des pays. Ainsi dans le prédicat « colorier » on va vérifier que l’objet à colorier est bien un pays, on récupère notre liste de pays (« pays(X) ») et on vérifie que notre objet appartient à la liste (« member »)
- Notre troisième argument est une liste « tampon ». Elle nous permet de récupérer notre résultat final via la pile.
• Spécification des tests
Test 1 : colorier une carte quelconque (par exemple carte1) avec quatre couleurs. Test 2 : trouver toutes les combinaisons de couleurs possibles.
Test 3 : colorier une carte déjà en partie coloriée Test 4 : tenter de colorier un objet qui n’est pas un pays
• Réalisation des tests
Test 1 :
Ce résultat est correct (voir ci-dessus).
Test 2 :
Ce résultat est compatible à ce que l’on attendait. Chaque ligne nous donne bien une nouvelle combinaison de couleurs. On vérifie également que vu la configuration de la carte, le pays1 peut prendre 4 couleurs, le pays2 ne peut alors en prendre que 3, le pays 3 peut en prendre deux et le pays4 ne peut alors choisir qu’une couleur. Le pays5 ne doit pas être de la même couleur que pays4 et pays3 donc il peut prendre 2 couleurs.
Au total on a donc 4*3*2*1*2 = 48 combinaisons possibles. Le prédicat nous renvoie bien 48 possibilités si l’on refuse toutes les solutions.
Test 3 : colorions la carte1 sachant que le pays3 est déjà colorier en vert.
Ce résultat est conforme à nos attentes. On voit que si l’on refuse les solutions, le couple [pays3, vert] est toujours présent. De plus les autres couleurs de pays sont correctes.
Test 4 : on essaie de colorier un objet qui n’est pas un pays = pays7
Ce résultat est conforme à nos attentes. o Les contraintes
Pour bien modéliser ce problème sous forme de contraintes, il nous faut tout d’abord identifier les variables, leurs domaines et les contraintes qui les lient.
Les inconnues ici se sont les couleurs et il y en a une par pays. Elles peuvent prendre comme valeur une des quatre couleurs.
Si l’on a « n » pays, on défini L={X1, X2, …, Xn}, c'est-à-dire une variable Xi par
région i à colorier. Pour tout Xi on a domaine(Xi) = {vert, jaune, bleu, rouge} et la contrainte
sur les frontières devient :
C = { Xi ≠ Xj | Xi et Xj soient deux variables différentes et Xi et Xj sont voisins}
Par la suite on considérera la carte1.
%Equivalence entre les chiffres et les couleurs couleur(1,rouge).
couleur(2,vert). couleur(3,bleu). couleur(4,jaune).
% prédicat qui nous permet d'avoir les solutions sous la forme d'une liste sol([],_,ListePaysCouleurs,ListePaysCouleurs).
sol([P|D],[L|R],ListePaysCouleurs,Z):-couleur(L,X),sol(D,R,[[P,X]|ListePaysCouleurs],Z). % col recupere la liste renvoyé par le prédicat "sol"
col(Rep):-L=[X1,X2,X3,X4,X5],L in 1..4, X1#\=X2, X1#\=X3, X1#\=X4, X2#\=X3, X4#\=X2, X4#\=X3, X5#\=X3, X5#\=X4, labeling(L), sol([pays1,pays2,pays3,pays4,pays5],L,[],Rep).
Toutes les relations adj(paysi,paysj) ont été traduites sous forme d’inégalité et nous
laissons prolog se charger de la résolution (« labeling(L) »). Cependant la solution qu’il nous renvoie est constituée de chiffre (car L in 1..4). Il faut donc avoir une table de correspondance entre ces chiffres et les couleurs. Le prédicat « sol » s’occupe de faire cette correspondance.
Le prédicat « sol » prend en paramètre la liste des pays à colorier, la liste des solutions renvoyée par prolog, une liste qui contiendra les couples pays/couleur et une autre liste qui servira de tampon pour récupérer les résultats via la pile. Elle va prendre le premier élément de la liste solution et faire la correspondance avec la couleur (« couleur(L,X) » où X est la couleur). Elle lie alors cette couleur au pays correspondant et ainsi de suite. Lorsqu’il n’y a plus de pays (et plus de solution dans la liste), on renvoie la liste solution via le 4ème argument.
Test : on colorie la carte1
Ce résultat est conforme à nos attentes. Il nous renvoie bien les 48 possibilités de coloriage.
o 5 couleurs
Le but de cette troisième partie est de prouver que pour une carte donnée, cinq couleurs suffisent pour la colorier sans que deux frontières soient de la même couleur. Notre objectif est différent des cas précédents où on trouvait la couleur de chaque pays. Grâce à des règles prédéfinies, nous allons réduire la carte jusqu’à ce qu’il ne reste que cinq pays. Si il y a cinq pays, il y aura au plus cinq couleurs.
Les règles de réduction de carte
Il faut réduire le nombre de régions sans altérer le nombre de couleurs. Il existe cinq cas : Cas 1 :
Cas 2 :
On fusionne la partie intérieure. Toute manière de colorier la carte avec au moins 2 couleurs pourra être étendu à la région fusionnée.
Région à 2 voisins. On la fusionne à l’une des deux. Si l’on peut colorier la nouvelle carte avec au moins trois couleurs, l’ancienne pourra l’être aussi. La partie engloutie sera coloriée différemment des deux autres.
Cas 3 :
Cas 4 :
Cas 5 :
En effet il faut quatre couleurs pour la nouvelle carte (3 couleurs pour l’extérieur et 1 pour la partie fusionnée en gris). On dé fusionne en donnant la 5ème couleur à la région centrale et en gardant la même couleur pour les deux autres. On obtient :
Région à 3 voisins. On la fusionne à l’un de ses voisins. Si l’on peut colorier la nouvelle carte avec au moins quatre couleurs, la carte d’origine aussi. La partie engloutie sera coloriée différemment des trois autres.
Région à 4 voisins. On la fusionne à l’un de ses voisins. Si l’on peut colorier la nouvelle carte avec au moins cinq couleurs, la carte d’origine aussi. La partie engloutie sera coloriée différemment des quatre autres.
Région à 5 voisins. Il existe une paire de régions qui ne se touchent pas. On fusionne ces trois régions. Si l’on peut colorier la nouvelle carte avec au moins cinq couleurs, la carte d’origine aussi.
Le code prolog et les explications
Pour étudier ce problème nous avons besoin d’outils qui nous permettent de travailler sur les listes. Nous avons placé tous ses outils dans un fichier nommé « biblio.pl ».
Biblio.pl
1. union(L1,L2,R)
Ce prédicat permet d’unir mathématiquement la liste L1 et L2 sachant que L1 a moins d’éléments que L2. Pour réaliser cela il va prendre la liste L2 comme base et y ajouter tous les éléments de L1 qui n’y soit pas déjà. Pour chacun des éléments de la liste L1 il va vérifier s’il est présent dans la liste L2 (« member(L1,L)»). S’il n’est pas présent, on le rajoute
(« union([L1|R1],L,[L1|R]) ») et on continue la concaténation sur le reste de la liste L1. S’il
est présent, on ne fait rien et on continue la concaténation. L’union se termine lorsque la liste
L1 est vide, dans ce cas on renvoie la liste L2 comme solution via le 3ème argument. 2. elimineAdj(X,L)
L est une liste de pays, X est un de ses pays.
%le prédicat elimine permet d’éliminer l’élément X d’une liste (= 2ème argument) %il renvoie la liste résultante dans le 3ème argument
elimine(X,[X|R],R).
elimine(X,[L|R],[L|F]) :- elimine(X,R,F).
%le prédicat union(L1,L2,R) unie (mathématiquement)les listes L1 à L2 et renvoie le résultat %dans R.
union([],L,L).
union([L1|R1],L,[L1|R]) :- not(member(L1,L)), union(R1,L,R). union([L1|R1],L,R) :- member(L1,L), union(R1,L,R).
%le prédicat elimineAdj permet d’éliminer dans le prédicat adj pour chaque pays (de la liste %passée en paramètre = [L|R]) l’élément X de la liste des voisins
elimineAdj(X,[]).
elimineAdj(X,[L|R]) :- L#\=X, adj(L,Vois), member(X,Vois), elimine(X,Vois,Res), retractall(adj(L,_)), assert(adj(L,Res)), elimineAdj(X,R). elimineAdj(X,[L|R]) :- adj(L,Vois), not(member(X,Vois)), elimineAdj(X,R).
%le prédicat recupVoisin permet de récupérer dans la liste passée en paramètre (= [L|R]) % un des voisins de X. il le renvoie dans le troisième argument
recupVoisin(X,[L|R],L) :- L#\=X, adj(L,Vois), member(X,Vois).
recupVoisin(X,[L|R],Z) :- adj(L,Vois), not(member(X,Vois)), recupVoisin(X,R,Z).
%Le predicat miseAJourAdj(L1,L2) met à jour le prédicat "adj" pour chaque pays de la liste L2. %il va unir la liste L1 à la liste des voisins du pays considéré.
miseAJourAdj(_,[]).
miseAJourAdj(VoisX,[L|R]) :- adj(L,VoisL), union(VoisX,VoisL,V), retractall(adj(L,_)), assert(adj(L,V)), miseAJourAdj(VoisX,R).
Ce prédicat va prendre chacun des pays de la liste L et vérifier si X en est un voisin. Pour réaliser cela il suffit de récupérer la liste de voisin du pays (« adj(L,Vois) ») et vérifier que X y soit(« member(X,Vois) »). Bien sûr il est inutile de faire la vérification sur X lui-même (L#\=X). Il y a alors deux cas :
- X appartient à la liste de voisins. Dans ce cas on le retire de cette liste (« elimine(X,Vois,Res) »). Il faut alors mettre à jour le prédicat « adj » pour le pays considéré. On efface donc le prédicat adj pour le pays considéré
(« retractall(adj(L,_)) ») ici le pays L et on enregistre les nouvelles données pour
ce pays (« assert(adj(L,Res)) ») c'est-à-dire la nouvelle liste de voisins privé de X. On continue ce processus sur le reste des pays de la liste passée en paramètre. - X n’appartient pas à la liste de voisins. Dans ce cas, on ne fait rien et on continue
ce processus sur le reste des pays de la liste passée en paramètre.
3. recupVoisin(X,L,R)
L est une liste de pays, X est un pays et R est la variable qui contiendra un des voisins de X
à la fin de la récurrence.
Ce prédicat va prendre chacun des pays de la liste L et vérifier s’il est voisin de X. Si c’est le cas on le renvoie dans le troisième argument (« recupVoisin(X,[L|R],L) ») sinon on continue.
4. miseAJourAdj(L1,L2)
Ce prédicat met à jour le prédicat "adj" pour chaque pays de la liste L2 en unifiant la liste L1 à la liste des voisins du pays considéré (« union(VoisX,VoisL,V) »). On enregistre alors les nouvelles données dans le prédicat « adj »
Voici notre carte en prolog : %les différents pays
pays(pays1). pays(pays2). pays(pays3). pays(pays4). pays(pays5). pays(pays6). Pays(pays7) pays(pays8). pays(pays9). pays(pays10). pays(pays11). pays(pays12). pays(pays13). pays(pays14). :- dynamic adj/2. adj(pays1,[pays7,pays9,pays10,pays11,pays12]). adj(pays2,[pays8,pays12,pays14]). adj(pays3,[pays7,pays10,pays14]). adj(pays4,[pays9,pays11,pays14]). adj(pays5,[pays8,pays11,pays12]). adj(pays6,[pays7,pays13,pays14]). adj(pays7,[pays1,pays3,pays6,pays10,pays13,pays14]). adj(pays8,[pays2,pays5,pays12]). adj(pays9,[pays1,pays4,pays10,pays11,pays14]). adj(pays10,[pays1,pays3,pays7,pays9,pays14]). adj(pays11,[pays1,pays4,pays5,pays9,pays12]). adj(pays12,[pays1,pays2,pays5,pays8,pays11,pays13,pays14]). adj(pays13,[pays6,pays7,pays12,pays14]). adj(pays14,[pays2,pays3,pays4,pays6,pays7,pays9,pays10,pays12,pays13]).
Nous avons toujours le prédicat « pays » qui nous permet de savoir si un élément est un pays ou non. Nous avons modifié le prédicat « adj » qui est de la forme :
« adj(pays, liste des voisins de ce pays). » Le code principal.
Explications
1. reduction(Carte,R)
« Carte » est une liste de pays et R est la liste finale des pays lorsque toutes les réductions ont été effectuées.
On s’arrête lorsque le nombre de pays dans « Carte » est strictement inférieur à 6 (« length < 6 »). Le prédicat « reduction » liste tout les cas de réduction cité précédemment.
:- consult(carte14). :- consult(biblio).
%s’il reste moins de six pays sur la carte, cinq couleurs suffisent. C’est terminé ! reduction(Carte,Carte) :- length(Carte,L), L<6.
%cas 1 :
reduction(Carte,Z) :- pays(X), member(X,Carte), adj(X,Vois), length(Vois,L), L#=1, elimineAdj(X,Carte), elimine(X,Carte,Res), reduction(Res,Z). %cas 2 :
reduction(Carte,Z) :- pays(X), member(X,Carte), adj(X,Vois), length(Vois,L), L#=2, recupVoisin(X,Carte,M), adj(X,VoisX), elimine(M,VoisX,VoisFin), miseAJourAdj(VoisFin,[M]), miseAJourAdj([M],VoisFin),
elimineAdj(X,Carte), elimine(X,Carte,Res), reduction(Res,Z). %cas 3 :
reduction(Carte,Z) :- pays(X), member(X,Carte), adj(X,Vois), length(Vois,L), L#=3, recupVoisin(X,Carte,M), adj(X,VoisX), elimine(M,VoisX,VoisFin), miseAJourAdj(VoisFin,[M]), miseAJourAdj([M],VoisFin),
elimineAdj(X,Carte), elimine(X,Carte,Res), reduction(Res,Z). %cas 4 :
reduction(Carte,Z) :- pays(X), member(X,Carte), adj(X,Vois), length(Vois,L), L#=4, recupVoisin(X,Carte,M), adj(X,VoisX), elimine(M,VoisX,VoisFin), miseAJourAdj(VoisFin,[M]), miseAJourAdj([M],VoisFin),
elimineAdj(X,Carte), elimine(X,Carte,Res), reduction(Res,Z). %cas 5 :
reduction(Carte,Z) :- pays(X), member(X,Carte), adj(X,Vois), length(Vois,L), L#=5, recupVoisin(X,Carte,M), adj(X,VoisX), elimine(M,VoisX,VoisFin), miseAJourAdj(VoisFin,[M]), miseAJourAdj([M],VoisFin),
recupVoisin(X,VoisFin,N), adj(M,VoisM), elimine(N,VoisM,VoisF), miseAJourAdj(VoisF,[N]), miseAJourAdj([N],VoisF),
elimineAdj(M,Carte), elimine(M,Carte,Res1), elimineAdj(X,Res1), elimine(X,Res1,Res2), reduction(Res2,Z).
Pour chacun des pays de notre liste « Carte », nous allons compter combien de voisins il possède. S’il en a 1 on entre dans le cas 1, 2 dans le cas 2, etc.
Si l’on est dans le cas 1 il nous faut fusionner ce pays avec son voisin ce qui correspond dans ce cas à effacer ce pays de notre carte. Effacer de notre carte c’est l’effacer de la liste des voisins de son voisin (« elimineAdj(X,Carte) ») et l’effacer de la liste « Carte » (« elimine(X,Carte,Res) »). On continue la réduction sur la nouvelle carte privé de X (= Res).
Si l’on est dans le cas 2, 3 ou 4 il nous faut fusionner ce pays que l’on nommera P avec un de ses voisins ce qui correspond dans ce cas à :
- récupérer un de ses voisins (« recupVoisin(X,Carte,M) »). Ici M.
- rajouter aux voisins du pays M la liste des voisins du pays X. (« miseAJourAdj(VoisFin,[M]) »).
- rajouter ce pays M à la liste des voisins des voisins du pays X. (« miseAJourAdj([M],VoisFin)»).
- effacer le pays X de la liste des voisins de ses anciens voisins (« elimineAdj(X,Carte) ») et l’effacer de la liste « Carte » (« elimine(X,Carte,Res) »)
On continue la réduction sur la nouvelle carte privé de X (= Res).
Le cas 5 est particulier car il faut fusionner notre pays à deux de ses voisins. Il faut donc effacer deux pays de notre carte. Pour cela on va récupérer deux voisins et répéter les opérations des cas 2 à 4 sur chacun d’eux.
Exemple :
Résultat :
Il reste bien 5 pays, ce qui est compatible avec ce que l’on attendait.
Si l’on met un espion sur le prédicat « reduction » on peut voir l’évolution de la carte et des pays qui sont supprimés.
| ?- spy reduction
Spy point reduction/2 has been set. yes {Debug mode} | ?- reduction([pays1,pays2,pays3,pays4,pays5,pays6,pays7,pays8,pays9,pays10,p$ Call: reduction([pays1,pays2,pays3,pays4,pays5,pays6,pays7,pays8,pays9,pays10,.. .],_560210) ?l Call: reduction([pays1,pays3,pays4,pays5,pays6,pays7,pays8,pays9,pays10,pays11 ,...],_560210) ?l Call: reduction([pays1,pays4,pays5,pays6,pays7,pays8,pays9,pays10,pays11, pays12,...],_560210) ?l Call: reduction([pays1,pays5,pays6,pays7,pays8,pays9,pays10,pays11,pays12, pays13,...],_560210) ?l Call: reduction([pays1,pays6,pays7,pays8,pays9,pays10,pays11,pays12, pays13,pays14],_560210) ?l Call: reduction([pays1,pays7,pays8,pays9,pays10,pays11,pays12,pays13, pays14],_560210) ?l Call: reduction([pays1,pays7,pays9,pays10,pays11,pays12,pays13, pays14],_560210) ?l Call: reduction([pays1,pays9,pays10,pays11,pays12,pays13,pays14],…) ?l Call: reduction([pays1,pays9,pays11,pays12,pays13,pays14],_560210) ?l Call: reduction([pays1,pays11,pays12,pays13,pays14],_560210) ?l
Dans l’ordre de disparition on a donc : pays2, pays3, pays4, pays5, pays6, pays8, pays7, pays10 et pays9.
On peut aussi vérifier que les voisins ont bien été mis à jour :