我尝试使用Prolog(SWI-Prolog)检查学生数学表达的正确性。因此,例如,如果要求学生添加三个变量x,y和z,并且有一个规则,即必须添加的前两个变量是:x和y(以任何顺序),以及必须的最后一个变量如果学生的答案是以下任何一个,我希望prolog可以给我真正的价值:
X + Y + Z
(x + y)+ z
Z +(X + 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.
答案 0 :(得分:1)
您应该尝试指定语法并为表达式编写解析器。
避免断言/撤回,这会使程序更多更难理解,而是尝试掌握Prolog的声明性模型。
表达式是递归数据结构,使用具有已知优先级和关联性的运算符进行组合,并使用括号在需要的地方更改指定的优先级。
请参阅this答案,了解解析器和评估者,它接受来自 text 的输入。在您的问题中,您将显示代码中的表达式。然后你使用Prolog的解析器来完成脏工作,并且可以简单地在结果语法树上表达你的要求:
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 .
编辑:我们可以提供我们想要的模板,让Prolog通过统一来制定详细信息:
% 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.