À la recherche du tueur sur Prolog

Chaque dimanche dans notre entreprise, il est de coutume d'organiser des quiz amusants, c'est l'un d'entre eux.

Devinette


Pour trouver le tueur de M. Boddy, vous devez savoir où se trouvait chaque personne et quelles armes se trouvaient dans la pièce. Des indices sont dispersés tout au long du quiz (vous ne pouvez pas répondre à la première question avant d'avoir lu les dix).

  • Imaginez d'abord les suspects. Il y a trois hommes (George, John, Robert) et trois femmes (Barbara, Christina, Yolanda). Chaque personne est dans une pièce séparée (salle de bain, salle à manger, cuisine, salon, cellier, bureau). Des armes suspectes ont été trouvées dans chaque pièce (sac, arme à feu, gaz, couteau, poison, corde). Question: qui a été trouvé dans la cuisine?
  • Astuce 1. Avec un homme dans la cuisine, il n'y a ni corde, ni couteau, ni sac. L'arme n'est pas une arme à feu. Question: Quelles armes ont été trouvées dans la cuisine?

  • Indice 2. Barbara est soit dans le bureau, soit dans la salle de bain, et Yolanda est dans une autre des deux chambres nommées. Dans quelle pièce Barbara a-t-elle trouvé?
  • Astuce 3. L'homme avec le sac n'est ni Barbara ni George, et il n'était ni dans la salle de bain ni dans la salle à manger. Qui avait le sac?
  • Astuce 4. Une femme avec une corde a été trouvée dans le bureau. C'est qui?
  • Astuce 5. L'arme dans le salon appartient à John ou à George. Quel genre d'arme dans le salon?
  • Astuce 6. Il n'y avait pas de couteau dans la salle à manger. Où était le couteau?
  • Indice 7. Yolanda n'était ni dans le bureau ni dans le garde-manger avec les armes appropriées pour ces pièces. Quel genre d'arme possède Yolanda?
  • Astuce 8. George a trouvé une arme à feu. Quelle pièce?
  • On a découvert que M. Boddy était gazé dans le garde-manger. Le suspect dans cette pièce était un tueur. C'est qui?

Je me fraye un chemin sur ces puzzles (en fait à partir de presque tous les puzzles). Cela pourrait prendre des heures et des heures de réflexion, mais Prolog vient toujours à la rescousse! Voyons comment cela aide à résoudre de tels problèmes de raisonnement.

Prolog 101


Installer SWI-Prolog


~> swipl Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.6.6) Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. Please visit http://www.swi-prolog.org for details. For help, use ?- help(Topic). or ?- apropos(Word). ?- write('Hello, World!'). Hello, World! true. ?- write('Hello,'), nl, write('world'). Hello, world true. ?- X is 3*4 + 2. X = 14. 

  • swipl - Interprète Prolog
  • write est appelé un foncteur, et la représentation write/1 signifie qu'il faut 1 argument (le même concept dans Erlang et Elixir pour ajouter le nombre d'arguments à un nom de fonction)
  • nl utilisé pour imprimer une nouvelle ligne
  • la séquence de commandes est séparée par des virgules, qui remplacent également l'opérateur AND
  • l'opérateur d'affectation is suivi d'une expression mathématique
  • les variables sont écrites en X majuscule, pas x

Base de connaissances


L'essence de Prolog consiste à énoncer des faits, à les compiler et à les demander.

Création du fichier hello.pl :

 friend(john, julia). friend(john, jack). friend(julia, sam). friend(julia, molly). loves(john, julia). loves(julia, sam). loves(sam, julia). male(brad). male(john). male(jim). male(alfred). female(marry). child(brad, alfred). child(john, jim). child(john, marry). 

  • nous utilisons [hello]. pour le chargement [hello]. : faites attention au point à la fin
  • listing répertorie tous les faits dans la base de connaissances

 ?- [hello]. % hello compiled 0.00 sec, 3 clauses true. ?- listing(friend). friend(john, julia). friend(john, jack). friend(julia, sam). friend(julia, molly). true. ?- listing(loves). loves(john, julia). loves(julia, sam). loves(sam, julia). true. 

