CLP Prolog - 逻辑编程

CLP Prolog - Logic Programming

我们有一个列表列表认为示例 ?- solve([[40,A,B],[30,B],[60,A,B,C]]),label([A,B,C]). 将成功替换 B=30、A=10 和 C=20。 此示例的约束是 A+B=40,A+B+C=60,通常每个变量都在 0 到 100 之间。每个列表必须以常量开头,并且它至少包含一个变量。

:- use_module(library(clpfd)).

sum([],0).                              % if the list is empty.
sum([X|XS],Z) :-
   sum(XS,Z1),
   X in 0..100,
   Z #= X+Z1.

solveOne([Const|Var]) :-
   sum(Var,Const). 

solve([]).                            % if the list of list is also empty
solve([First|Others]) :-
   solveOne(First),
   solve(Others).

我有点怀疑基本案例的想法,事实。因为每个列表必须根据约束在列表中包含一个变量,另一方面我们考虑 "empty list" 的情况。?

首先,明显的问题:您定义了一个 solve/2 和一个 solve/1 谓词 (solve([],0))。 “,0”可能是不需要的。

除此之外,如果你只有一个常量,比如[X],那么只有当X为零时solveOne才会成功;否则,根据 sum([],0) 失败。因此,从某种意义上说,如果您假设您的总和始终严格为正,则可以间接检查您是否可以拥有至少一个变量。

为了明确地检查至少有一个变量,那么你可以修改solveOne如下:

 solveOne([Const,V1|Vars]) :-
    sum([V1|Vars], Const).

@coredump 的回答应该会让你走上正轨。如果您有兴趣编写精益代码,请考虑这个更简洁的定义(在 SWI-Prolog 中测试)

solve(L) :- maplist(solveOne, L).
solveOne([C|Vs]) :- Vs ins 0..100, sum(Vs, #=, C).

?- solve([[40,A,B],[30,B],[60,A,B,C]]).
A = 10,
B = 30,
C = 20.