我想问一下如何简化表达式:
1+2+a*5+0/b-c*0
= 3+a*5
尤其如何在列表中分隔这些表达式。
答案 0 :(得分:2)
在Prolog中实际上很有趣,因为你不需要做任何太神奇的事情来使它工作。
?- X-Y = 1+2+a*5+0/b-c*0.
X = 1+2+a*5+0/b,
Y = c*0.
所以你可以从做这样的事情开始:
simplify(C, C) :- atom(C) ; number(C).
simplify(X+Y, X1+Y1) :- simplify(X, X1), simplify(Y, Y1).
simplify(X*Y, X1*Y1) :- simplify(X, X1), simplify(Y, Y1).
simplify(X/Y, X1/Y1) :- simplify(X, X1), simplify(Y, Y1).
simplify(X-Y, X1-Y1) :- simplify(X, X1), simplify(Y, Y1).
这是一种身份变换:它没有做任何事情。
?- simplify(1+2+a*5+0/b-c*0, Result).
Result = 1+2+a*5+0/b-c*0.
现在您可以为特定情况添加规则:
simplify(X*0, 0).
simplify(0*X, 0).
现在你得到了多个结果:
?- simplify(1+2+a*5+0/b-c*0, Result).
Result = 1+2+a*5+0/b-c*0 ;
Result = 1+2+a*5+0/b-0 ;
您可以为常量折叠添加规则:
simplify(X+Y, C) :- number(X), number(Y), C is X+Y.
你知道,只是玩得开心。
列表并不是更容易使用,但您可以使用“univ”运算符制作它们:=..
:
?- 1+2+a*5+0/b-c*0 =.. R.
R = [-, 1+2+a*5+0/b, c*0].
答案 1 :(得分:2)
可以使用统一来简化Prolog中的表达式,但这有时会导致意外的结果。在此示例中,当“匹配”模式时,即使表达式中的两个不同变量是不同的,它们也会统一在一起:
:- initialization(main).
simplify(A+A,2*A).
main :-
simplify(A+B,C),
writeln(C).
在这种情况下,simplify(A+B,C)
将A
与B
统一。
为解决此问题,我使用subsumes_term/2
来匹配模式,而不用统一表达式中的变量。除非subsumes_term(A+A,Input)
已与A+B
统一,否则A
将与B
不匹配:
simplify(Input,2*A) :-
subsumes_term(A+A,Input).
这个subsumes_term/2
谓词通常对元编程很有用:我用它来编写Prolog-to-Minizinc compiler。