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

时间:2013-11-26 15:46:01

标签: replace prolog expression

我定义了一个谓词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))请尽快提供帮助。 谢谢。

1 个答案:

答案 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稍好一些,也许它可以倒退来做到这一点,但这个不是。我把这作为学生的练习。