在Minizinc中混合两个可变大小的数组

时间:2018-05-08 09:23:10

标签: arrays minizinc

我有两个可变大小的数组a和b。

我想编写一个接受这两个数组的函数,并将返回一个新数组c(length(c)是length(a)+ length(b))具有以下特征: -

  • 变量必须与它们在原始数组中出现的顺序相同,例如,a = [x,y,z,a,b]和b = [p,q,r],然后c必须是这样的 c = [x,p,q,y,z,r,a,b](基本上是两个数组交错的顺序)或者它可以像这样c = [p,x,q,r,y,z, A,b]

    function array[int] of var int : mixed(array[int] of var int: a, 
    array[int] of var int: b) = 
    let { array [1 .. length(a++b)] of var int : c = %some magic here
    } in c
    ;
    

    我尝试了几种阵列理解但失败了。

1 个答案:

答案 0 :(得分:2)

如果我正确理解你的问题,那么你正在寻找一个函数,它返回一个数组,该数组可以包含两个给定数组的所有可能的交错。

这个问题似乎更复杂,因为生成的数组不能与参数相同的变量泄露,但必须是变量本身。

我担心我无法在理解中看到这样做的方法,但使用了一些全局变量。工作职能可以包括:

include "globals.mzn";

function array[int] of var int: interleave(array[int] of var int: a, array[int] of var int: b) = let {
        array[index_set(a)] of var 1..length(a ++ b): map_a;
        array[index_set(b)] of var 1..length(a ++ b): map_b;
        array[1..length(a ++ b)] of var dom_bounds_array(a ++ b): c;
        constraint all_different(map_a ++ map_b);
        constraint forall(i in index_set(a)) (c[map_a[i]] = a[i]);
        constraint increasing(map_a);
        constraint forall(i in index_set(b)) (c[map_b[i]] = b[i]);
        constraint increasing(map_b);
    } in c;

误解解决方案:逐个元素挑选:

您的问题的解决方案是结合多种理解:

  • 对交错数组的理解,其中每次从一个数组中选择元素。
  • 如果一个数组比另一个数组长,则添加其余元素的理解。

结果函数是:

function array[int] of var int: interleave(array[int] of var int: a, array[int] of var int: b) = let {
        array[int] of int: ai = [ i | i in index_set(a)];
        array[int] of int: bi = [ i | i in index_set(b)];
        int: share = min(length(a), length(b));
    } in [ if x = 1 then a[ai[i]] else b[bi[i]] endif | i in 1..share, x in 1..2]
        ++ [ a[ai[i]] | i in share+1..length(a) ]
        ++ [ b[bi[i]] | i in share+1..length(b) ];

同样重要的是要注意,在MiniZinc中,索引集不需要是连续的。因此,我们使用理解来获取索引集中的所有元素。这主要是为了使这个功能可用于任何类型的MiniZinc阵列。