Replace 替换prolog中列表中的多个术语

Replace 替换prolog中列表中的多个术语,replace,prolog,expression,Replace,Prolog,Expression,我已经定义了一个谓词replace(单词\u to\u be\u replacement,replacement,[List\u requires\u replacement],[storing\u List]),我正在使用它简化算术表达式,如:- simplify([Head|Tail], Simplified) :- (replace(add(a,a), 2*a, [Head|Tail], L) ; L = [Head|Tail]), !, Simplified = L. 现在的问题

我已经定义了一个谓词
replace(单词\u to\u be\u replacement,replacement,[List\u requires\u replacement],[storing\u List])
,我正在使用它简化算术表达式,如:-

simplify([Head|Tail], Simplified) :-
   (replace(add(a,a), 2*a, [Head|Tail], L) ; L = [Head|Tail]), !, Simplified = L.
现在的问题是,我想用
2*x+y
替换像
x+y+x
这样的术语。用户输入的算术表达式将采用以下形式 示例
添加(x,div(1,z))
请尽快提供帮助。
谢谢。

您需要以某种方式规范您的条款。这是一个非常不完整的草图,描述了我将如何接近它。我认为这种方法是可以被证明的,但是你需要做大量的重复检查,以确保它正确地处理每一个案例

首先,请注意它的规范形式:

?- 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
稍微好一点,也许可以倒着运行,但这个不行。我把这个留给学生做练习