List SWI:约束:域D中最多N个元素的列表?

List SWI:约束:域D中最多N个元素的列表?,list,prolog,clpfd,clp,List,Prolog,Clpfd,Clp,我可以为变量分配一个可能值的域,即: ?- X in 1..3, X #= 3. X = 3. 有没有一种方法可以添加约束,使变量可以接受一系列值 在指定的域中? 对于一个最多包含3个元素且值在1到5范围内的列表的约束如何 最后一个问题是: 一个变量Y,可以接受最多3个元素的列表,这些元素在接受的值域中 通过变量X(为了方便起见,正好是1..5) 有没有示例或提示如何开始构建这样的约束 根据潜伏者的说法: ?- L=[1,2,3], length(L, 3), L ins 1..5. L

我可以为变量分配一个可能值的域,即:

 ?- X in 1..3, X #= 3.
 X = 3.
有没有一种方法可以添加约束,使变量可以接受一系列值 在指定的域中? 对于一个最多包含3个元素且值在1到5范围内的列表的约束如何

最后一个问题是: 一个变量Y,可以接受最多3个元素的列表,这些元素在接受的值域中 通过变量X(为了方便起见,正好是1..5)

有没有示例或提示如何开始构建这样的约束


根据潜伏者的说法:

?- L=[1,2,3], length(L, 3), L ins 1..5.
L = [1, 2, 3].

?- L=[1,2,3,4], length(L, 3), L ins 1..5.
false.

?- L=[1,2,6], length(L, 3), L ins 1..5.
false.

?- L=[1,2,5], length(L, 3), L ins 1..5.
L = [1, 2, 5].


?- L=[4,5], length(L, 3), L ins 1..5.
false.
只有最后一个是错的,应该是真的。。让我细化其中一个约束:)

列出1到3个元素,而不是仅3个元素


哈,这个奏效了:

?- L=[4,5], X in 1..3, length(L, X), L ins 1..5.
L = [4, 5],
X = 2.
中电有多酷:)



现在再做一次改进。如何使列表中的元素不重复

根据潜伏者的说法,这似乎是一个列表的解决方案,其中1到3个元素的不可重复数字在1的范围内。。5:

 ?- L=[4,1,Z], X in 1..3, length(L, X), L ins 1..5, all_distinct(L).
 L = [4, 1, Z],
 X = 3,
 Z in 2..3\/5,
 all_distinct([4, 1, Z]).

 ?- L=[4,1,1], X in 1..3, length(L, X), L ins 1..5, all_distinct(L).
 false.

 ?- L=[4,1,2], X in 1..3, length(L, X), L ins 1..5, all_distinct(L).
 L = [4, 1, 2],
 X = 3.

 ?- Lst=[3,1,5], Length in 1..3, length(Lst, Length), Lst ins 1..5, all_distinct(Lst).
 Lst = [3, 1, 5],
 Length = 3.

这段代码毫无意义,实际上也没有使用clpfd

?- L=[4,5], X in 1..3, length(L, X), L ins 1..5.

L = [4, 5],
X = 2.
删除1..3中的
X和1..5中的
L后,它的工作原理相同

?- L=[4,5],length(L,X).

L = [4, 5],
X = 2.

在CLP中,将约束与不确定性分开是很重要的 (搜索)。在基于Prolog的框架中,这种区别并不明显 在语言中显而易见,这常常使初学者感到困惑

以Prolog的length/2这样的谓词为例:从逻辑上讲,这可以 在CLP中,被视为对其参数值的“约束” 术语我们通常不称之为约束,因为它会 每当这些参数 没有充分实例化

我们期望约束的行为更加被动:它 应禁止其参数采用约束指定的值 语义不允许,但不能主动生成任意有效的 价值观原因是我们通常想要建立一个整体 开始之前的约束网络(约束设置阶段) 探索不同的变量分配(搜索阶段)

