3

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

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

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 种情况下,它可以正常工作,当:

  • % 初始公式:(x y/5-z)+x y*w
  • % 查找:x*y
  • % 替换:xa*y+1
  • % 在前缀视图中准备公式:+/*xy -5z **xyw
  • % 在前缀视图中查找:*xy
  • % 在前缀视图中替换:*-xa+y1

%正确工作示例

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 情况下它不起作用,我无法解决问题,已经几天了......

  • % 初始公式:((x->z)->((y->z)->(x/y->z))->(x/y->z))
  • % 查找:A->B
  • % 替换:不是(A/B)
  • % 评论:逻辑德摩根规则。蕴涵定理。
  • % 在前缀视图中准备公式:( ->->->xz ->->yz->/xyz ->/xyz )
  • % 在前缀视图中查找:->(A, B)
  • % 在前缀视图中替换:not(/(A, B))

%不工作示例 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))).

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

4

1 回答 1

1

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

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确保既A不会也B不会进一步检查:

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

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

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

于 2017-09-08T16:10:54.757 回答