Pergunta

Existe uma maneira de fazer um IF no Prolog, por exemplo, se uma variável for 0, então fazer algumas ações (escreva texto no terminal). Um mais nem sequer é necessário, mas não consigo encontrar nenhuma documentação do IF.

Foi útil?

Solução

Um predicado padrão do Prolog fará isso.

   isfive(5). 

Avaliará como verdadeiro se você ligar com 5 e falhar (retornar false) se você executá -lo com qualquer outra coisa. Para não igual, você usa =

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

Tecnicamente, não é unificado, mas é semelhante a não ser igual.

Learn Prolog Now é um bom site para aprender o Prolog.

EDIT: Para adicionar outro exemplo.

isEqual(A,A). 

Outras dicas

Sim, existe tal construção de controle no ISO Prolog, chamado ->. Você usa assim:

( condition -> then_clause ; else_clause )

Aqui está um exemplo que usa uma cadeia de mais-cláusulas:

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

Observe que, se você omitir a cláusula de outra pessoa, a falha na condição significará que toda a estatura se falhará. Portanto, eu recomendo sempre incluir a cláusula de outra pessoa (mesmo que seja apenas true).

Prolog prediz 'unificar' -

Então, em um Langauge imperativo, eu escrevia

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

Em Prolog, eu escrevia

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

O que, quando você entende os dois estilos, é realmente muito mais claro.
"Eu sou Bazoo para o caso especial quando Foo tem 5"
"Eu sou Bazoo para o caso normal quando Foo não é 5"

Eu achei isso útil para usar um E se declaração em uma regra.

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

Graças a http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html

Primeiro, lembre -se de uma lógica clássica de primeira ordem:

"Se P então Q senão R "é equivalente a" (p e Q) ou (non_p e R) ".


Como podemos expressar "se-then-else" como este em Prolog?

Vamos dar o seguinte exemplo concreto:

Se X é um membro da lista [1,2] então X é igual a 2 senão X é igual a 4.

Podemos corresponder ao padrão acima ("Se P então Q senão R ") se ...

  • doença P é list_member([1,2],X),
  • condição negada non_P é non_member([1,2],X),
  • consequência Q é X=2, e
  • alternativo R é X=4.

Para expressar a lista (não) de uma maneira pura, definimos:

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

non_member(Es,X) :-
   maplist(dif(X),Es).

Vamos verificar diferentes maneiras de expressar "se-then-else" no Prolog!

  1. (P,Q ; non_P,R)

    ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4).
    X = 2 ; X = 4.
    ?- X=2, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2.
    X = 2 ; falso.
    ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2.
    X = 2 ; falso.
    ?- X=4, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4.
    X = 4.
    ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4.
    X = 4.
    

    Pontuação de correção 5/5. Pontuação de eficiência 3/5.

  2. (P -> Q ; R)

    ?-      (list_memberd([1,2],X) -> X=2 ; X=4).
    falso.                                                % WRONG
    ?- 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.
    falso.                                                % WRONG
    ?- 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.
    falso.                                                % WRONG
    

    Pontuação de correção 2/5. Pontuação de eficiência 2/5.

  3. (P *-> Q ; R)

    ?-      (list_memberd([1,2],X) *-> X=2 ; X=4).
    X = 2 ; falso.                                        % WRONG
    ?- X=2, (list_memberd([1,2],X) *-> X=2 ; X=4), X=2.
    X = 2 ; falso.
    ?-      (list_memberd([1,2],X) *-> X=2 ; X=4), X=2.
    X = 2 ; falso.
    ?- 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.
    falso.                                                % WRONG
    

    Pontuação de correção 3/5. Pontuação de eficiência 1/5.


(Preliminar) Resumo:

  1. (P,Q ; non_P,R) está correto, mas precisa de uma implementação discreta de non_P.

  2. (P -> Q ; R) Perde a semântica declarativa quando a instanciação é insuficiente.

  3. (P *-> Q ; R) é "menos" incompleto do que (P -> Q ; R), mas ainda tem problemas semelhantes.


Felizmente para nós, aí são alternativas:Digite a construção de controle logicamente monótono if_/3!

Podemos usar if_/3 juntamente com o predicado de memória de lista reificada memberd_t/3 igual a:

?-      if_(memberd_t(X,[1,2]), X=2, X=4).
X = 2 ; X = 4.
?- X=2, if_(memberd_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 ; falso.
?- X=4, if_(memberd_t(X,[1,2]), X=2, X=4), X=4.
X = 4.
?-      if_(memberd_t(X,[1,2]), X=2, X=4), X=4.
X = 4.

Pontuação de correção 5/5. Pontuação de eficiência 4/5.

A melhor coisa a fazer é usar o chamado cuts, que tem o símbolo !.

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

O acima é a estrutura básica de uma função de condição.

Para exemplificar, aqui está o max função:

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

Sugiro ler mais documentação sobre cortes, mas em geral eles são como pontos de interrupção. Ex.: Caso o primeiro max A função retorna um valor verdadeiro, a segunda função não é verificada.

PS: Sou bastante novo no Prolog, mas foi isso que descobri.

Existem essencialmente três maneiras diferentes de como expressar algo como If-Then-Else em Prolog. Para compará -los, considere char_class/2. Por a e b A classe deve ser ab e other Para todos os outros termos. Alguém poderia escrever isso desajeitadamente assim:

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

Para escrever as coisas com mais compactação, é necessária uma construção if-then-else. Prolog tem um embutido:

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

Embora essa resposta seja sólida, é incompleta. Apenas a primeira resposta de ( Ch = a ; Ch = b ) é dada. As outras respostas são cortadas. Não é muito relacional, de fato.

Uma construção melhor, geralmente chamada de "corte suave" (não acredite no nome, um corte é um corte é um corte), fornece resultados um pouco melhores (isso está no YAP):

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

Alternativamente, Sicstus tem if/3 com semântica muito semelhante:

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

Portanto, a última resposta ainda é suprimida. Agora digite library(reif) por Sicstus, Yap, e Swi. Instale -o e diga:

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

Observe que todo o if_/3 é compilado para um if-then-else aninhado para

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

que se expande no YAP 6.3.4 para:

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

O programa Prolog na verdade é uma grande condição para "se" com "então", que imprime ", a meta é alcançada" e "else", que imprime ", não foi encontrada sloutions". A, Bsignifica que "A é verdadeiro e B é verdadeiro", a maioria dos sistemas Prolog não tentará satisfazer "B" se "A" não for alcançado (ou seja, X=3, write('X is 3'),nl Imprimir 'x é 3' quando x = 3 e não fará nada se x = 2).

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

A parte else é necessária

Você deve ler Aprenda Prolog agora! Capítulo 10.2 Usando Cut. Isso fornece um exemplo:

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

a ser dito,

Z é igual a Y E SE ! é verdadeiro (o que sempre é) E X é <= Y.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top