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

时间:2018-02-15 19:48:24

标签: list prolog clpfd clp

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

Object.keys(this.state.days).filter(day => this.state.days[day])

是否有办法添加约束,以便变量可以接受值列表 在指定的域名? 对于最大3个元素列表的约束怎么样,其值在1..5范围内?

最后一个问题: 一个变量Y,它可以接受最多3个元素的列表,这些元素位于接受的值域中 变量X(为了它恰好是1..5)?

任何示例或提示如何开始构建这样的约束?

根据潜伏者:

 ?- X in 1..3, X #= 3.
 X = 3.

只有最后一个关闭,应该是真的..让我改进其中一个约束:)

  

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

哈,这很有效:

?- 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.

CLP有多酷:)

现在又一个改进。如何使列表中的元素不重复?

3 个答案:

答案 0 :(得分:2)

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

采用像Prolog的 length / 2 这样的谓词:虽然逻辑上可以这样做 在CLP中被视为其参数值的“约束” 术语我们通常不称之为约束,因为它会 每当这些参数时,不确定地为其参数生成值 没有充分实例化。

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

现在,约束求解器带有许多预定义约束 在一个特定的变量域上(最广泛使用的是约束 整数变量)。但是你想约束一个变量 来自列表的值。你没有现成的 实现,所以你可能想写自己的。 CLP 系统的不同之处在于它们可以让您定义自己的系统 自己的约束。在以下示例中,我使用ECLiPSe延迟 子句功能,因为这可能是最具可读性的(免责声明: 我亲自参与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)

但是当信息不足时,它会等待(如图所示) “延迟目标”消息):

?- c_len(Xs, 3), Xs = [_,_|Tail].
Xs = [_64, _66|Tail]
There is 1 delayed goal.
Yes (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).

这可以强制执行您想要的列表属性(此处长度为1到3和值 介于1和5之间):

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

答案 1 :(得分:1)

根据潜伏者的说法,这似乎是一个List的解决方案,其中包含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.

答案 2 :(得分:0)

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

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

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

删除X in 1..3L ins 1..5后,它的工作原理相同。

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

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