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, ...)