k个连续的整数约束

时间:2013-08-31 17:30:52

标签: optimization constraint-programming gurobi

如何在约束编程中声明以下约束? (最好是在Gurobi或Comet)。

S是大小为n的整数数组。我可以用来填充数组的整数集在1-k范围内。对于可以使用的每个整数,存在约束 ci ci 表示连续整数的最小数量 i

例如,如果c1 = 3,c2 = 2则1112211112111不是有效序列,因为必须有两个连续的2,而1112211122111是有效序列。

1 个答案:

答案 0 :(得分:2)

使用常规约束(Comet中的自动机)可能是最好的方法。

然而,这是一个简单的MiniZinc解决方案,它使用了大量的修改。应该可以将它翻译成Comet至少(我不认为Gurobi支持修改)。

决策变量(序列)在数组“x”中。它还使用一个辅助数组(“开始”),它包含每个序列的起始位置;这使得更容易推断“x”中的序列。序列的数量为“z”(例如,对于优化问题)。

根据x和其他约束的大小,可能会对可以有多少序列添加更多(冗余)约束。但是,这不是在这里完成的。

以下是模型:http://www.hakank.org/minizinc/k_consecutive_integers.mzn

它也显示如下。

int: n;
int: k;

% number of consecutive integers for each integer 1..k
array[1..k] of int: c;

% decision variables
array[1..n] of var 1..k: x;

% starts[i] = 1 ->  x[i] starts a new sequence
% starts[i] = 0 ->  x[i] is in a sequence
array[1..n] of var 0..k: starts;
% sum of sequences
var 1..n: z = sum([bool2int(starts[i] > 0) | i in 1..n]);

solve :: int_search(x, first_fail, indomain_min, complete) satisfy;

constraint
   forall(a in 1..n, b in 1..k) (
      (starts[a] = b ) -> 
         (
             forall(d in 0..c[b]-1) (x[a+d] = b )
             /\
             forall(d in 1..c[b]-1) (starts[a+d] = 0 )
             /\
             (if a > 1 then x[a-1] != b else true endif)    % before 
             /\
             (if a <= n-c[b] then x[a+c[b]] != b else true endif) % after
         )
  )
  /\
  % more on starts
  starts[1] > 0 /\
  forall(i in 2..n) (
     starts[i] > 0 <-> ( x[i]!=x[i-1] )
  )
  /\
  forall(i in 1..n) (
     starts[i] > 0 -> x[i] = starts[i]
  )
;

output [ 
     "z     : " ++ show(z) ++ "\n" ++
     "starts: " ++ show(starts) ++ "\n" ++
     "x     : " ++ show(x)  ++ "\n"
];


%
% data
%

%% From the question above:
%% It's a unique solution.
n = 13;
k = 2;
c = [3,2];