Вы находитесь на странице: 1из 15

GROLEAU William H4304

MURCY Eddy TP Prolog


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 :

a b c
c
b a

b 1
a

c 1 1

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

1/15
GROLEAU William H4304
MURCY Eddy TP Prolog
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

%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).
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.

2/15
GROLEAU William H4304
MURCY Eddy TP Prolog

Une première ébauche nous donne ce résultat :

:- 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([])), !.
temp([]).

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

3/15
GROLEAU William H4304
MURCY Eddy TP Prolog
« 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 :

5
4
3
1
2

Résultat :

Ce résultat est compatible avec ce que l’on attendait. Le résultat est correct :

5
4
3
1
2

4/15
GROLEAU William H4304
MURCY Eddy TP Prolog
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

:- 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),
compatible([L,C],ListeCouleur), colorier(R,[[L,C]|ListeCouleur],Z).

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

5/15
GROLEAU William H4304
MURCY Eddy TP Prolog
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.

6/15
GROLEAU William H4304
MURCY Eddy TP Prolog
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).

7/15
GROLEAU William H4304
MURCY Eddy TP Prolog
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 :
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.

™ Cas 2 :

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.
8/15
GROLEAU William H4304
MURCY Eddy TP Prolog
™ Cas 3 :

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.

™ Cas 4 :

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.

™ Cas 5 :

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.

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 :

9/15
GROLEAU William H4304
MURCY Eddy TP Prolog
ƒ 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 ».

%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).

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.

10/15
GROLEAU William H4304
MURCY Eddy TP Prolog
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]).

11/15
GROLEAU William H4304
MURCY Eddy TP Prolog
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.

:- 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).

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.

12/15
GROLEAU William H4304
MURCY Eddy TP Prolog
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 :

Soit la carte suivante qui correspond au fichier « carte14.pl » :

13/15
GROLEAU William H4304
MURCY Eddy TP Prolog
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.

14/15
GROLEAU William H4304
MURCY Eddy TP Prolog
On peut aussi vérifier que les voisins ont bien été mis à jour :

Ce résultat est correct. La carte finale réduite est donc

15/15

Вам также может понравиться