这个 Prolog 程序如何解析为 H=2?执行线看不懂

How does this Prolog program resolve to H=2? I don't understand the line of execution

我从 Prolog 上的 YouTube tutorial 中提取了以下 Prolog 块:

change(H, Q, D, N, P) :-
        member(H, [0, 1, 2]),
        member(Q, [0, 1, 2, 3, 4]),
        member(D, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
        member(N, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]),

        S is 50*H + 25*Q + 10*D + 5*N,
        S =< 100,
        P is 100-S.

这是一个找零钱的程序。 H 是半美元,Q 是四分之一,D 是一角硬币,N 是镍币,P 是便士。

如果我输入 change(H, 0, 0, 0, 0). 作为查询,它会解析为 H=2。视频里他说这是一个1元找零的程序,所以我知道两个半元是1元,但我不明白它是怎么算出来的。

我对 Prolog 的理解是,当我传递 change(H, 0, 0, 0, 0). 时,它会寻找满足条件的 H 值,因此它转到第一行,发现 0 可以,然后为其他 "member" 行看到传递的 0 也是正确的。

然后将 S 设置为一个值,给定上述值将是 S = 0。下一行确保它小于或等于 100,也就是 0,然后将 P 设置为 100-S(这是 100)。

H = 0 怎么没有完成?我错过了什么?

member(H,[0,1,2])H 绑定到 0、1 或 2。因为 QDNP 都是0,满足底部方程式的 H 的唯一值是 2。

H=0时,S为0,100-S为100,由于P为0,P is 100-S将失败。

H=1时,S为50,100-S为50,由于P为0,P is 100-S将失败。

H=2时,S为100,100-S为0,由于P为0,所以P is 100-S会成功。

除了操作解释之外,我想为此类问题建议CLP(FD)约束,它比低级算术谓词更容易理解并且更具声明性。例如,在 SICStus Prolog、YAP 和 SWI 中:

:- use_module(library(clpfd)).

change(H, Q, D, N, P) :-
        H in 0..2,
        Q in 0..4,
        D in 0..10,
        N in 0..20,

        S #= 50*H + 25*Q + 10*D + 5*N,
        S #=< 100,
        P #= 100-S.

现在让我们声明式推理:

如你所问H = 0,其他参数如你指定的0,那么P的允许值是多少?

?- change(0, 0, 0, 0, P).
P = 100.

由此可见,如果所有其他参数都是 0,那么您的查询唯一有效的解决方案是 P = 100。这样,目标change(0, 0, 0, 0, 0)肯定会失败。