这是我想在Minizinc中做的一件非常简单的事情。我有一个整数值数组,我想知道最常见值出现的次数。我不知道该怎么做。我希望有人能提供帮助。
答案 0 :(得分:3)
解决此问题的“经典”方法是将全局约束global_cardinality
与max
一起使用。
下面是使用这些约束对该问题进行建模的一种方法。并且还会显示最频繁的号码。
使用此方法的缺点是必须创建一个新数组gcc
(用于“全局基数计数”),其中包括每个数字0..upb
的出现次数(其中{{1 }}是数组upb
的上限,如果数组中的数字很大,则可能会很大。另外,必须对索引稍加注意,例如别忘了在a
中加入0。
这种方法的优点-除了可以在求解器中高效实现之外-可以在gcc
数组上添加一些额外的约束:在这里,我添加了此功能来显示最频繁(使用gcc
);这样的数字可能不止一个,然后会给出多个解决方案。
arg_max(a)
以下是该模型的输出:
include "globals.mzn";
int: n = 7;
array[1..n] of int: a = [15, 14, 39, 23, 14, 14, 8];
% array[1..n] of var 0..29: a; % using decision variables
% upper value of a
int: upb = ub_array(a);
% Number of occurrences in a
array[0..upb] of var 0..n: gcc;
% max number of occurrenes
var 0..upb: z = max(gcc);
% The value of the max number of occurrences
var 0..upb: max_val = arg_max(gcc)-1;
solve satisfy;
constraint
% count the number of occurrences in a
global_cardinality(a, array1d(0..upb,[i | i in 0..upb]), gcc)
;
output [
"a: \(a)\n",
"upb: \(upb)\n",
"gcc: \(gcc)\n",
"z: \(z)\n",
"max_val: \(max_val)\n",
"ub_array(a): \(lb_array(a))..\(ub_array(a))\n",
];
答案 1 :(得分:2)
我不知道这是否是最有效的方法,但是它起作用了,基本上,对于数组中的每个元素,您求和该值出现在数组中的次数并将其存储在辅助数组中,然后取查找在辅助数组中出现的最大值,因此在示例14中出现3次,因此repeats
对于对应于14的每个元素保留3。
最后,我添加了上面所有内容的一个线性版本,在这里您无需生成repeats
的数组,而是在max_repeats
的行中生成它。
% count the number of times that the most common value is repeated in an array
% As an example lets make a 7 element array
% size
int : n = 7;
% index set
set of int : SET = 1..n;
% the values
array [SET] of int : x = [15,14,39,23,14,14,8];
% auxiliar variable to carry the count
array [SET] of var int : repeats;
% we will count the number of times that value repeats
constraint forall(i in SET)(repeats[i] = sum(j in SET)(x[i] = x[j]) );
% the value of the most repeated element in the array
var int : value;
% if the number of repeats of that element is the maximum
% then value is equal to that element
constraint forall(i in SET)(repeats[i] = max(repeats) -> value = x[i]);
% this does the same but in one line
var int : max_repeats = max([sum(j in SET)(x[i] = x[j]) | i in SET]);
solve satisfy;
output ["Original values " ++ show(x) ++ "\n"] ++
["Number of repeats of each element " ++ show(repeats) ++ "\n"] ++
["Maximum number of repeats : " ++ show(max(repeats))];
Original values [15, 14, 39, 23, 14, 14, 8]
Number of repeats of each element [1, 3, 1, 1, 3, 3, 1]
Maximum number of repeats : 3