代码之家  ›  专栏  ›  技术社区  ›  Enrique

k个连续整数约束

  •  1
  • Enrique  · 技术社区  · 11 年前

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

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

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

    1 回复  |  直到 11 年前
        1
  •  2
  •   hakank    11 年前

    也许使用正则约束(Comet中的自动机)将是最好的方法。

    然而,在MiniZinc中有一个简单的解决方案,它使用了大量的具体化。至少可以将其翻译成彗星(我认为古罗比不支持实体化)。

    决策变量(序列)在数组“x”中。它还使用一个辅助数组(“starts”),其中包含每个序列的起始位置;这使得对“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];