Demande de faits


Après avoir énoncé les faits dans la base de connaissances, nous pouvons aller plus loin et poser des questions sur la vérité des faits, ainsi que sur les conclusions qui peuvent en être tirées.

 ?- friend(john, julia). true . ?- friend(john, jack). true. ?- loves(john, julia). true. ?- loves(john, sam). false. 

Nous pouvons inventer des questions plus complexes. Par exemple, qui est ami avec John ou qui aime Julia.

 ?- friend(john, Who). Who = julia ; Who = jack. 

 ?- listing(child). child(brad, alfred). child(john, jim). child(john, mary). true. ?- child(john, X). X = jim ; X = mary. 

John est-il dans la zone d'amis?


Nous avons établi l'amitié de John avec Julia ( friend(john, julia) ), mais pour Prolog, cela ne signifie pas que Julia est amie avec John: vous devez ajouter un autre fait friend(julia, john) . Nous avons également indiqué qui a des enfants et ne voulons évidemment pas dupliquer le code, en indiquant séparément les parents de chaque enfant. Nous ne voulons pas écrire quelque chose comme

 child(brad, alfred). child(john, jim). child(john, mary). parent(alfred, brad). parent(jim, john). parent(mary, john). 

Prolog permet d'éviter la duplication avec des règles de conclusion logiques:

 rule :- stmt1, stmt2,... 

La règle est vraie si toutes les déclarations internes sont vraies (répertoriées et repliées logiquement avec une virgule).

 friend(X, Y) :- friend(Y,X). parent(X, Y) :- child(Y,X). father(X, Y) :- child(Y,X), male(X). mother(X, Y) :- child(Y,X), female(X). friendzoned(X) :- loves(X, Y), \+ loves(Y,X). 

  • friend(X,Y) vrai pour friend(Y,X )
  • parent(X,Y) vrai lorsque child(Y,X)
  • father(X,Y) vrai avec parent(X,Y) et ensemble male(X)
  • mother(X,Y) vraie lorsque le parent(X,Y) et la female(X)
  • friendzoned(X) vrai si X aime SOMEONE Y et Y n'aime pas X (remarquez la variable cachée Y?)

 ?- friend(julia, john). true . ?- male(jim). true. ?- parent(jim,X). X = john. ?- father(jim, X). X = john. ?- mother(X, john). X = marry. ?- mother(marry,X). X = john. ?- mother(marry, john). true. ?- loves(julia, X). X = sam. ?- friendzoned(julia). false. ?- friendzoned(john). true. 

Ok, maintenant nous avons toutes les connaissances nécessaires. Pratiquons la coloration de la carte.

Coloriage carte


Commençons par le problème mathématique bien connu. Il est nécessaire qu'aucune zone adjacente n'ait la même couleur.



Par conséquent, le raisonnement doit être tel, nous avons trois choses:

  1. Les variables sont les zones que nous voulons coloriser: A, B, C, D, E.
  2. Domaine - une plage de valeurs pouvant être affectées à des variables: rouge, bleu, vert.
  3. La limitation est que les zones adjacentes ne peuvent pas être de la même couleur.

Domaine


Définissez le domaine de nos régions (rouge, vert, bleu).

 color(red). color(green). color(blue). 

C’est tout.

Nous demandons une solution


 colorify(A,B,C,D,E) :- color(A), color(B), color(C), color(D), color(E), \+ A=B, \+ A=C, \+ A=D, \+ A=E, \+ B=C, \+ C=D, \+ D=E. 

Ici, nous définissons la solution comme une règle à colorify avec cinq variables A, B, C, D, E, et à l'intérieur de la règle, nous attribuons la couleur de domaine (rouge, bleu, vert) pour les variables et définissons les restrictions que A n'est pas égal à B, pas égal à C ... et etc.

\+ X=Y signifie que X n'est pas égal à Y

