clpfd - 生成5到10之间所有整数的列表

时间:2016-04-12 01:01:38

标签: prolog clpfd

我正在使用SWI-Prolog来获取clpfd生成5到10之间所有不同整数的列表:

q1(Answer) :-
  length(Xs, Answer),
  Xs ins 0..20,
  chain(Xs, #<),
  maplist(q1constraints, Xs).

q1constraints(X) :-
  X #>= 5,
  X #=< 10.

有点工作,但为每个长度0,1,... 6生成一个解决方案然后挂起寻求长度为7的解决方案:

?- q1(Answer).
Answer = 0 ;
Answer = 1 ;
Answer = 2 ;
Answer = 3 ;
Answer = 4 ;
Answer = 5 ;
Answer = 6 ;
<hangs>

有没有一种很好的方法来生成满足所需约束的所有整数列表?

2 个答案:

答案 0 :(得分:3)

你的问题对我来说并不是那么清楚。但我会尝试:

?- length(Xs,6), Xs ins 5..10, chain(Xs, #<), Xs = [5|_], last(Xs, 10).
Xs = [5, 6, 7, 8, 9, 10].

请注意,使用这些元素时,必须先确定列表的长度。否则:

?- length(Xs,N), Xs ins 5..10, chain(Xs, #<), Xs = [5|_], last(Xs, 10).
Xs = [5, 10], N = 2 ;
Xs = [5, _A, 10], N = 3, _G7292 in 6..9 ;
Xs = [5, _A, _B, 10], N = 4, _A in 6..8,_A#=<_B+ -1,_B in 7..9 ;
Xs = [5, _A, _B, _C, 10], N = 5, _A in 6..7, _A#=<_B+ -1, _B in 7..8,_B#=<_C+ -1, _C in 8..9 ;
Xs = [5, 6, 7, 8, 9, 10], N = 6 ;
** LOOPS **

事实上,即使(ins)/2也不需要:

?- length(Xs,6), chain(Xs, #<), Xs = [5|_], last(Xs, 10).
Xs = [5, 6, 7, 8, 9, 10].

答案 1 :(得分:2)

以下是您的计划的作用:

  1. 从空列表开始生成一个不断增加的长度列表
  2. 对于列表中的每个元素X,提出X在[0,20]中的约束
  3. 对于整个列表,提出一个约束,即值的严重程度正在增加
  4. 对于列表中的每个元素,构建X在[5,10]中的附加约束。
  5. 然后询问生成列表的长度。

    [0,20]和[5,10]中有6个值:5,6,7,8,9,10。对于首先生成的空列表,没有约束变量;对于包含1个变量的列表,变量有6个可能的值,但是您不要求这些值,仅用于列表的长度;对于包含2个变量的列表,您将有5种可能的组合:{5,6},{6,7},...,{9,10},但同样,您不需要它们,仅用于列表的长度。

    最终,您将列出7个值。由于每个元素只有6个值,因此没有解决方案。

    那么你的目标是什么?也许你应该尝试更好地解释。要通过回溯获取5到10之间的所有值,您可以说:between(5, 10, X),或者使用CLPFD X in 5..10, label([X])。如果不是这些,你需要重新写下你的问题。