我定义了一个谓词replace(word_to_be_replaced, replacement, [List_requires_replacement], [storing_List] )
,我用它来简化算术表达式,如: -
simplify([Head|Tail], Simplified) :-
(replace(add(a,a), 2*a, [Head|Tail], L) ; L = [Head|Tail]), !, Simplified = L.
现在我的问题是我想用x+y+x
替换2*x+y
之类的字词。用户输入的算术表达式将具有以下形式
示例add(x,div(1,z))
请尽快提供帮助。
谢谢。
答案 0 :(得分:2)
您需要以某种方式规范化您的条款。这是一个非常不完整的草图,描述了我如何接近它。我认为这种方法可以证明,但你需要做很多仔细检查才能正确处理每一个案例。
首先,注意它在规范形式中的表现:
?- write_canonical(x+y+x).
+(+(x,y),x)
true.
问题的关键在于此。一个x
位于树的深处。另一个是不同的水平。我们需要将它们全部放在同一个地方,以便我们可以一起处理它们。这意味着我们想以某种方式将它们移到同一个列表中。我想我们想要[+, x, y, x]
,因为我们可以将它排序到[+, x, x, y]
然后递归处理它。
?- x+y+x =.. Q.
Q = [+, x+y, x].
更好,但不是一直到那里。
expand(Var, Var) :- number(Var) ; atom(Var).
expand(Term, Expanded) :-
(\+ number(Var), \+ atom(Var)),
Term =.. Parts,
maplist(expand, Parts, Expanded).
?- expand(x+y+x, Q).
Q = [+, [+, x, y], x] ;
更好。现在我们需要以某种方式压扁它。
flatten_expr([Op, [Op|Inner] | Outer], Result) :-
append([Op|Inner], Outer, Result).
flatten_expr(Other, Other).
?- expand(x+y+x, Q), flatten_expr(Q, QFlat).
Q = [+, [+, x, y], x],
QFlat = [+, x, y, x]
如果我们在中间排序,我们可以继续生活。
flatten_expr([Op, [Op|Inner] | Outer], Result) :-
append([Op|Inner], Outer, ResultU),
msort(ResultU, Result).
flatten_expr(A, A).
现在,您可以将模式应用于这些并简化。
simplify([+, X, X | Rest0], [+, [*, 2, X] | Rest1]) :-
simplify([+, Rest0], [+, Rest1]).
?- expand(x+y+x, Q), flatten_expr(Q, QFlat), simplify(QFlat, Simplified).
Q = [+, [+, x, y], x],
QFlat = [+, x, x, y],
Simplified = [+, [*, 2, x], y]
然后你只需要一种转换回代数表示的方法。如果expand/2
稍好一些,也许它可以倒退来做到这一点,但这个不是。我把这作为学生的练习。