82 lines
2.2 KiB
MiniZinc
82 lines
2.2 KiB
MiniZinc
%------------------------------------------------------------------------------
|
|
% Parameters
|
|
|
|
int: num_strings;
|
|
int: max_length_strings;
|
|
int: max_char;
|
|
|
|
int: max_length_median;
|
|
|
|
array [1..num_strings, 1..max_length_strings] of int: strings;
|
|
array [1..num_strings] of int: str_length;
|
|
|
|
|
|
%------------------------------------------------------------------------------
|
|
% Variables
|
|
|
|
array [1..max_length_strings] of var 0..max_char: median;
|
|
array [1..num_strings] of var 0..2*max_length_strings: distances;
|
|
|
|
int: obj_ub = num_strings * 2 * max_length_strings;
|
|
var 0..obj_ub: objective;
|
|
|
|
%------------------------------------------------------------------------------
|
|
% Predicates
|
|
|
|
predicate lcs_global(array[int] of var int: S1, array[int] of var int: S2, var int: ED) =
|
|
|
|
let { int: l1 = min(index_set(S1)) - 1;
|
|
int: l2 = min(index_set(S2)) - 1;
|
|
int: u1 = max(index_set(S1));
|
|
int: u2 = max(index_set(S2));
|
|
array[l1..u1,l2..u2] of var 0..u1+u2: T; } in
|
|
T[l1,l2] = 0 /\
|
|
T[u1,u2] = ED /\
|
|
forall(i in l1+1..u1, j in l2+1..u2)
|
|
(T[i,j] >= 0 /\ T[i,j] <= i+j) /\
|
|
forall(j in l2+1..u2)(T[l1,j] = j-l2) /\
|
|
forall(i in l1+1..u1)(T[i,l2] = i-l1) /\
|
|
forall(i in l1+1..u1, j in l2+1..u2)
|
|
(T[i,j] = if S1[i] = S2[j] then
|
|
T[i-1,j-1]
|
|
else
|
|
if S1[i] = 0 then
|
|
T[i-1,j]
|
|
else
|
|
if S2[j] = 0 then
|
|
T[i,j-1]
|
|
else
|
|
min([T[i-1,j]+1,T[i,j-1]+1])
|
|
endif
|
|
endif
|
|
endif
|
|
);
|
|
|
|
%------------------------------------------------------------------------------
|
|
% Constraints
|
|
|
|
constraint forall(i in 1..num_strings)(
|
|
lcs_global([strings[i,j] | j in 1..max_length_strings], median, distances[i])
|
|
);
|
|
|
|
constraint forall(i in max_length_median+1..max_length_strings)(
|
|
median[i] = 0
|
|
);
|
|
|
|
constraint objective = sum(i in 1..num_strings)(distances[i]);
|
|
|
|
%------------------------------------------------------------------------------
|
|
% Solve item
|
|
|
|
solve
|
|
:: int_search(median, input_order, indomain_min, complete)
|
|
minimize objective;
|
|
|
|
%------------------------------------------------------------------------------
|
|
% Output
|
|
|
|
output [
|
|
"median = \(median);\n",
|
|
"objective = \(objective);\n"
|
|
];
|