web-dev-qa-db-fra.com

Savoir quand utiliser couper en prologue

J'ai suivi un cours dans lequel j'ai appris le prologue. Je ne pouvais pas comprendre quand et comment utiliser les coupes. Bien que j'aie une idée générale des coupures, je n'arrive pas à les utiliser correctement. Quelqu'un peut-il l'expliquer brièvement ou donner un bon tutoriel (ce n'est pas learnprolognow.org) sur les "coupes" qu'il peut recommander ?

38
Shookie

TL; DR: Non.

O corte poda à l'aventure de bus do Prolog. Cliquez sur le programme que vous avez programmé pour commencer et sur le programme qui vous convient le mieux et qui est différent du programme que vous programmez. pode ter menos respostas; também pode terminar enquanto o programa original no.

Soa muito inofensivo ... ou à partir de maintenant, n'est-ce pas? Bem, na maioria das vezes as coisas são plus complexas.

Cortes Vermelhos

De plus, il est fréquent que nous utilisions des informations supplémentaires sur le programme, mais il n’existe pas de sens. Tais cortes sao chamados cortes vermelhos. Nos concerts, qui sont mis en œuvre sous la forme d'une résolution brutale de négociations monétaires. E alguns sur les cas, la résolution, les processus significatifs et les processus qui en découlent. Aucun commentaire sur le programme, le contenu de votre auteur. De plus, rien ne vaut ce que nous avons acheté firme . Dans le cas contraire: esses cortes ne sont pas colocados dans le programme existant. Eles estão destinados a est nesse programa dede in incio.

Si vous utilisez ce matériel, utilisez melhor once/1, (\+)/1 ou (;)/2 - si-alors-sinon, sinon _( If -> Then ; Else ). Melhor ainda, tente protégé a construit des contraventions contre toutes les tentatives d'émettre des instantiation_errors. Vous pouvez utiliser iwhen/2 que des erreurs d’instanciação ou when/2 (oferecido no SWI, YAP, SICStus) soient ajoutées à l’objet.

Cortes Verdes

Cortes que removemos pontos de escolha inúteis (et autres réponses redondantes) à partir de maintenant. Masquer la liste des mots simples à lire comme programme!e alguns #00ff00. Cliquez ici pour afficher la liste des personnes protégées, cliquez ici pour en savoir plus sur ce que vous devez savoir sur le comportement de chacun #ff0000. Vous êtes ici pour utiliser les outils de nettoyage simples à utiliser pour résoudre le problème: call_semidet/1 . Cliquez ici pour afficher les informations détaillées:

Cortar n'est pas confirmé

Finalmente, deixe-me salientar that or corte não is um operador de commit. À partir de maintenant, il était encore moins cher, mais il était préférable de choisir. Um commit-operator não pode ser (ab) avec les implémentations (\+)/1. Um commit requer que nous soyons soumis à un test indépendant des règles de la vie. Cada cláusula precisa, portant, de sécurité totale; Vous ne pouvez pas vous tromper si vous voulez que votre argent soit épuisé par le monde. En outre, vous commettez un acte d'accomplissement dans les conditions qui précèdent. O corte pode ocorrer em qualquer lugar.

23
false

Une coupure commet l'objectif Prolog étant prouvé aux choix effectués.

Il doit être utilisé ensuite lorsque le programmeur sait que toute alternative disponible doit ne doit pas être essayée.

L'utilisation la plus importante est l'implémentation de négation par échec.

fact(a).
fact(b).

/* 1 */ neg(X) :- call(X), !, fail.
/* 2 */ neg(_).

Ici, j’ai (re) défini l’opérateur de négation standard, normalement c’est ( \+ )/1

?- neg(fact(c)).
true.

call(fact(c)) de la règle 1 ne peut pas être prouvé et la règle alternative 2 réussit.

?- neg(fact(a)).
false.

parce que fact(a)peut être prouvé, la coupe ignore l’alternative avant d’échouer.

?- neg(fact(X)).
false.

il existe au moins un X inconnu tel que le fait (X) réussisse.

?- neg(neg(fact(X))).
true.

la double négation a pour effet que les variables non sont liées. Cela peut être utile lors de la méta-programmation, pour extraire des clauses sans modifier leur "structure". Du point de vue opérationnel, ce qui se passe est clair (?), Mais le programme perd sa propriété déclarative.

Une autre utilisation, utile uniquement dans les interpréteurs rudimentaires, consistait à demander au système d'effectuer optimisation du dernier appel, en préfixant un appel récursif. Ensuite, le système peut éviter d’allouer l’espace de pile normalement requis pour garder trace du point de remplacement. Un exemple factice:

print_list([E|Es]) :- print_element(E), !, print_list(Es).
print_list([]).

edit à propos d'un tutoriel: j'ai trouvé que «Clause and Effect» de William Clocksin contient une enquête détaillée sur la coupe: le chapitre 4 «Choix et engagement» est entièrement consacré à la réduction des avantages et des inconvénients. En bout de ligne, principalement contre ...

14
CapelliC

Avant d’utiliser une coupe, j’ai besoin que mes prédicats répondent à ces deux critères:

  • il donne des réponses correctes sans coupure
  • il donne des réponses correctes si les clauses sont réorganisées

Une fois que mon prédicat se comporte de cette manière, j’ajoute parfois une coupure pour éliminer le non-déterminisme indésirable.

Par exemple, un prédicat pour tester si un nombre est positif, négatif ou nul.

sign(N, positive) :-
    N > 0.
sign(N, negative) :-
    N < 0.
sign(N, zero) :-
    N =:= 0.

Chaque clause est totalement indépendante des autres. Je peux réorganiser ces clauses ou supprimer une clause et les clauses restantes donnent toujours la réponse attendue. Dans ce cas, je pourrais mettre un terme à la fin des clauses positive et negative simplement pour dire au système Prolog qu'il ne trouvera plus de solutions en examinant les autres clauses.

On pourrait écrire un prédicat similaire sans couper en utilisant -> ;, mais certains n'aiment pas son apparence:

sign(N, Sign) :-
    (   N > 0 -> Sign=positive
    ;   N < 0 -> Sign=negative
    ;            Sign=zero
    ).
11
mndrix

Le prédicat Cut empêche le retour en arrière. Le prédicat Cut est spécifié en tant que point d'exclamation (!). Cut élague l’arbre de recherche et raccourcit la trace du chemin par l’interprète de prologue.

read(a).
read(b).
color(p, red) :- red(p).
color(p,black) :- black(p),!.
color(p,unknown).

?-color(X,Y).
  X = a,
  Y = red;
  X = b,
  Y = black;

Sans coupure, les buts montrent Y = inconnu après Y = noir.

Il existe deux types de prédicats de coupe:

Coupe verte: La coupe verte est un type de coupe qui n’a pas d’effet sur le sens déclaratif. Il ne sert qu'à améliorer l'efficacité et à éviter les calculs inutiles. La suppression de la coupe verte du programme ne change pas la signification du programme.

Red Cut: Red Cut est celui qui a eu un effet sur le sens déclaratif. La suppression du rouge coupé du programme change la signification du programme.

1
rashedcs

Les coupes ont quasiment disparu de mon code une fois que j'ai trouvé le prédicat once. En interne, il agit comme

once(X) :- X, !.

et j’ai trouvé cela très utile pour prendre une décision ferme sur la manière de faire quelque chose avant de le faire.

Par exemple, voici mon méta-interprète standard. La clause maybe1/1 a des foncteurs uniques dans ses arguments, donc une fois qu'ils sont connus, le droit maybe1/1 peut être sélectionné parfaitement. 

Le travail de recherche de cette fonction unique est confié au préprocesseur maybe0/2 qui définit Y comme une "instruction à faire" sur X

Sans once, des coupures seraient nécessaires. Par exemple. Dans maybe1, il existe trois/deux interprétations différentes de X/Y et or que nous devons vérifier de manière descendante. Mais vérifiez-le sans coupures.

maybe(X) :- 
    once(maybe0(X,Y)), maybe1(Y).

maybe0(true,       true).
maybe0((X,Y),      (X,Y)).
maybe0((X;Y),      or(L))          :- o2l((X;Y),L).
maybe0(X,          calls(X))       :- calls(X).
maybe0(X/Y,        fact(X/Y))      :- clause(X/_, true).
maybe0(X/Y,        rule(X/Y))      :- clause(X/_,_).
maybe0(X/Y,        abducible(X/Y)).
maybe0(or([H|T]),  or([H|T])).
maybe0(or([]),     true).

maybe1(true).
maybe1((X,Y))        :- maybe(X),maybe(Y).
maybe1((X;Y))        :- maybe(X);maybe(Y).
maybe1(abducible(X)) :- assume(X,0).
maybe1(fact(X))      :- assume(X,1), one(X).
maybe1(rule(X))      :- assume(X,2), one(clause(X,Y)), maybe(Y).
maybe1(calls(X))     :- one(clause(X,Y)), maybe(Y).
maybe1(or([H|T]))    :- any(One,Rest,[H|T]), ignore(maybe(One)), maybe(or(Rest)).
0
Tim Menzies