web-dev-qa-db-fra.com

'si' dans le prologue?

Existe-t-il un moyen de faire un if dans un prologue, par exemple si une variable est 0, alors faire quelques actions (écrire du texte sur le terminal). Un autre n’est même pas nécessaire, mais je ne trouve aucune documentation sur if.

50
jreid9001

Un prédicat standard prolog fera cela.

   isfive(5). 

sera évalué à true si vous l'appelez avec 5 et échouera (retournera false) si vous l'exécutez avec autre chose. Pour pas égal, vous utilisez\=

isNotEqual(A,B):- A\=B.

Techniquement, cela n’unit pas, mais c’est semblable à différent.

Learn Prolog Now est un bon site pour apprendre le prologue.

Edit: Pour ajouter un autre exemple.

isEqual(A,A). 
50
stonemetal

Oui, il existe une telle construction de contrôle dans ISO Prolog, appelée ->. Vous l'utilisez comme ceci:

( condition -> then_clause ; else_clause )

Voici un exemple utilisant une chaîne de clauses else-if-:

(   X < 0 ->
    writeln('X is negative.  That's weird!  Failing now.'),
    fail
;   X =:= 0 ->
    writeln('X is zero.')
;   writeln('X is positive.')
)

Notez que si vous omettez la clause else, la condition échouant signifiera que toute l'instruction if échouera. Par conséquent, je recommande de toujours inclure la clause else (même s'il ne s'agit que de true).

85
Matthias Benkard

Les prédicats de Prolog "unifient" -

Donc, dans un langage impératif j'écrirais

function bazoo(integer foo)
{
   if(foo == 5)
       doSomething();
   else
       doSomeOtherThing();
}

En Prolog j'écrirais

bazoo(5) :-  doSomething.
bazoo(Foo) :- Foo =/= 5, doSomeOtherThing.

ce qui, lorsque vous comprenez les deux styles, est en réalité beaucoup plus clair.
"Je suis bazoo pour le cas particulier où foo a 5 ans"
"Je suis bazoo pour le cas normal où foo n'a pas 5 ans"

25
Anniepoo

J'ai trouvé cela utile pour utiliser une instruction if dans une règle.

max(X,Y,Z) :-
    (  X =< Y
    -> Z = Y
    ;  Z = X
    ).

Merci à http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html

12
Tom Howard

Tout d’abord, rappelons une logique classique du premier ordre:

" Si P alors Q sinon R" est équivalent à "(P et = Q) ou (non_P et R) ".


Comment pouvons-nous exprimer "if-then-else" comme ça dans Prolog?

Prenons l'exemple concret suivant:

SiX est membre de la liste [1,2] alorsX est égal à 2 sinonX est égal à 4.

Nous pouvons faire correspondre le modèle ci-dessus (" Si P alors Q sinon R") si ...

  • la condition P est list_member([1,2],X),
  • condition annulée non_P est non_member([1,2],X),
  • conséquence Q est X=2, et
  • la variante R est X=4.

Pour exprimer des (non) membres de liste de manière pure, nous définissons:

 list_memberd ([E | Es], X): - 
 (E = X 
; dif (E, X), 
 list_memberd (Es, X) 
). 
 
 non-membre (Es, X): - 
 liste (dif (X), Es). 

Voyons maintenant différentes façons d’exprimer "if-then-else" dans Prolog!

  1. (P,Q ; non_P,R)

    ?  liste_memberd ([1,2], X), X = 2; non membre ([1,2], X), X = 4). [.____] X = 2; X = 4. 
    ? - X = 2, (list_memberd ([1,2], X), X = 2; non membre ([1,2], X), X = 4), X = 2 . 
     X = 2 ; faux. 
    ? - (list_memberd ([1,2], X), X = 2; non membre ([1,2], X), X = 4), X = 2. 
     X = 2 ; faux. 
    ? - X = 4, (list_memberd ([1,2], X), X = 2; non membre ([1,2], X), X = 4), X = 4. ____.] X = 4. 
    ? - (list_memberd ([1,2], X), X = 2; non membre ([1,2], X), X = 4), X = 4. 
     X = 4. 
    

    Score de correction 5/5. Score d'efficacité 3/5.

  2. (P -> Q ; R)

    ? - (list_memberd ([1,2], X) -> X = 2; X = 4). 
    false. % FAUX 
    ? - X = 2, (list_memberd ([1,2], X) -> X = 2; X = 4), X = 2. 
     X = 2. 
    ? - (list_memberd ([1,2], X) -> X = 2; X = 4), X = 2. 
    false. % FAUX 
    ? - X = 4, (list_memberd ([1,2], X) -> X = 2; X = 4), X = 4. 
     X = 4. 
    ? - (list_memberd ([1,2], X) -> X = 2; X = 4), X = 4. 
    false. % FAUX
    

    Score de correction 2/5. Score d'efficacité 2/5.

  3. (P *-> Q ; R)

    ? - (list_memberd ([1,2], X) * -> X = 2; X = 4). 
     X = 2 ; faux. % FAUX 
    ? - X = 2, (list_memberd ([1,2], X) * -> X = 2; X = 4), X = 2. 
     X = 2 ; faux. 
    ? - (list_memberd ([1,2], X) * -> X = 2; X = 4), X = 2. 
     X = 2 ; faux. 
    ? - X = 4, (list_memberd ([1,2], X) * -> X = 2; X = 4), X = 4. 
     X = 4. 
    ? - (list_memberd ([1,2], X) * -> X = 2; X = 4), X = 4. 
    false. % FAUX
    

    Score de correction 3/5. Score d'efficacité 1/5.


