'if' in prolog?

前端 未结 10 1487
小鲜肉
小鲜肉 2020-12-03 02:12

Is there a way to do an if in prolog, e.g. if a variable is 0, then to do some actions (write text to the terminal). An else isn\'t even needed, but I can\'t find any docume

10条回答
  •  情歌与酒
    2020-12-03 02:55

    First, let's recall some classical first order logic:

    "If P then Q else R" is equivalent to "(P and Q) or (non_P and R)".


    How can we express "if-then-else" like that in Prolog?

    Let's take the following concrete example:

    If X is a member of list [1,2] then X equals 2 else X equals 4.

    We can match above pattern ("If P then Q else R") if ...

    • condition P is list_member([1,2],X),
    • negated condition non_P is non_member([1,2],X),
    • consequence Q is X=2, and
    • alternative R is X=4.

    To express list (non-)membership in a pure way, we define:

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

    Let's check out different ways of expressing "if-then-else" in 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 ; 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.
      

      Correctness score 5/5. Efficiency score 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
      

      Correctness score 2/5. Efficiency score 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
      

      Correctness score 3/5. Efficiency score 1/5.


    (Preliminary) summary:

    1. (P,Q ; non_P,R) is correct, but needs a discrete implementation of non_P.

    2. (P -> Q ; R) loses declarative semantics when instantiation is insufficient.

    3. (P *-> Q ; R) is "less" incomplete than (P -> Q ; R), but still has similar woes.


    Luckily for us, there are alternatives: Enter the logically monotone control construct if_/3!

    We can use if_/3 together with the reified list-membership predicate memberd_t/3 like so:

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

    Correctness score 5/5. Efficiency score 4/5.

提交回复
热议问题