简化Prolog中的表达式

时间:2016-12-22 07:59:15

标签: prolog

我想问一下如何简化表达式:

1+2+a*5+0/b-c*0
= 3+a*5

尤其如何在列表中分隔这些表达式。

2 个答案:

答案 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)AB统一。

为解决此问题,我使用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