Prolog continuera de générer des valeurs jusqu'à ce qu'il trouve une option qui satisfasse à la règle avec des restrictions.

 ?- [mapcoloring] | . true. ?- colorify(A,B,C,D,E) | . A = red, B = D, D = green, C = E, E = blue ; A = red, B = D, D = blue, C = E, E = green ; A = green, B = D, D = red, C = E, E = blue ; A = green, B = D, D = blue, C = E, E = red ; A = blue, B = D, D = red, C = E, E = green ; A = blue, B = D, D = green, C = E, E = red 

 color(red). color(green). color(blue). colorify(A,B,C,D,E) :- color(A), color(B), color(C), color(D), color(E), \+ A=B, \+ A=C, \+ A=D, \+ A=E, \+ B=C, \+ C=D, \+ D=E. 

... mais nous ne colorions pas les images ici, mais recherchons le tueur.

Le meurtre


Imaginez d'abord les suspects. Il y a trois hommes (George, John, Robert) et trois femmes (Barbara, Christina, Yolanda). Chaque personne est dans une pièce séparée (salle de bain, salle à manger, cuisine, salon, cellier, bureau). Des armes suspectes ont été trouvées dans chaque pièce (sac, arme à feu, gaz, couteau, poison, corde).

Qui a été trouvé dans la cuisine?

Domaine


De cela, nous pouvons conclure que nous avons cinq domaines: man , woman , person ou suspect, location et weapons , et nos variables (A, B, C, D, E, F) devraient représenter à la fois la personne, le lieu et l'arme avec quelques limitations qui seront révélées dans les prochains conseils.

 man(george). man(john). man(robert). woman(barbara). woman(christine). woman(yolanda). person(X):- man(X). person(X):- woman(X). location(bathroom). location(dining). location(kitchen). location(livingroom). location(pantry). location(study). weapon(bag). weapon(firearm). weapon(gas). weapon(knife). weapon(poison). weapon(rope). 

La règle uniq_ppl génère des valeurs uniques pour nos variables.

 uniq_ppl(A,B,C,D,E,F):- person(A), person(B), person(C), person(D), person(E), person(F), \+A=B, \+A=C, \+A=D, \+A=E, \+A=F, \+B=C, \+B=D, \+B=E, \+B=F, \+C=D, \+C=E, \+C=F, \+D=E, \+D=F, \+E=F. 

Solution


Nous commençons par définir la règle d'un tueur avec des personnes uniques dans les lieux et des personnes uniques avec des armes, et allons maintenant indiquer la relation entre les personnes dans les lieux avec ceux qui ont des armes

Veuillez noter que nous avons encore six suspects.

Entrée


 murderer(X) :- uniq_ppl(Bathroom, Dining, Kitchen, Livingroom, Pantry, Study), uniq_ppl(Bag, Firearm, Gas, Knife, Poison, Rope), 

Pour parler facilement de variables telles que la salle de bain, la salle à manger, les armes à feu, le gaz, nous déterminons immédiatement:

  • Salle de bain - c'est le même suspect (homme ou femme) dans la salle de bain
  • Armes à feu - c'est le même suspect (homme ou femme) avec une arme à feu
  • et ainsi de suite ... vous pouvez l'imaginer comme une grille

Maintenant, nous continuons d'ajouter des restrictions après la dernière virgule de la règle du murderer .

Astuce 1


Avec un homme dans la cuisine, il n'y a ni corde, ni couteau, ni sac. L'arme n'est pas une arme à feu. Quelles armes trouve-t-on dans la cuisine?

 % 2. Clue 1: The man in the kitchen was not found with the rope, knife, or bag. % Which weapon, then, which was not the firearm, was found in the kitchen? man(Kitchen), \+Kitchen=Rope, \+Kitchen=Knife, \+Kitchen=Bag, \+Kitchen=Firearm, 

Ici, nous disons que la variable Kitchen satisfait le fait de l' man (défini dans notre domaine), et déclarons que peu importe qui est la personne dans la cuisine, il n'a aucun des éléments suivants: Rope , Knife , Bag , Firearm .

Indice 2


Indice 2. Barbara est soit dans le bureau, soit dans la salle de bain, et Yolanda est dans une autre des deux chambres nommées. Dans quelle pièce Barbara a-t-elle trouvé?

