You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Prolog递归加法异常求助:s(0)与p(0)无法抵消导致结果错误

问题:前驱后继加法中的化简错误

我写了一段Prolog代码实现带s(0)(0的后继)和p(0)(0的前驱)的加法,执行查询:

?- add3(p(0)+s(s(0)),s(s(0)),Z). 

得到结果Z = p(s(s(s(s(0))))),但预期结果应该是Z = s(s(s(0)))——因为p(0)本该和一个s(0)抵消。不清楚递归哪里出问题,求排查。

原知识库代码

% Original add
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
add(p(X), Y, p(Z)) :- add(X,Y,Z).

% Base case when 0 cannot be broken down further
simple(0,0).
simple(p(s(0)), 0).
simple(s(p(0)), 0).

% Change to make to simplify expression

simple(s(X),s(Y)) :-
    simple(X,Y).

simple(p(X), p(Y)) :-
    simple(X, Y).

% Case if X+Y
simple(X+Y,Z) :-
    simple(X,XS),
    simple(Y,YS),
    add(XS,YS,Z).

% add3
add3(A,B,C) :-
    simple(A,RA),
    simple(B,RB),
    add(RA,RB,C).

问题根源

你的simple/2规则只处理直接嵌套的s(p(0))或p(s(0)),但当化简p(0)+s(s(0))时,simple/2会先分别化简p(0)和s(s(0))——这两个都触发不了抵消的基准规则(p(0)不是p(s(0)),s(s(0))也不是s(p(0)))。随后调用add(p(0), s(s(0)), Z),原add/3规则直接给结果加了p前缀,得到p(s(s(0))),再和第二个参数s(s(0))相加,最终得到p(s(s(s(s(0))))),完全没机会触发抵消逻辑。

简单说:你的化简逻辑只处理已经成对出现的s(p(...))或p(s(...)),但没处理分散的p和s在加法后可以抵消的情况。


修复方案

方案1:先合并为纯序列再化简

调整思路:先把所有表达式转换成纯s/p的嵌套序列,再对序列进行化简抵消p和s。

修改后的代码:

% 基础加法:将表达式转换为纯s/p嵌套形式
add_raw(0, X, X).
add_raw(s(X), Y, s(Z)) :- add_raw(X, Y, Z).
add_raw(p(X), Y, p(Z)) :- add_raw(X, Y, Z).
add_raw(X+Y, Z, Result) :- add_raw(X, Y, Temp), add_raw(Temp, Z, Result).

% 化简纯s/p序列:抵消相邻的p和s
simplify(0, 0).
simplify(s(p(X)), Y) :- simplify(X, Y).
simplify(p(s(X)), Y) :- simplify(X, Y).
simplify(s(X), s(Y)) :- simplify(X, Y).
simplify(p(X), p(Y)) :- simplify(X, Y).

% 最终的add3:先转成纯序列,再化简
add3(A, B, C) :-
    add_raw(A, B, Temp),
    simplify(Temp, C).

方案2:调整化简顺序(先相加再化简)

修改原simple/2的加法规则,先执行加法再化简,而非先化简再相加:

% 原add规则保留
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
add(p(X), Y, p(Z)) :- add(X,Y,Z).

% 化简规则调整:加法先计算再化简
simple(0,0).
simple(s(p(X)), Y) :- simple(X, Y).
simple(p(s(X)), Y) :- simple(X, Y).
simple(s(X), s(Y)) :- simple(X, Y).
simple(p(X), p(Y)) :- simple(X, Y).
simple(X+Y,Z) :-
    add(X,Y,Temp),  % 先相加,再化简
    simple(Temp,Z).

% add3规则:最后再对加法结果化简一次
add3(A,B,C) :-
    simple(A,RA),
    simple(B,RB),
    add(RA,RB,Temp),
    simple(Temp,C).

测试验证

执行原查询:

?- add3(p(0)+s(s(0)),s(s(0)),Z). 

两种方案都会得到正确结果:Z = s(s(s(0)))

内容的提问来源于stack exchange,提问作者ggplot2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 01:20:21