0

C#で書かれた学生プログラムを理解できるプロローグコードを書いてみました。今、私は学生のプログラムの「if」ステートメントを認識する過程で立ち往生しています。例: 以下は、学生に期待するコードです。

int d = int.Parse(Console.ReadLine());  // value d is inputted by user
int s = 0;

if (d>0)
    s = 2;
else if (d==0)
    s = 1;
else
    s = 0;

この予想されるコードの目標を次のように定義しました。

goal:- 
   hasVarName(Vid_s, s),
   hasVarName(Vid_d, d),
   hasVarValue(Vid_d, Vd),
   ((not(gt(Vd,0)); hasVarValue(Vid_s, 2)),           %eq: [Vd>0] -> [val_s = 2]
   ((gt(Vd,0); not(eq(Vd,0)); hasVarValue(Vid_s, 1)), %eq: [~(Vd>0)^(Vd=0)] -> [val_s = 1]
   ((gt(Vd,0); eq(Vd,0); hasVarValue(Vid_s, 0).       %eq: [~(Vd>0)^~(Vd=0)] -> [val_s = 0]

問題は、上記の学生コードをプロローグの事実とルールでどのように表現して、可能な条件に対して目標が満たされているかを確認する方法です。

学生コードの最初の部分を次のようなファクトになるように変更しようとしましたが、prolog で学生の 'if' ステートメントをファクト/ルールとして表現する方法がよくわかりません (おそらく、prolog に変更しないでください)。 「もし」ですよね?)

hasVarName(varID_d, d)
hasVarValue(varID_d, val_d)   %it is unknown, so I represent it as symbol 'val_d'

hasVarName(varID_s, s)
hasVarValue(varID_s, 0)

もう 1 つは、私の目標では、演算子よりも大きいプロローグを使用できないと思うような比較があるgt(Vd,0)場合、Vd の値が実際にはユーザーによって入力された特定の値ではなく、シンボリック値として表されます (この場合は : )。Vd> 0Vd @> 0val_d

注:上記の目標を使用して、学生コードを次のコードに変更すると、定義された目標が満たされると思います。

int d = int.Parse(Console.ReadLine());  // value d is inputted by user
int s = 0;

if (d>0)
    s = 2;
else if (d==0)
    s = 1;

また

int d = int.Parse(Console.ReadLine());  // value d is inputted by user
int s = 10;           // any random initialization

if (d>0)
{
    int x = 2;       // unnecessary step, but still Ok.
    s = x;
}
else if (d==0)
    s = 1;
else
    s = 0;

しかし、繰り返しになりますが、目標を達成するために、このコードをプロローグでアクション/ルール/ファクトとしてどのように表現できるかについて、ヘルプ/アイデアが必要です。

どんな助けでも本当に感謝しています。

どうもありがとう

4

2 に答える 2

0

通常、言語の実装には抽象構文ツリーが必要です。そこでは、表現できる構造を実装するセマンティック アクションを指定すると便利です。

構文ツリーを構築するフェーズをスキップしているようで、(手動で?) プログラムの中間レベルを表しています。

if(Condition, Then, Else)このような中レベルの表現に固執する場合は、各 var が構文ツリーである場合のように、再帰的な用語 (実質的には抽象ツリー) を使用できます。

それ以外の場合、より実用的な表現 (通常は命令型言語に適用される) では、基本ブロック (ジャンプのない命令シーケンス) の概念を使用してから、ラベルを使用して実行フローを記述します。

結果はグラフであり、プログラムの動作はその表現の「トポロジ」によって決定されます。

goal:- 
   hasVarName(Vid_s, s),
   hasVarName(Vid_d, d),
   hasVarValue(Vid_d, Vd),

   %eq: [Vd>0] -> [val_s = 2]
   ((not(gt(Vd,0)); hasVarValue(Vid_s, 2), goto(label(0))),

   %eq: [~(Vd>0)^(Vd=0)] -> [val_s = 1]
   ((gt(Vd,0); not(eq(Vd,0)); hasVarValue(Vid_s, 1), goto(label(0))),

   %eq: [~(Vd>0)^~(Vd=0)] -> [val_s = 0]
   ((gt(Vd,0); eq(Vd,0); hasVarValue(Vid_s, 0)), % the goto is useless here...

   label(0),
   .....

サンプルプログラムを正しく説明するために注意を払っていないことに注意してください。この可能性を示すためにジャンプを配置しただけです...

編集チューリングマシンの停止問題に相当する一般的な問題は解決できないと思います。loops を使用しない特定のケースについては、AST で抽象解釈を使用して問題を攻撃します。つまり、何が興味深いかを計算するインタープリターです。

実行可能かどうかは、ターゲット プログラムの一般性に依存します。各条件点に含まれる変数ごとに整数ドメインを分割できる必要があります。物事は急速に複雑になります...

具体的には、IF THEN ELSE の条件ポイントで、ドメインを分割しようとします。このようなアプローチを使用して、Prologに両方のブランチをテストする IFを実行させ、値を伝播させます。しかし、前述のとおり、実際には簡単ではありません...

于 2012-10-25T13:16:34.240 に答える
0

次のブール値のアイデンティティを使用して、含意を介して if-then-else をモデル化しようとしたと思います。

A -> B == ~A v B.

含意の結合を使用する代わりに、分離を使用して分岐を選択し、制御フローに沿って結合する方が簡単です。ただし、否定を介して以前の if 条件を除外することは依然として必要です。

あなたの例を見てください:

if (d>0)
   s = 2;
else if (d==0)
   s = 1;
else
   s = 0;

CLP( * ) を使用してモデル化できます。変数がオーバーライドされないように変数を追加しますが、これは上の小さなスニペットでは問題になりません。CLP( * ) では、上記のスニペットは次のようになります。簡単にするために CLP(FD) を使用しています。

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.3.0)
Copyright (c) 1990-2012 University of Amsterdam, VU Amsterdam
?- use_module(library(clpfd)).
?- [user].
that_if(D, S) :-
   (D #> 0, S #= 2;
    D #=< 0, D #= 0, S #= 1;
    D #=< 0, D #\= 0, S #= 0)
^D

まともな CLP( * ) システムでは、クエリで D または S を任意にインスタンス化または制約できます。たとえば、すでに CLP(FD) に含まれています。

/* What conditions give result S #= 1 ? */
?- S #= 1, that_if(D, S).
S = 1,
D = 0 .

/* What results give condition D #= 1 */
?- D #= 1, that_if(D, S).
D = 1,
S = 2 ;
false.

/* What conditions give a result S #=< 1 */
?- S #=< 1, that_if(D, S).
S = 1,
D = 0 ;
S = 0,
D in inf.. -1.

/* What results give a condition D #>= 0 */
?- D #>= 0, that_if(D, S).
S = 2,
D in 1..sup ;
D = 0,
S = 1 ;
false.

さよなら

于 2012-10-25T06:22:03.237 に答える