假设我有一个等价关系eq
和多个二元运算符o_1, o_2, ... o_n
。我想找出哪些操作分布在其他操作上。假设我有一个可以确定两个表达式是否等价的知识库,一个简单的解决方案就是输入所有可能的查询:
(左派分布)
?- eq(o_1(Z,o_1(X,Y)),o_1(o_1(Z,X),o_1(Z,Y))).
?- eq(o_1(Z,o_2(X,Y)),o_2(o_1(Z,X),o_1(Z,Y))).
?- eq(o_1(Z,o_3(X,Y)),o_3(o_1(Z,X),o_1(Z,Y))).
...
?- eq(o_2(Z,o_2(X,Y)),o_2(o_2(Z,X),o_2(Z,Y))).
?- eq(o_2(Z,o_3(X,Y)),o_3(o_2(Z,X),o_2(Z,Y))).
...
?- eq(o_n(Z,o_n(X,Y)),o_n(o_n(Z,X),o_n(Z,Y))).
但必须有更好的方法来做到这一点。对于初学者,我想定义一个谓词left_dist
,以便left_dist(o_m,o_k)
为我生成相应的查询。我最初认为我会使用call
执行此操作,如
left_dist(O_m,O_k) :-
eq(call(O_m,Z,call(O_k,X,Y)),call(O_k,call(O_m,Z,X),call(O_m,Z,Y))).
但嵌套调用由于this question中概述的原因不起作用,我想这也不是处理Prolog编程的好方法。
所以问题是:如何在Prolog中定义left_dist
或以其他方式简化上述查询?
答案 0 :(得分:3)
左派分布意味着对所有x,y,z
:x*(y+z)=(x*y)+(x*z)
现在你没有提到具体领域,所以我假设所有关系都已经知道了。这假设Add_3
和Mult_3
始终终止。
not_left_dist(Mult_3, Add_3) :-
call(Add_3, Y, Z, YZ),
call(Mult_3, X, YZ, LHS),
call(Mult_3, X, Y, XY),
call(Mult_3, X, Z, XZ),
call(Add_3, XY, XZ, RHS),
neq(LHS, RHS).
left_dist(Mult_3, Add_3) :-
iwhen(ground(Mult_3+Add_3), \+ not_left_dist(Mult_3, Add_3) ).
这使用iwhen/2
。