现在,约束解算器附带了许多预定义的约束 在某个变量域上(最广泛使用的是 整数变量)。但是您想约束一个变量,使其 列表域中的值。你没有现成的 实现,所以您可能需要编写自己的。中电 系统在支持您定义您的应用程序方面有所不同 自我约束。在下面的示例中,我使用的是 子句功能,因为这可能是最可读的(免责声明: 我个人参与了ECLiPSe)

这里是一个简单的长度约束。请注意“延迟条款”,即 如果任一参数未实例化,则导致谓词等待:

delay c_len(Xs, N) if var(Xs) ; var(N).
c_len([], 0).
c_len([_|Xs], N) :-
        N1 is N-1,
        c_len(Xs, N1).
这可以确保变量只使用特定长度的列表:

?- c_len(Xs, 3), Xs = [_,_].
No (0.00s cpu)

?- c_len(Xs, 3), Xs = [_,_,_].
Xs = [_76, _78, _80]
Yes (0.00s cpu)

?- c_len(Xs, 3), Xs = [_,_,_,_].
No (0.00s cpu)
但是当没有足够的信息时,它会等待(如 “延迟目标”信息:

在最后一个示例中,我们看到,尽管约束是正确的(在 它不允许对其参数进行无效实例化的感觉), 它实际上可能更聪明一些,并推断
Tail
必须是长度为1的列表。 这是相当典型的:约束的操作行为(通常是 在不同的实现中,被称为“传播强度”的参数可能会有所不同。 通常,它反映了传播强度和传播速度之间的折衷 计算复杂性

这里有一个更好的实现。它利用有限的 域变量,并且还实现了您的约束需求 列表元素的域:

:- use_module(library(ic)).    % provides finite domain solver

delay bounded_list(Xs,_Lo,_Hi,Len) if var(Xs), var(Len).
bounded_list([],_Lo,_Hi, 0).
bounded_list([X|Xs], Lo, Hi, Len) :-
        Len #> 0,
        Lo #=< X, X #=< Hi,
        Len1 #= Len-1,
        bounded_list(Xs, Lo, Hi, Len1).
它还进行一些早期推断,例如使用 适当的整数域:

?- bounded_list(Xs, 1, 5, 3).
Xs = [_319{1..5}, _472{1..5}, _625{1..5}]
Yes (0.00s cpu, ...)

例如,您可以说
length(L,3),L in 1..5
以获得长度为3的列表,其中每个元素都在1到5的范围内。不确定您的最后一个问题…您使用的是什么版本的prolog?SWI,ECLiPSe?最后一个q是第二个的重述。我指的不是域,而是从变量中查找域,而不是直接定义域。对于ECLiPSe,您可以基于另一个变量的域来分配变量的域……如果不希望列表元素重复,请查找
all\u distinct/1
约束。它在文档中。扰流板:
1.5中的L个元素,所有元素都不同(L)
。这只是我给出的示例之一。不理解的是:列表不能超过3个元素,在指定的1.5范围内,不能重复。其他ppl明白了!!!使用clp变量时,必须确定它们的“数量”。因此,length/2的第二个变量不能是clp变量(至少没有意义)。当您对变量应用clp约束时,swi prolog使用属性变量机制隐式地将它们转换为clp变量(从普通prolog变量)。当您使用clpfd时,您必须始终注意您使用的是哪种谓词,普通prolog谓词或clp谓词。就像我们经常注意的那个样,谓词是否决定了选择点。
?- N #:: 1..3, bounded_list(Xs,1,5,N), Xs = [1,2,3].
N = 3
Xs = [1, 2, 3]
Yes (0.00s cpu)

?- N #:: 1..3, bounded_list(Xs,1,5,N), Xs = [1,2,3,4].
No (0.00s cpu)

?- N #:: 1..3, bounded_list(Xs,1,5,N), Xs = [1].
N = 1
Xs = [1]

?- N #:: 1..3, bounded_list(Xs,1,5,N), Xs = [1,9].
No (0.00s cpu)
?- bounded_list(Xs, 1, 5, 3).
Xs = [_319{1..5}, _472{1..5}, _625{1..5}]
Yes (0.00s cpu, ...)