替换prolog中的部分表达

时间:2013-11-24 04:39:41

标签: replace prolog

我需要简化prolog中的身份(例如x+0 = xx-x=0等)。为此,我需要替换表达式的部分内容(例如x+0表示x)。

你可以帮我替换一下吗?

2 个答案:

答案 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