2012-04-03 15 views
1

Prolog(SWI-Prolog)を使用して、学生の数式の正確性をチェックしようとします。たとえば、x、y、zの3つの変数を追加するように求められた場合、追加する必要がある最初の2つの変数は、xとy(任意の順序)、最後に必要な変数SWI-Prolog。数式の正確性を確認する

X + Y + Z

(X + Y)+ Z

Z +(X:追加するには、私が学生の答えはこれらのいずれかであればプロローグは私の真の価値を与えることができることを期待して、その後のzであります+ Y)

Z + X + Y

Y + X + Z

など多くの可能性があります。

私は、このチェックのために以下のルールを使用します。

addData :- 
    assert(variable(v1)), 
    assert(variable(v2)), 
    assert(variable(v3)), 
    assert(varName(v1,x)), 
    assert(varName(v2,y)), 
    assert(varName(v3,z)), 
    assert(varExpr(v1,x)), 
    assert(varExpr(v2,y)), 
    assert(varExpr(v3,z)). 


add(A,B,R) :- R = A + B. 

removeAll :- retractall(variable(X)), 
    retractall(varName(X,_)), 
    retractall(varExpr(X,_)). 


checkExpr :- 
     % The first two variable must be x and y, in any combination 
     ( (varExpr(v1,AExpr), varExpr(v2,BExpr)); 
      (varExpr(v2,AExpr), varExpr(v1,BExpr)) 
     ), 
     add(AExpr, BExpr, R1), 

     % store the expression result as another variable, say v4 
     retractall(variable(v4)), 
     retractall(varName(v4, _)), 
     retractall(varExpr(v4, _)), 

     assert(variable(v4)), 
     assert(varName(v4, result)), 
     assert(varExpr(v4, R1)), 

     % add the result from prev addition with Z (in any combination) 
     ( (varExpr(v3,CExpr), varExpr(v4,DExpr)); 
      (varExpr(v4,CExpr), varExpr(v3,DExpr)) 
     ), 

     add(CExpr, DExpr, R2), 

     R2 = z + x + y.    % will give me false 
     % R2 = z + (x + y).   % will give me true 
             % Expected: both should give me true 


checkCorrect :- removeAll, 
      addData, 
      checkExpr. 

答えて

1

あなたは文法を指定して、あなたの表現のためにパーサを書くようにしてください。 ずっとより困難を理解し、プロローグの宣言型モデルを習得する代わりにしようとするためのプログラムを作る

避けアサート/後退、。

式は、再帰データ構造、構成する既知優先連想オペレータを使用し、そして必要な場合、指定の優先順位を変更するための括弧です。

テキストからの入力を受け付けるパーサ評価者のためのthis答えを、参照してください。あなたの質問でコードからの表現を表示します。そして、あなたは汚い仕事をするためにプロローグ」パーサーを使用している、と単純に結果構文木上の要件を表現することができます。

expression(A + B) :- 
    expression(A), 
    expression(B). 
expression(A * B) :- 
    expression(A), 
    expression(B). 

expression(V) :- 
    memberchk(V, [x,y,z]). 

?- expression(x+y+(x+z*y)). 
true . 

が編集:我々はプロローグを私たちが何をしたいのテンプレートを提供してみましょうことができます統一によって細部を詰める:

% enumerate acceptable expressions 
checkExpr(E) :- 
    member(E, [F = A + D, F = D + A]), 
    F = f, 
    A = c * N, 
    N = 1.8, 
    D = d. 

のように...

テスト:

?- checkExpr(f=(c*1.8)+d). 
true. 

?- checkExpr(f=(c*1.8)+e). 
false. 

?- checkExpr(f=d+c*1.8). 
true. 
+0

こんにちはチャック、提案に感謝します。しかし、この場合、私は特定のタスクを解決するコードを持っていたいと思います。したがって、この場合、追加できる最初の2つの変数はxとyであり、この加算の結果をzに加算することができます。この場合の正しい式は、x + y + z、y + x + z、(x + y)+ z、(y + x)+ z、z +(x + y)、z + )。例えば、実際のケースは、このタスクを解決することです:摂氏度から華氏度を計算します(dを32で格納)。次に、f = c * 1.8 + d、f = 1.8 * c + d、f = d + c * 1.8、f = d + 1.8 * c、 (c * 1.8)+ d。ありがとう –

+0

*宣言的なアプローチをとっておくことが重要です。*正確性を判断できる最小限のコードを書くようにしてください。あなたの場合は、* examples *を提供するのに便利です。編集を参照してください。 – CapelliC

+0

こんにちは。ありがとう。はい、私は私のプログラムでもっと宣言的なアプローチをしようとします。私の以前のアプローチは、まだ私のバックグラウンドから多くの影響をC#プログラマとして受けているようです。私が解決したい(例がたくさんあります)ケースの1つの例は、例えば摂氏を華氏に変換するための生徒の数式表現を確認することです。 f = d * 1.8 + c、f = d *(1.8 + c)、f = c *(1.8 + d)ここで、 )、 等々。ありがとう –