2016-02-17 52 views
3

我试图编写一个谓词来执行与circuit相同的操作,但忽略数组中的零,我不断收到以下错误:MiniZinc:类型错误:预期`int [int] int,实际`array [int] var var int

MiniZinc: type error: initialisation value for 'x_without_0' has invalid type-inst: expected 'array[int] of int', actual 'array[int] of var opt int'

代码:

% [0,5,2,0,7,0,3,0] -> true 
% [0,5,2,0,4,0,3,0] -> false (no circuit) 
% [0,5,2,0,3,0,8,7] -> false (two circuits) 
predicate circuit_ignoring_0(array[int] of var int: x) = 
    let { 
     array[int] of int: x_without_0 = [x[i] | i in 1..length(x) where x[i] != 0], 
     int: lbx = min(x_without_0), 
     int: ubx = max(x_without_0), 
     int: len = length(x_without_0), 
     array[1..len] of var lbx..ubx: order 
    } in 
    alldifferent(x_without_0) /\ 
    alldifferent(order) /\ 

    order[1] = x_without_0[1] /\ 
    forall(i in 2..len) (
    order[i] = x_without_0[order[i-1]] 
) 
    /\ % last value is the minimum (symmetry breaking) 
    order[ubx] = lbx 
; 

我使用MiniZinc v2.0.11

编辑

每Kobbe的建议,认为这是具有可变长度数组的问题,我用"the usual workaround"保持order阵列相同的大小和原来阵列x,并使用参数,nnonzeros的,跟踪该阵列的一部分,我在乎:

set of int: S = index_set(x), 
int: u = max(S), 
var int: nnonzeros = among(x, S), 
array[S] of var 0..u: order 
+0

错误告诉x_without_0是VAR int数组,你把它定义为INT这就是为什么它失败的数组。也许你还想将lbx和ubx定义为var ints? – Emilien

+0

@Emilien不错的想法,但不幸的是,当我将x_without_0的类型更改为var int的'array [int],将lbx/ubx更改为'var int'时,该错误仅变为'expected'var [int] int',实际'var opt int''的数组[int]。 – UnderwaterKremlin

+0

是的,事实上,定义x_without_0的公式使其成为可选var整数的数组。我不是很了解这个[新功能](http://www.minizinc.org/2.0/doc-lib/doc-optiontypes.html)([出版物](http://people.eng.unimelb。 edu.au/pstuckey/papers/mznopt.pdf)) – Emilien

回答

1

这种回答你的问题:

您所遇到的问题是,你的数组大小依赖于var。这意味着MiniZinc无法真正知道应该创建的数组的大小,并且使用了opt类型。如果你不知道如何处理它,我建议你远离opt类型。

通常,解决方法是在数组不依赖于var的大小的情况下制定一些解决方法。我的解决方案是最常见的垫阵列,即[2,0,5,0,8] -> [2,2,5,5,8],如果应用程序允许的话,还是

var int : a; 
[i * bool2int(i == a) in 1..5] 

如果你还好在你的答案零(我猜不是在这种情况下)。

此外,alldifferent_except_0可能会对您有利,或者至少您可以看看alldifferent_except_0如何解决答案中的零问题。

predicate alldifferent_except_0(array [int] of var int: vs) = 
forall (i, j in index_set(vs) where i < j) ( 
    vs[i]!=0 /\ vs[j]!=0 -> vs[i]!=vs[j] 
) 

MiniZinc documentation

+0

是的,就是这样!实际上,MiniZinc不会允许在运行时确定数组大小。要将此标记为接受的答案。 – UnderwaterKremlin

相关问题