这是一个用 MiniZinc 实现的简单 MILP 模型:
int: nPoints = 4;
set of int: POINT = 1..nPoints;
array[POINT, POINT] of int: d = [|
0, 2, 4, 5|
2, 0, 3, 1|
1, 4, 0, 4|
2, 4, 3, 0|];
int: k = 2;
int: M = max(d);
array[POINT] of var 0..1: x;
array[POINT, POINT] of var int: d_top;
array[POINT, POINT] of var 0..1: r;
array[POINT, POINT] of var int: d_min;
var int: z;
% max k points in C
constraint (sum(i in POINT)(x[i]) <= k);
% set d_top_ij to d_ij if x_i in C otherwise M
constraint forall(i, j in POINT)
(d_top[i,j] = d[i,j]*x[i] + M*(1-x[i]));
% exactly one closest point for each point
constraint forall(j in POINT)
(sum(i in POINT)(r[i,j]) = 1);
% d_min_ij = d_top_ij*r_ij (linearize product of continuous variable and binary variable)
constraint forall(i, j in POINT)
(d_min[i,j] <= d_top[i,j] /\ d_min[i,j] <= M*r[i,j] /\ d_min[i,j] >= 0 /\ d_min[i,j] >= d_top[i,j] - (1-r[i,j])*M);
% z is greater than all values in m
constraint forall(i, j in POINT)(z >= d_min[i,j]);
solve
minimize z;
output ["obj=\(z)\n"] ++
["x="] ++ [show(x)] ++
["\nd_top=\n"] ++ [show2d(d_top)] ++
["r=\n"] ++ [show2d(r)] ++
["d_min=\n"] ++ [show2d(d_min)];
跑步给出:
obj=1
x=[0, 1, 1, 0]
d_top=
[| 5, 5, 5, 5 |
2, 0, 3, 1 |
1, 4, 0, 4 |
5, 5, 5, 5 |]
r=
[| 0, 0, 0, 0 |
0, 1, 0, 1 |
1, 0, 1, 0 |
0, 0, 0, 0 |]
d_min=
[| 0, 0, 0, 0 |
0, 0, 0, 1 |
1, 0, 0, 0 |
0, 0, 0, 0 |]