问题描述
我遇到的下一个问题是尝试计算数组中出现的次数,条件是它们与另一个数组中的值匹配。
我想结合以下模型
set of int: OPTS = 1..4;
set of int: ASSIGN = 1..12;
array[ASSIGN] of var OPTS: result;
有这些声明
enum CONDS = {A,B,C,D};
array[ASSIGN] of CONDS : const = [A,A,D,D];
array[OPTS,CONDS] of var int: result2;
output ["\(result) \(show2d(result2))"]
CONDS
也就是说,[ 1,2,1,3,4,4 ] [|2,0|1,2|0,0|0,1]
有 2 A OPTS[1]
,0 B CONDS
和 2 C CONDS
和 0 D CONDS
,而 CONDS
有1 A OPTS[2]
、0 B CONDS
、0 C CONDS
和 2 D CONDS
,依此类推。
我不知道我经历了多少以下组合,但没有一个产生预期的结果,尽管我认为应该是合乎逻辑的。
CONDS
解决方法
这是一个模型,它为 OPTS
中的每个值计算 CONDS
中出现的次数。棘手的部分是 count
构造,其中必须检查 result
中的值是否为 OPTS
值 o
。这是通过 count
约束完成的,其中 (result[i]==0)
是条件 result[i]
中的这个值是我们想要的 o
,然后我们检查它是什么 COND
属于 (const[i]
)。
include "globals.mzn";
set of int: OPTS = 1..4;
set of int: ASSIGN = 1..12;
% Note: hard coded with the example from the question.
array[ASSIGN] of var OPTS: result = [ 1,2,1,3,4,4 ];
enum CONDS = {A,B,C,D};
array[ASSIGN] of CONDS : const = [A,A,D,D];
% count the number of occurences in each chunk
array[OPTS,CONDS] of var 0..max(ASSIGN): result2;
constraint
% for each integer in OPTS
% count the number of occurrences of each c in CONDS
forall(o in OPTS) (
forall(c in CONDS) (
result2[o,c] = count([const[i]*(result[i] == o) | i in ASSIGN],c)
)
)
;
solve satisfy;
output [
"const: \(const)\n","result: \(result)\n","result2: ",show2d(result2),"\n",];
带有硬编码 result
的模型的输出是:
const: [A,D]
result: [1,4]
result2: [| 2,0 |
1,2 |
0,0 |
0,1 |]
编辑:
除了计数循环,我们还可以使用全局约束,这应该更有效一点global_cardinality
。它使用与 count
版本相同的想法,但包含在单个 forall
循环中:
constraint
forall(o in OPTS) (
global_cardinality([const[i]*(result[i] == o) | i in ASSIGN],OPTS,result2[o,..])
)
;