"если" в прологе?

вероятно, глупый вопрос,но я не могу найти никакой документации для него. Есть ли способ сделать if в prolog, например, если переменная равна 0, то выполнить некоторые действия (написать текст в терминал). Другое даже не нужно, но я не могу найти никакой реализации if.

10 ответов


стандартный предикат prolog сделает это.

   isfive(5). 

будет оценивать true, если вы вызываете его с помощью 5 и fail (return false), если вы запустите его с чем-либо еще. Для не равных вы используете \=

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

технически это не объединяет,но это похоже на не равно.

Learn Prolog Now-хороший сайт для изучения пролога.

изменить: Чтобы добавить еще один пример.

isEqual(A,A). 

да, в ISO Prolog есть такая управляющая конструкция, называемая ->. Вы используете его так:

( condition -> then_clause ; else_clause )

вот пример, который использует цепочку предложений else-if:

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

обратите внимание, что если вы опустите предложение else, условие failing будет означать, что весь оператор if потерпит неудачу. Поэтому я рекомендую всегда включать предложение else (даже если это просто true).


предикаты пролога 'unify' -

Итак, в императивном langauge я бы написал

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

в прологе я бы написал

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

что, когда вы понимаете, оба стиля, на самом деле намного яснее.
"Я базу для особого случая, когда фу 5"
"Я базу для нормального случая, когда фу не 5"


Я нашел это полезным для использования если оператор в правиле.

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

спасибо http://cs.union.edu / ~striegnk/learn-prolog-now/html/node89.html


лучше всего использовать так называемый cuts, который имеет символ !.

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

вышеуказанное основная структура функции условия.

чтобы проиллюстрировать, вот max функция:

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

Я предлагаю прочитать больше документации по сокращениям, но в целом они похожи на точки останова. Бывший.: В случае первой max функция возвращает значение true, вторая функция не проверено.

PS: Я довольно новичок в Prolog, но это то, что я узнал.


во-первых, давайте вспомним классическую логику первого порядка:

"если P затем Q другое R " эквивалентно "(P и Q)или (non_P и R)".


как мы можем выразить "если-то-иначе" как это в прологе?

рассмотрим следующий конкретный пример:

если X является членом затем X равна 2 другое X равна 4.

мы можем соответствовать над картиной ("если P затем Q другое R") если ...

  • условие P is list_member([1,2],X),
  • отрицается условие non_P is non_member([1,2],X),
  • следствие Q is X=2 и
  • альтернатива R is X=4.

чтобы выразить список (не-)членство в чистом виде, мы определяем:

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

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

давайте проверим различные способы выражения "если-то-иначе" в прологе!

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

    оценка правильности 5/5. Оценка эффективности 3/5.

  2. (P -> Q ; R)

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

    оценка правильности 2/5. Оценка эффективности 2/5.

  3. (P *-> Q ; R)

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

    оценка правильности 3/5. Оценка эффективности 1/5.


(предварительный) резюме:

  1. (P,Q ; non_P,R) правильная, но нуждается в дискретной реализации non_P.

  2. (P -> Q ; R) теряет декларативную семантику при недостаточном создании экземпляра.

  3. (P *-> Q ; R) "меньше", чем неполные (P -> Q ; R), но все еще имеет подобные проблемы.


к счастью для нас, есть are альтернативы: введите логически монотонную конструкцию управления if_/3!

можно использовать if_/3 вместе с предикатом reified list-membership memberd_t/3 вот так:

?-      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 ; false.
?- 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.

оценка правильности 5/5. Оценка эффективности 4/5.


есть по существу три разных способа выразить что-то вроде if-then-else в прологе. Чтобы сравнить их рассмотрим char_class/2. Для a и b класса необходимо ab и other для всех остальных условия. Можно было бы написать это так неуклюже:--17-->

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

чтобы писать вещи более компактно, нужна конструкция if-then-else. Prolog имеет встроенный:

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

хотя этот ответ звучит, он неполон. Только первый ответ от ( Ch = a ; Ch = b ) дается. Остальные ответы отрезаны. В самом деле, не очень близкие отношения.

лучшая конструкция, часто называемая "мягким вырезом" (не верьте названию, разрез-это разрез-это разрез), дает немного лучшие результаты (это в YAP):

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

альтернативно, SICStus имеет if/3 С очень похожей семантики:

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

таким образом, последний ответ все еще подавлен. Теперь введите library(reif) на SICStus, YAP, и SWI. Установите его и скажите:

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

обратите внимание, что все if_/3 компилируется в дико вложенный if-then-else для

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

который расширяется в 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
     )
   ).

программа Prolog на самом деле является большим условием для "Если" с "ТО", который печатает "цель достигнута" и "еще", который печатает "не было найдено sloutions". A, Bозначает "a истинно и B истинно", большинство систем пролога не будут пытаться удовлетворить" B", если" A " недоступно (т. е. X=3, write('X is 3'),nl будет печатать "X равно 3", Когда X=3, и ничего не будет делать, если X=2).


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

требуется другая часть


следует читать Узнайте Пролог Сейчас! Глава 10.2 Использование Cut. Это дает пример:

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

сказано,

Z равна Y если ! истинно (что всегда так)и X is <= Y.