我需要简化prolog中的身份(例如x+0 = x
,x-x=0
等)。为此,我需要替换表达式的部分内容(例如x+0
表示x
)。
你可以帮我替换一下吗?
答案 0 :(得分:1)
Prolog的一个巧妙之处在于你可以很容易地解构算术表达式。您的基本模板将如下所示:
simplify(X, X) :- number(X) ; atom(X) ; var(X).
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(3+X*y, Q).
Q = 3+X*y
将其视为空循环。掌握了这一点,您可以通过在此遍历中添加“特殊情况” 来开始处理您的身份。身份是你可以用这种方式处理的一件事:
simplify(1*X, X1) :- simplify(X, X1).
simplify(X*1, X1) :- simplify(X, X1).
simplify(0+X, X1) :- simplify(X, X1).
simplify(X+0, X1) :- simplify(X, X1).
尝试一下:
?- simplify(x*1+0, Q).
Q = x
你可以看到为什么我们在这里使用递归例程:
?- simplify(x+(y+(z*43)+0)*1, Q).
Q = x+(y+z*43)
即使+0深深嵌套在结构中,它也会被删除。我们也可以做一些更大的简化:
simplify(_*0, 0).
simplify(0*_, 0).
这里不需要递归,整个子表达式基本上被删除了:
?- simplify(x+(y+(z*43)+1)*0, Q).
Q = x+0 ;
你也可以做一些有趣的事情:
simplify(X*Y+Z*Y, Y1*(X1+Z1)) :-
simplify(X, X1), simplify(Y, Y1), simplify(Z, Z1).
尝试一下:
?- simplify(34*z+17*z, X).
X = z* (34+17)
?- simplify(34*z+z*17, X).
X = 34*z+z*17
这里的第二个例子表明这种处理存在限制。您不希望必须为模板提供每个排列。如果你想让它们更加智能化,你可能不得不采用更智能的中间表示,或者采用比简单统一更智能的模板应用方法。统一是伟大的,但它不了解可交换或关联属性。
为了更进一步,你可能想要深入挖掘Prolog。大多数Prolog书籍都研究过这类问题;我偏爱编程Prolog 和 Prolog的艺术,但我听说Bratko的书很棒。我建议你抓住其中一个并开始挖掘它。不过,不要犹豫,提出更多问题!
答案 1 :(得分:0)
可以使用=../2
替换表达式中的子项。基于this predicate,我写了一个谓词来替换术语中所有出现的模式:
:- initialization(main).
:- set_prolog_flag('double_quotes','chars').
main :- Input=((X+0)=(Y+0)-(Z+0)),replace(A+0,A,Input,Output),writeln(Input),writeln(Output).
replace(Subterm0_, Subterm_, Term0, Term) :-
copy_term([Subterm0_,Subterm_],[Subterm0,Subterm]),
( Term0=Subterm0 -> (Term = Subterm)
; var(Term0) -> Term = Term0
; Term0 =.. [F|Args0],
maplist_(Args0, Args, replace(Subterm0,Subterm)),
Term =.. [F|Args]
).
maplist_([], [], _).
maplist_([Elem1|Tail1], [Elem2|Tail2], replace(A,B)) :-
copy_term([A,B],[A1,B1]),
Goal=replace(A1,B1),
writeln(Goal),
call(Goal, Elem1, Elem2),
maplist_(Tail1, Tail2, Goal).
在这种情况下,输入为(X+0)=(Y+0)-(Z+0)
,输出为X=Y-Z
。