Est-ce que les problèmes de type "fréquentation des partis" sont résolus dans Prolog? Par exemple:
Burdock Muldoon et Carlotta Pinkstone ont tous deux déclaré qu'ils viendraient si Albus Dumbledore venait. Albus Dumbledore et Daisy Dodderidge ont tous deux déclaré qu'ils viendraient si Carlotta Pinkstone venait. Albus Dumbledore, Burdock Muldoon et Carlotta Pinkstone ont tous dit qu'ils viendraient si Elfrida Clagg venait. Carlotta Pinkstone et Daisy Dodderidge ont toutes deux déclaré qu'elles viendraient si Falco Aesalon venait. Burdock Muldoon, Elfrida Clagg et Falco Aesalon ont tous dit qu'ils viendraient si Carlotta Pinkstone et Daisy Dodderidge venaient tous les deux. Daisy Dodderidge a dit qu'elle viendrait si Albus Dumbledore et Burdock Muldoon venaient tous les deux. Qui doit être persuadé d'assister à la fête afin de s'assurer que tous ses invités y assistent?
J'ai essayé d'exprimer cela dans GNU Prolog:
attend(BM) :- attend(AD).
attend(CP) :- attend(AD).
attend(AD) :- attend(CP).
attend(DD) :- attend(CP).
attend(AD) :- attend(EC).
attend(BM) :- attend(EC).
attend(CP) :- attend(EC).
attend(CP) :- attend(FA).
attend(DD) :- attend(FA).
attend(BM) :- attend(CP),attend(DD).
attend(EC) :- attend(CP),attend(DD).
attend(FA) :- attend(CP),attend(DD).
attend(DD) :- attend(AD),attend(BM).
attend(FA). /* try different seed invitees in order to see if all would attend*/
/* input:
write('invited:'),nl,
attend(X),write(X),nl,
fail.*/
Je rencontre un débordement de pile (sans jeu de mots) et je n'ai aucune connaissance de l'évaluation de prologue, c'est pourquoi je demande.
De manière générale, ce problème peut être transposé dans la formule de satisfaction booléenne CNF (avec 6 variables booléennes). Par conséquent, la perspective prologue est-elle valable?
la source
attend(BM) :- attend(AD).
c'est exactement la même chose queattend(X) :- attend(Y).
Réponses:
Pour résoudre un problème avec Prolog, comme avec tout langage de programmation, qu'il soit déclaratif ou impératif, vous devez penser à la représentation de la solution et de l'entrée.
Comme il s'agit d'une question de programmation, elle aurait été populaire sur StackOverflow.com où les programmeurs résolvent les problèmes de programmation. Ici, j'essaierais d'être plus scientifique.
Pour résoudre le problème dans l'OP, il faut inverser la relation définie par les dépendances indiquées dans l'entrée. Les clauses de la forme sont faciles à inverser. Les clauses A t t e n d ( A D ) ∧ A t t e n d (A t t e n d( X) → A t t e n d( O) ∧ A t t e n d( Z) commeA t t e n d( A D ) ∧ A t t e n d( B M) → A t t e n d( D D )
sont plus difficiles à traiter.
Avec Prolog, la première approche simple consiste à éviter un renversement complet de la relation et à être plutôt orienté vers un objectif.
Supposons une commande sur la liste des invités et utilisez une règle
(Nous utilisons au lieu de A t t e n d ( X ) pour faire court)UNE( X) A t t e n d( X)
Cette règle est facile à mettre en œuvre.
Une approche plutôt naïve
Pour la lisibilité,
follows
soit la relation donnée en entrée, etbrings
son inverse.Ensuite, l'entrée est donnée par
Et
brings
peut être défini comme suit:brings/3(X,L,S)
Si nous définissons
Nous obtenons les solutions uniques suivantes:
Ce n'est pas la liste complète, car dans l'ordre alphabétique, la clause
ne fonctionne pas.
Une solution plutôt impliquée au puzzle original
Pour résoudre complètement le problème, vous devez laisser le système essayer de prouver la présence des invités ultérieurs sans introduire de boucles infinies dans l'arborescence de recherche. Il existe plusieurs façons d'atteindre cet objectif. Chacun a ses avantages et désavantages.
Une façon consiste à redéfinir
brings/2
comme suit:Le dernier argument dans
brings/4
est nécessaire pour éviter une boucle infinietry_bring
.Cela donne les réponses suivantes: Albus, Carlotta, Elfrida et Falco. Cependant, cette solution n'est pas la plus efficace car le retour en arrière est introduit là où il est parfois possible de l'éviter.
Une solution générale
Maintenant, si par exemple l'ensemble de données # 2 est donné comme
Nous obtenons la réponse L = [[ad, bm, dd, ec]]. Ce qui signifie que tous les invités sauf Carlotte et Falco doivent être invités.
Les réponses que cette solution m'a données correspondaient aux solutions données dans l'article Wicked Witch à l'exception du jeu de données # 6, où plus de solutions ont été produites. Cela semble être la bonne solution.
Enfin, je dois mentionner la bibliothèque CLP (FD) de Prolog qui est particulièrement adaptée à ce type de problèmes.
la source
Comme repéré par svick, le premier problème avec le code dans l'OP est que les noms commençant par des lettres majuscules sont des variables dans Prolog. Donc,
admit(CP) :- admit(AD)
est équivalent àattend(X) :- attend(Y)
, ce qui fait que Prolog entre immédiatement dans une boucle infinie essayant de démontrer queattend
tient pour un terme en trouvant un terme pour lequelattend
tient.Cependant, si vous vouliez que chaque ensemble d'initiales soit un terme distinct concret, vous rencontrerez toujours un débordement de pile car vous avez des cycles, par exemple
Donc, pour savoir si les
attend(cp)
suspensions, Prolog essaiera de déterminer si lesattend(ad)
suspensions, ce qu'il fera en vérifiant si lesattend(cp)
suspensions, et ainsi de suite jusqu'au débordement de la pile.Je ne crois pas que vanilla Prolog tente de déterminer s'il existe un tel cycle et d'examiner d' autres façons de faire l'un
attend(cp)
ou leattend(ad)
vrai plutôt que de rester coincé dans une boucle infinie.Il peut y avoir ou non des versions de Prolog qui prennent en charge une telle fonctionnalité. Je connais mieux Mercury et je pense que le "dépôt de modèle minimal" de Mercury est exactement ce dont vous avez besoin pour cette affaire. Je ne l'ai jamais réellement utilisé, mais d'après ce que je comprends, il permet plus ou moins à un terme qui implique lui-même d'être considéré comme vrai s'il existe un autre moyen de le prouver, ou faux sinon, sans se faire prendre dans une boucle infinie. Consultez la section pertinente de la documentation Mercury et, si vous êtes intéressé, un article décrivant la mise en œuvre.
Mercury est un langage de programmation logique de pureté forcée, avec une syntaxe similaire à Prolog mais des systèmes de type et de mode forts, et il est compilé plutôt qu'interprété.
Je viens de recréer l'introduction du document (que je n'ai pas lu depuis un certain temps), et il mentionne que le dépôt a été implémenté dans plusieurs versions de Prologs, il se peut donc que vous puissiez aller plus loin en recherchant le dépôt sur Google dans Prolog.
la source
J'ai trouvé l'article suivant sur la résolution SAT à l'aide de prolog:
Une implémentation du solveur peut être trouvée ici .
Voir cette réponse stackoverflow pour plus de détails sur le code et comment l'utiliser.
la source
Mis à part le problème des minuscules / majuscules, il y a un cycle dans les clauses:
Ainsi, lorsque vous appelez un interprète descendant, il se met en boucle. Vous aurez peut-être plus de chance avec la programmation par ensemble de réponses (ASP), qui fonctionne de bas en haut. Voici un codage via la bibliothèque ( minimal / asp ):
Voici un exemple d'exécution:
la source