web-dev-qa-db-ja.com

プロローグの「if」?

プロローグでifを実行する方法はありますか?変数が0の場合、何らかのアクションを実行します(端末にテキストを書き込みます)。 elseは必要ありませんが、ifのドキュメントは見つかりません。

50
jreid9001

標準のプロローグ述語がこれを行います。

   isfive(5). 

5で呼び出すとtrueに評価され、それ以外で実行すると失敗します(falseを返します)。等しくない場合は、\ =を使用します

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

技術的には統一されていませんが、等しくないことに似ています。

Learn Prolog Nowは、プロローグを学習するのに適したWebサイトです。

編集:別の例を追加します。

isEqual(A,A). 
50
stonemetal

はい、ISO Prologには->と呼ばれる制御構造があります。次のように使用します。

( condition -> then_clause ; else_clause )

Else-if-clausesのチェーンを使用する例を次に示します。

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

Else-clauseを省略すると、条件が失敗すると、if文全体が失敗することになります。したがって、else-clauseを常に含めることをお勧めします(たとえtrueであっても)。

85

プロローグ述語 'unify'-

だから、命令的な言語で私は書きます

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

プロローグに書きます

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

両方のスタイルを理解すると、実際にははるかに明確になります。
"fooが5である特別な場合のバズーです"
"fooが5でない通常の場合はバズーです"

25
Anniepoo

これは、ルールでifステートメントを使用するのに役立ちます。

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

http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html に感謝

12
Tom Howard

最初に、古典的な一次論理を思い出してみましょう。

IfPthenQelseR」は「(P andQ)or(non_PandR)」。


Prologでthatのような「if-then-else」をどのように表現できますか?

次の具体例を見てみましょう。

IfXはリスト[1,2]のメンバーであるthenX2に等しいelseX4と等しい。

上記のパターンに一致させることができます( "IfPthenQelseR" )if ...

  • 条件Plist_member([1,2],X)であり、
  • 否定条件non_Pnon_member([1,2],X)です、
  • 結果QX=2であり、
  • 代替のRX=4です。

リスト(非)メンバーシップを純粋な方法で表現するには、以下を定義します。

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

Prologで「if-then-else」を表現するさまざまな方法を見てみましょう。

  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 ;偽。
    ?-(list_memberd([1,2]、X)、X = 2; non_member([1,2]、X)、X = 4)、X = 2。
     X = 2 ;偽。
    ?-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。 % 違う
    

    正しさスコア2/5。効率スコア2/5。

  3. (P *-> Q ; R)

    ?-(list_memberd([1,2]、X)*-> X = 2; X = 4)。
     X = 2 ;偽。 %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。
     X = 2 ;偽。
    ?-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。 % 違う
    

    正しさスコア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 を、具体化されたリストメンバーシップ述語 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 ;偽。
?-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。

9
repeat

最善の方法は、!というシンボルを持つ、いわゆる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関数が真の値を返す場合、2番目の関数は検証されません。

PS:私はPrologにかなり慣れていないが、これは私が見つけたものだ。

5
skipper

Prologでif-then-elseのようなものを表現するには、基本的に3つの異なる方法があります。それらを比較するには、char_class/2を検討してください。 aおよびbの場合、他のすべての用語では、クラスはabおよびotherでなければなりません。これを次のように不器用に書くことができます:

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.

したがって、最後の答えはまだ抑制されています。次に、 SICStus[〜#〜] yap [〜#〜] 、および library(reif)と入力します[〜#〜] 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
     )
   ).
5
false

プロローグプログラムは、実際には「if」と「then」、「ゴールに到達しました」、「else」と「No sloutions was found」を出力するための大きな条件です。 _A, B_ means「Aが真でBが真」。プロローグシステムのほとんどは、「A」に到達できない場合(「X=3, write('X is 3'),nl」は「Xは3」を出力します) X = 3の場合、X = 2の場合は何もしません。

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

Elseの部分は必須です

2
Dieter

Prolog Nowを学びましょう!第10.2カットの使用 をお読みください。これは例を提供します:

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

言われるように、

ZYと等しい[〜#〜] if [〜#〜]!が真(常に)[〜#〜] and [〜#〜]X<= Y

1
mdo123