SWIProlog中SICStus的nvalue/2等效值

SWIProlog中SICStus的nvalue/2等效值,prolog,swi-prolog,clpfd,sicstus-prolog,Prolog,Swi Prolog,Clpfd,Sicstus Prolog,CLP(FD)图书馆的手册说明: nvalue(?N,+变量)其中变量是具有有限边界或整数的域变量列表,N是整数或整数 域变量。如果N是 变量 当希望最小化解决方案中不同值的数量时,这尤其有用。例如,如果一个人试图把东西分到不同大小的袋子里,并且想尽量减少袋子的数量 在SWI Prolog中是否有一个等价的谓词(或方法)来实现相同的功能?在@jschimpf comment之后,我重新思考了算法 nvalue(1, [_]). nvalue(C, [V|Vs]) :- count_equ

CLP(FD)图书馆的手册说明:

nvalue(?N,+变量)
其中
变量
是具有有限边界或整数的域变量列表,
N
是整数或整数 域变量。如果
N
变量

当希望最小化解决方案中不同值的数量时,这尤其有用。例如,如果一个人试图把东西分到不同大小的袋子里,并且想尽量减少袋子的数量


在SWI Prolog中是否有一个等价的谓词(或方法)来实现相同的功能?

在@jschimpf comment之后,我重新思考了算法

nvalue(1, [_]).
nvalue(C, [V|Vs]) :-
    count_equals(V, Vs, E),
    E #= 0 #/\ C #= R+1 #\/ E #> 0 #/\ C #= R,
    nvalue(R, Vs).

count_equals(_, [], 0).
count_equals(V, [U|Vs], E) :-
    V #= U #/\ E #= E1+1 #\/ V #\= U #/\ E #= E1,
    count_equals(V, Vs, E1).
进一步清理

在@jschimpf note之后,我再次调整了代码:现在它非常紧凑,这要感谢apply和yall库

nvalue(1, [_]).
nvalue(C, [V|Vs]) :-
    maplist({V}/[U,Eq]>>(Eq#<==>V#=U), Vs, Es),
    sum(Es, #=, E),
    E #= 0 #/\ C #= R+1 #\/ E #> 0 #/\ C #= R,
    nvalue(R, Vs).
编辑

我的代码有点迂腐,当然可以更紧凑(更清晰?):

N值(N,Vs):-
bagof(D,X^H^T^V^(追加(X[H|T],Vs),成员(V,T),V\=H#D),VRs),
总和(VRs,#=N)。

请注意,findall/3将不起作用,因为具体化变量D的副本将丢失发布的约束。

是这样吗?我不这么认为
fd_size/2
返回域的元素数。例如,
0..10中的X,fd_大小(X,11)
。我在寻找一种约束变量列表中不同元素数量的方法。你会期望
X在0..10,foo([X],1)
?我会期望
length(Vs,3),Vs ins 1..3,nvalue(2,Vs)
尽可能排除
Vs=[3,3]
Vs=[1,2,3]
,因为我们说,必须有两个不同的值。对clpz的改进。不正确:您的代码成功地实现了
nvalue(3[1,1,1,2])
,例如。重写得很好!请注意,您仍然可以通过使用
E#E1#/\(V#\=U)
count#U equals/3
中的求和转换为一个连词来简化,只需在外循环中将得到的布尔值求和即可。@jschimpf:再次感谢。我听了你的暗示,但简化了。。。希望我做对了。。。至少,看起来还可以。和我想的不完全一样。您不需要计算满足等式的和
E
,只要计算一个布尔值
D
,如果所有等式都为假,则该值为真。然后您可以将
E#=0#/\C#=R+1#\/E#>0#/\C#=R
简化为
C#=R+D
% nvalue(?N, +Variables)
nvalue(N, Vs) :-
    nvalues(Vs, [], VRs),
    sum(VRs, #=, N).

nvalues([], Acc, Acc).
nvalues([V|Vs], Acc, VRs) :-
    nvalues_(V, Vs, Acc, Upd),
    nvalues(Vs, Upd, VRs).

nvalues_(_V, [], Acc, Acc).
nvalues_(V, [U|Vs], Acc, Upd) :-
    V #\= U #<==> D,
    nvalues_(V, Vs, [D|Acc], Upd).
?- length(Vs, 3), Vs ins 1..3, nvalue(2, Vs), label(Vs).
Vs = [1, 1, 2] ;
Vs = [1, 1, 3] ;
Vs = [1, 2, 1] ;
Vs = [1, 2, 2] ;
Vs = [1, 3, 1] ;
Vs = [1, 3, 3] ;
Vs = [2, 1, 1] ;
Vs = [2, 1, 2] ;
Vs = [2, 2, 1] ;
Vs = [2, 2, 3] ;
Vs = [2, 3, 2] ;
Vs = [2, 3, 3] ;
Vs = [3, 1, 1] ;
Vs = [3, 1, 3] ;
Vs = [3, 2, 2] ;
Vs = [3, 2, 3] ;
Vs = [3, 3, 1] ;
Vs = [3, 3, 2].
nvalue(N, Vs) :-
    bagof(D, X^H^T^V^(append(X, [H|T], Vs), member(V, T), V #\= H #<==> D), VRs),
    sum(VRs, #=, N).