Résumé (préliminaire):

  1. (P,Q ; non_P,R) Est correct, mais nécessite une implémentation discrète de non_P.

  2. (P -> Q ; R) Perd la sémantique déclarative lorsque l'instanciation est insuffisante.

  3. (P *-> Q ; R) Est "moins" incomplet que (P -> Q ; R), Mais présente toujours des problèmes similaires.


Heureusement pour nous, il y a sont alternatives: Entrez la structure de commande monotone et logique if_/3!

Nous pouvons utiliser --- (if_/3 avec le prédicat d'adhésion à la liste réifié memberd_t/3 comme suit:

? - if_ (memberd_t (X, [1,2]), X = 2, X = 4). 
 X = 2; X = 4. 
? - X = 2, si_ (membred_t (X, [1,2]), X = 2, X = 4), X = 2. 
 X = 2. 
? - if_ (memberd_t (X, [1,2]), X = 2, X = 4), X = 2. 
 X = 2 ; faux. 
? - X = 4, si_ (membred_t (X, [1,2]), X = 2, X = 4), X = 4. 
 X = 4. 
? - if_ (membred_t (X, [1,2]), X = 2, X = 4), X = 4. 
 X = 4. 

Score de correction 5/5. Score d'efficacité 4/5.

9
repeat

La meilleure chose à faire est d'utiliser le soi-disant cuts, qui porte le symbole !.

if_then_else(Condition, Action1, Action2) :- Condition, !, Action1.  
if_then_else(Condition, Action1, Action2) :- Action2.

Ce qui précède est la structure de base d'une fonction de condition.

Pour illustrer cela, voici la fonction max:

max(X,Y,X):-X>Y,!.  
max(X,Y,Y):-Y=<X.

Je suggère de lire plus de documentation sur les coupes, mais en général elles ressemblent à des points d'arrêt. Ex .: Si la première fonction max renvoie une valeur vraie, la deuxième fonction n'est pas vérifiée.

PS: Je suis assez nouveau sur Prolog, mais c'est ce que j'ai découvert.

5
skipper

Il existe essentiellement trois façons différentes d'exprimer quelque chose comme si-alors-sinon dans Prolog. Pour les comparer, considérons char_class/2. Pour a et b, la classe doit être ab et other pour tous les autres termes. On pourrait écrire ceci maladroitement ainsi:

char_class(a, ab).
char_class(b, ab).
char_class(X, other) :-
   dif(X, a),
   dif(X, b).

?- char_class(Ch, Class).
   Ch = a, Class = ab
;  Ch = b, Class = ab
;  Class = other,
   dif(Ch, a), dif(Ch, b).

Pour écrire les choses de manière plus compacte, une construction if-then-else est nécessaire. Prolog a un intégré:

?- ( ( Ch = a ; Ch = b ) -> Class = ab ; Class = other ).
   Ch = a, Class = ab.

Bien que cette réponse soit valable, elle est incomplète. Seule la première réponse de ( Ch = a ; Ch = b ) Est donnée. Les autres réponses sont coupées. Pas très relationnel, en effet.

Une meilleure construction, souvent appelée "coupe douce" (ne croyez pas le nom, une coupe est une coupe est une coupe), donne des résultats légèrement meilleurs (c'est dans YAP):

?- ( ( Ch = a ; Ch = b ) *-> Class = ab ; Class = other ).
   Ch = a, Class = ab
;  Ch = b, Class = ab.

Sinon, SICStus a if/3 Avec une sémantique très similaire:

?- if( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
   Ch = a, Class = ab
;  Ch = b, Class = ab.

Donc, la dernière réponse est toujours supprimée. Maintenant, entrez library(reif) pour SICStus , YAP , et SWI . Installez-le et dites:

?- use_module(library(reif)).

?- if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
   Ch = a, Class = ab
;  Ch = b, Class = ab
;  Class = other,
   dif(Ch, a), dif(Ch, b).

Notez que tout le if_/3 Est compilé dans un if imbriqué si-alors-sinon pour

char_class(Ch, Class) :-
   if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).

qui s'étend dans YAP 6.3.4 à:

char_class(A,B) :-
   ( A\=a
   ->
     ( A\=b
     ->
       B=other
     ;
       ( A==b
       ->
         B=ab
       )
     ;
       A=b,
       B=ab
     ;
       dif(A,b),
       B=other
     )
   ;
     ( A==a
     ->
       B=ab
     )
   ;
     A=a,
     B=ab
   ;
     dif(A,a),
     ( A\=b
     ->
       B=other
     ;
       ( A==b
       ->
         B=ab
       )
     ;
       A=b,
       B=ab
     ;
       dif(A,b),
       B=other
     )
   ).
5
false

Le programme Prolog est en fait une condition importante pour "si" avec "alors" qui imprime "L'objectif est atteint" et "sinon" qui affiche "Aucune définition n'a été trouvée". A, B Signifie "A est vrai et B est vrai", la plupart des systèmes de prologue n'essaieront pas de satisfaire "B" si "A" n'est pas accessible (c'est-à-dire que X=3, write('X is 3'),nl imprimera 'X est 3 'quand X = 3, et ne fera rien si X = 2).

4
ony
(  A == B ->
     writeln("ok")
;
     writeln("nok")
),

La partie else est requise

2
Dieter

Vous devriez lire apprendrez maintenant Prolog! Chapitre 10.2 Utiliser Cut . Ceci fournit un exemple:

max(X,Y,Z) :- X =< Y,!, Y = Z.

être dit,

Z est égal à Y [~ # ~] si [~ # ~] ! est vrai (ce qui est toujours le cas) [~ # ~] et [~ # ~] X est <= Y.

1
mdo123