Ainsi, on peut dire qu'il y a une woman au bureau et dans la salle de bain, et ce n'est pas Christina, et on raye aussi les autres options pour Barbara et Yolanda (cuisine, salle à manger, salon, cellier).

 % % 3. Clue 2: Barbara was either in the study or the bathroom; Yolanda was in the other. % % Which room was Barbara found in? woman(Bathroom), woman(Study), \+christine=Bathroom, \+christine=Study, \+barbara=Dining, \+barbara=Kitchen, \+barbara=Livingroom, \+barbara=Pantry, 

Astuce 3


L'homme au sac n'est ni Barbara ni George, et il n'était ni dans la salle de bain ni dans la salle à manger. Qui avait le sac?

 % % 4. Clue 3: The person with the bag, who was not Barbara nor George, was not in the bathroom nor the dining room. % % Who had the bag in the room with them? \+barbara=Bag, \+george=Bag, \+Bag=Bathroom, \+Bag=Dining, 

Astuce 4


Une femme avec une corde a été trouvée dans le bureau. C'est qui?

 % % 5. Clue 4: The woman with the rope was found in the study. % % Who had the rope? woman(Rope), Rope=Study, 

Astuce 5


Astuce 5. L'arme dans le salon appartient à John ou à George. Quel genre d'arme dans le salon?

 man in Livingroom Livingroom isn't robert % % 6. Clue 5: The weapon in the living room was found with either John or George. % % What weapon was in the living room? man(Livingroom), \+Livingroom=robert, 

Astuce 6


Il n'y avait pas de couteau dans la salle à manger. Où était le couteau?

 % % 7. Clue 6: The knife was not in the dining room. % % So where was the knife? \+Knife=Dining, 

Astuce 7


Indice 7. Yolanda n'était ni dans le bureau ni dans le garde-manger. Quelle arme est dans la chambre de Yolanda?

 % % 8. Clue 7: Yolanda was not with the weapon found in the study nor the pantry. % % What weapon was found with Yolanda? \+yolanda=Pantry, \+yolanda=Study, 

Astuce 8


George a trouvé une arme à feu.

 % % 9. Clue 8: The firearm was in the room with George. % % In which room was the firearm found? Firearm=george, 

Astuce 9


On a découvert que M. Boddy était gazé dans le garde-manger. Le suspect dans cette pièce était un tueur. C'est qui?

 % % 10. It was discovered that Mr. Boddy was gassed in the pantry. The suspect found in that room was the murderer. % % Who, then, do you point the finger towards? Pantry=Gas, Pantry=X, write("KILLER IS :"), write(X), nl, writeanswers(Bathroom, Dining, Kitchen, Livingroom, Pantry, Study, Bag, Firearm, Gas, Knife, Poison, Rope). 

writeanswers correspondre le gaz, le garde-manger et le tueur, puis utilisez l' write pour write writeanswers .

 writeanswers(Bathroom, Dining, Kitchen, Livingroom, Pantry, Study, Bag, Firearm, Gas, Knife, Poison, Rope):- write("Bathroom: "), write(Bathroom), nl, write("Dining: "), write(Dining), nl, write("Livingroom: "), write(Livingroom), nl, write("Pantry: "), write(Pantry), nl, write("Study: "), write(Study), nl, write("Kitchen: "), write(Kitchen), nl, write("Knife: "), write(Knife), nl, write("Gas: "), write(Gas), nl, write("Rope: "), write(Rope), nl, write("Bag: "), write(Bag), nl, write("Poison: "), write(Poison), nl, write("Firearm: "), write(Firearm), nl. 

Qui est le tueur?


  ?- [crime2]. true. ?- murderer(X). KILLER IS :christine Bathroom: yolanda Dining: george Livingroom: john Pantry: christine Study: barbara Kitchen: robert Knife: yolanda Gas: christine Rope: barbara Bag: john Poison: robert Firearm: george X = christine ; 

Le code est publié ici . Cela aurait probablement pu être beaucoup mieux puisque je ne suis pas un expert en Prolog :)

Source: https://habr.com/ru/post/fr434172/


All Articles