替换数学公式中的参数时出错

Error in replacing arguments in math formula

我在替换数学公式中的参数时遇到一些递归问题。

我使用谓词替换数学公式中的参数。

replace(Term,Term,With,With) :-
    !.
replace(Term,Find,Replacement,Result) :-
    Term =.. [Functor|Args],
    replace_args(Args,Find,Replacement,ReplacedArgs),
    Result =.. [Functor|ReplacedArgs].

replace_args([],_,_,[]).
replace_args([Arg|Rest],Find,Replacement,[ReplacedArg|ReplacedRest]) :-
    replace(Arg,Find,Replacement,ReplacedArg),
    replace_args(Rest,Find,Replacement,ReplacedRest).

在 1 种情况下它工作正常,时间:

%正确工作示例

replace1(Result) :- 
    replace(
        f1(+(/(*(x, y), -(5, z)), *(*(x, y), z))), 
        *(x, y), 
        *(-(x, a), +(y, 1)), 
        Result).

% 替换后的结果:

?- replace1(Result).
Result = f1((x-a)*(y+1)/(5-z)+(x-a)*(y+1)*z).

2种情况下它不起作用,我无法解决问题,已经几天了...

%不工作示例 1):

replace3(Result) :- 
    replace(
        f3( ->(->(->(x, z), ->(->(y, z), ->(\/(x, y), z))), ->(\/(x, y), z) )),
        ->(A,B), 
        not(\/(A,B)), 
        Result
    ).

% 替换后的结果:

?- replace3(R).
R = f3(not(((x->z)->(y->z)->x\/y->z)\/(x\/y->z))).

%尝试了其他方法,但未能成功达到目标:

replace3(Result) :- 
    replace(
        f3( ->(->(->(x, z), ->(->(y, z), ->(\/(x, y), z))), ->(\/(x, y), z) )),
        ->(A,B), 
        not(\/(A,B)), 
        Result1
    ),  
    replace(
        Result1,
        ->(A,B), 
        not(\/(A,B)), 
        Result
    ).

% 替换后的结果:

?- replace3(R).
R = f3(not(((x->z)->(y->z)->x\/y->z)\/(x\/y->z))).

但是如果手动将之前的结果插入到新的调用中,那么将再进行一次替换。

%手动插入以前的结果从 replace3 到 replace4

replace4(Result) :- 
    replace(
        f3(not(((x->z)->(y->z)->x\/y->z)\/(x\/y->z))),
        ->(A,B), 
        not(\/(A,B)), 
        Result
    ).

% 替换后的结果:

?- replace4(R).
R = f3(not(not((x->z)\/((y->z)->x\/y->z))\/(x\/y->z))).

有人可以给我建议哪里做错了吗? 我试图尽可能完整地解释。 非常感谢您的帮助!

我认为这个谓词从句是你的问题:

replace(Term,Term,With,With) :- !.

如果整个表达式与find表达式匹配,则在顶层进行替换,然后整个替换过程停止。在您的具体情况下:

replace(
    f3( ->(->(->(x, z), ->(->(y, z), ->(\/(x, y), z))), ->(\/(x, y), z) )),
    ->(A,B), 
    not(\/(A,B)), 
    Result
).

您的输入表达式已经是 f3(->(A,B)) 形式,所以您的 最终 结果是 f3(not(\/(A,B))) 并且第一个谓词子句的设计为 replace/4 确保 AB 都不会被进一步检查:

f3(not(((x->z)->(y->z)->x\/y->z)\/(x\/y->z))).

这个问题实际上可能发生在递归的 任何 级别。一旦您的谓词看到与您的第一个 replace/4 谓词子句匹配的子词,它将在该级别替换但不再更深。

您需要用更详细的内容替换您的第一个子句,当外部项匹配时,它将递归地替换内部项。