Python Minizinc 有时会给出与 Minizinc IDE 不同的结果

Python Minizinc gives sometimes a different result than Minizinc IDE

根据输入数据,我有时会在使用 Minizinc Python 库或 Minizinc IDE.

时获得不同的结果(不同的 objective 和解决方案)

我的 Python 代码如下:

from minizinc import Instance, Model, Solver
import datetime

gecode = Solver.lookup("gecode")

model = Model()
model.add_file("./model.mzn")
model.add_file("./data.dzn", parse_data=True)

instance = Instance(gecode, model)

TIMELIMIT = datetime.timedelta(seconds=60)
result = instance.solve(timeout=TIMELIMIT)

print(result.status)

result.solution

据我所知,我的求解器参数在 IDE 中是相同的,我使用相同的模型和相同的数据。

我可以在 IDE 中看到以下命令:

Command: minizinc --json-stream --param-file-no-push /private/var/folders/hf/_75w1jh170x75y2_2vwt60lc0000gn/T/mzn_KneEzb.mpc model.mzn data.dzn
Configuration:
{
    "intermediate-solutions": true,
    "solver": "org.gecode.gecode@6.3.0",
    "time-limit": 60000
}

在一个特定的输入数据实例中,IDE 在 obj = 80 处找到一个最优值,Python 在 obj = 104 处找到一个最优值。 在输入数据的另一个实例中,IDE 和 Python 都找到相同的对象。

什么可以解释这种不同的结果?


更新:我正在添加 MiniZinc 模型和数据:

model.mzn

int: nNodes = nC+2*nV;

% ============== Vehicle Routing Problem ============= %
include "globals.mzn";

int: nC; int: nV; int: timeBudget;
set of int: VEHICLE = 1..nV;
set of int: CUSTOMER = 1..nC;
set of int: NODES = 1..nNodes;
set of int: START_DEPOT_NODES = nC+1..nC+nV;
set of int: END_DEPOT_NODES = nC+nV+1..nC+2*nV;
set of int: TIME = 0..timeBudget;
array[NODES] of int: serviceTime;
array[NODES, NODES] of int: distance;

% Time windows
% departure time must be between TimeWindows[client_i, 1] and TimeWindows[client_i, 2]
array[1..nC, 1..2] of int: TimeWindows;

% -------- variables ------------- %
array[NODES] of var VEHICLE: vehicle;
array[NODES] of var NODES: successor;
array[NODES] of var TIME: arrivalTime;

% -------- Start Nodes, End Nodes constraints ---------- %
constraint forall (n in START_DEPOT_NODES) % associate each start
( vehicle[n] = n-nC ); % node with a vehicle
constraint forall (n in END_DEPOT_NODES) % associate each end
( vehicle[n] = n-nC-nV ); % node with a vehicle

% -------- Successor Nodes constraints ---------- %
constraint forall (n in nC+nV+1..nC+2*nV-1) % successors of end nodes
( successor[n] = n-nV+1 ); % are start nodes
constraint successor[nC+2*nV] = nC+1;

constraint forall (n in START_DEPOT_NODES) % vehicles leave the
( arrivalTime[n] = 0 ); % depot at time zero
constraint circuit(successor); % hamiltonian circuit

constraint forall (n in CUSTOMER) % use the same vehicle
( vehicle[successor[n]] = vehicle[n] ); % along a subtour

constraint forall (n in 1..nC+nV)
( arrivalTime[n] + serviceTime[n] + distance[n,successor[n]]
<= arrivalTime[successor[n]] ); % time constraints

% -------- Time windows constraints -------------- %
constraint
    forall(i in 1..nC)(
        TimeWindows[i, 1] <= arrivalTime[i]
    );

constraint
    forall(i in 1..nC)(
        TimeWindows[i, 2] >= arrivalTime[i]
    );


% -------- objective ------------ %
% minimize distance (could be travel time in hours)
var int: obj = (sum (n in NODES) (distance[n,successor[n]]));

solve minimize obj; % expected overall travel time of each vehicle

% -------- output ------------ %
output ["obj = \(obj) \n"];

data.dzn

nV =5; nC = 40; timeBudget = 5000;

serviceTime = [ 6, 7, 3, 10, 2, 5, 2, 9, 7, 6, 5, 7, 7, 9, 9, 3, 7, 9, 1, 2, 5, 4, 7, 6, 3, 4, 6, 6, 2, 1, 10, 1, 5, 4, 10, 2, 10, 9, 2, 10, 5, 6, 4, 9, 9, 10, 6, 6, 6, 5];

distance = [| 0, 3, 7, 2, 10, 1, 6, 1, 10, 7, 3, 9, 5, 10, 5, 6, 2, 4, 3, 6, 5, 4, 4, 8, 7, 8, 8, 7, 8, 8, 9, 5, 2, 2, 9, 1, 2, 3, 1, 6, 6, 1, 1, 5, 3, 1, 5, 1, 4, 9
|5, 0, 7, 7, 6, 9, 1, 2, 2, 7, 10, 1, 9, 7, 5, 9, 4, 9, 8, 8, 4, 2, 10, 6, 1, 2, 7, 7, 4, 6, 5, 7, 9, 1, 10, 8, 6, 9, 1, 8, 6, 10, 7, 5, 7, 4, 10, 6, 8, 2
|7, 7, 0, 8, 10, 10, 6, 5, 9, 7, 5, 3, 2, 8, 10, 6, 10, 9, 8, 2, 1, 9, 10, 7, 4, 6, 1, 5, 8, 8, 9, 1, 2, 2, 6, 3, 2, 7, 1, 3, 6, 9, 7, 3, 6, 6, 6, 3, 3, 8
|7, 3, 6, 0, 10, 5, 8, 2, 5, 7, 1, 10, 8, 2, 5, 6, 9, 7, 1, 2, 1, 3, 3, 10, 10, 3, 9, 7, 2, 3, 4, 10, 10, 7, 6, 4, 9, 9, 8, 4, 1, 5, 6, 3, 10, 4, 5, 9, 3, 7
|5, 4, 9, 4, 0, 9, 8, 1, 1, 4, 9, 2, 10, 4, 4, 9, 7, 6, 8, 10, 5, 5, 5, 7, 8, 10, 10, 7, 3, 1, 6, 2, 4, 6, 5, 3, 10, 1, 2, 7, 3, 1, 2, 8, 1, 5, 10, 1, 5, 5
|2, 4, 4, 4, 7, 0, 8, 9, 3, 2, 8, 7, 7, 7, 5, 9, 9, 8, 3, 2, 3, 8, 3, 2, 8, 4, 1, 6, 4, 3, 2, 3, 6, 4, 2, 10, 6, 5, 5, 5, 10, 6, 4, 10, 10, 10, 8, 3, 2, 4
|5, 3, 6, 3, 7, 1, 0, 9, 10, 5, 4, 10, 4, 8, 9, 8, 6, 4, 1, 9, 2, 1, 4, 4, 6, 6, 9, 1, 9, 1, 7, 2, 1, 5, 4, 3, 6, 4, 4, 10, 4, 10, 7, 10, 4, 7, 8, 1, 3, 4
|9, 1, 5, 4, 6, 5, 10, 0, 4, 8, 10, 7, 5, 10, 7, 5, 4, 4, 10, 7, 8, 6, 2, 7, 9, 6, 2, 3, 9, 8, 3, 9, 4, 6, 5, 1, 4, 6, 7, 6, 9, 1, 9, 5, 5, 5, 5, 6, 7, 1
|5, 6, 4, 2, 9, 1, 5, 4, 0, 3, 3, 3, 6, 1, 4, 10, 1, 10, 10, 4, 8, 4, 7, 2, 9, 4, 4, 4, 4, 10, 8, 9, 9, 7, 9, 3, 9, 9, 3, 7, 1, 9, 2, 1, 3, 9, 8, 4, 1, 8
|10, 5, 8, 5, 7, 2, 1, 1, 5, 0, 7, 2, 5, 10, 5, 7, 1, 7, 7, 8, 3, 1, 3, 3, 9, 10, 1, 7, 1, 3, 4, 1, 8, 8, 4, 4, 5, 3, 3, 2, 3, 9, 4, 2, 3, 8, 5, 7, 9, 9
|9, 5, 8, 1, 2, 3, 1, 5, 10, 4, 0, 8, 10, 9, 3, 5, 1, 2, 10, 4, 9, 2, 1, 1, 10, 1, 4, 7, 7, 8, 10, 2, 6, 7, 8, 7, 4, 3, 5, 7, 7, 8, 10, 2, 3, 4, 7, 6, 6, 7
|8, 10, 3, 2, 9, 4, 2, 3, 7, 4, 8, 0, 9, 5, 1, 6, 7, 7, 9, 5, 4, 2, 3, 8, 7, 1, 2, 10, 9, 5, 4, 4, 4, 9, 3, 4, 9, 9, 6, 9, 6, 10, 9, 3, 8, 3, 9, 3, 6, 2
|1, 1, 6, 3, 6, 1, 9, 3, 9, 2, 6, 1, 0, 5, 10, 5, 1, 7, 7, 5, 3, 1, 7, 3, 7, 3, 5, 10, 1, 8, 3, 6, 2, 6, 2, 1, 2, 5, 8, 8, 10, 4, 6, 1, 10, 2, 3, 3, 1, 1
|3, 5, 3, 4, 7, 7, 10, 9, 5, 3, 5, 3, 8, 0, 5, 6, 5, 9, 8, 8, 4, 1, 6, 8, 5, 9, 7, 5, 7, 5, 5, 1, 3, 6, 7, 9, 9, 10, 2, 3, 2, 6, 8, 9, 10, 3, 2, 1, 4, 5
|6, 5, 6, 8, 6, 5, 2, 9, 5, 3, 10, 8, 4, 6, 0, 10, 2, 2, 3, 3, 7, 5, 5, 9, 4, 2, 10, 10, 4, 4, 2, 3, 4, 8, 10, 6, 1, 1, 1, 9, 8, 1, 9, 5, 6, 9, 7, 5, 7, 8
|6, 9, 8, 1, 8, 10, 7, 1, 4, 2, 8, 1, 4, 3, 2, 0, 3, 7, 4, 9, 5, 2, 10, 2, 8, 9, 3, 3, 2, 8, 9, 4, 1, 10, 2, 10, 9, 6, 10, 2, 9, 9, 9, 2, 4, 8, 7, 9, 9, 5
|8, 3, 4, 5, 5, 5, 4, 6, 6, 2, 6, 6, 5, 3, 4, 6, 0, 7, 1, 7, 1, 8, 5, 10, 8, 8, 9, 6, 10, 3, 10, 6, 4, 6, 8, 9, 9, 9, 1, 7, 3, 5, 4, 7, 3, 7, 2, 10, 10, 7
|10, 7, 1, 4, 7, 6, 2, 5, 1, 9, 7, 9, 6, 9, 6, 2, 3, 0, 5, 4, 3, 4, 2, 5, 5, 1, 1, 1, 1, 10, 4, 5, 6, 2, 2, 7, 10, 9, 4, 3, 4, 3, 9, 2, 6, 10, 9, 6, 4, 2
|2, 10, 10, 8, 5, 4, 4, 2, 1, 7, 7, 9, 2, 2, 7, 1, 7, 4, 0, 9, 5, 3, 10, 4, 10, 9, 7, 3, 4, 1, 8, 6, 1, 8, 2, 6, 1, 1, 6, 7, 3, 3, 10, 1, 10, 5, 3, 1, 5, 9
|8, 4, 2, 6, 5, 5, 6, 2, 1, 3, 10, 10, 10, 4, 3, 3, 1, 4, 6, 0, 6, 4, 3, 10, 4, 5, 3, 10, 1, 6, 6, 8, 4, 8, 4, 7, 4, 5, 9, 1, 3, 6, 1, 5, 10, 3, 10, 7, 7, 5
|3, 9, 8, 5, 2, 7, 9, 9, 10, 4, 9, 10, 10, 2, 8, 2, 9, 2, 2, 8, 0, 2, 5, 3, 9, 10, 9, 8, 2, 2, 5, 4, 7, 6, 5, 7, 6, 1, 4, 10, 6, 4, 4, 8, 4, 5, 4, 3, 10, 5
|4, 2, 5, 7, 7, 5, 9, 8, 2, 9, 5, 6, 5, 4, 4, 1, 1, 5, 8, 8, 4, 0, 2, 10, 8, 6, 8, 8, 3, 8, 2, 4, 6, 7, 1, 4, 1, 1, 6, 3, 3, 10, 9, 7, 1, 8, 10, 4, 1, 7
|1, 10, 1, 5, 4, 8, 8, 5, 5, 9, 7, 9, 1, 8, 4, 7, 8, 3, 5, 6, 2, 4, 0, 1, 10, 3, 10, 7, 8, 4, 10, 4, 10, 1, 10, 5, 1, 9, 8, 5, 6, 7, 6, 7, 9, 10, 9, 5, 8, 2
|7, 1, 8, 8, 9, 4, 9, 10, 1, 5, 6, 8, 8, 10, 9, 7, 10, 5, 3, 4, 10, 6, 5, 0, 6, 2, 6, 8, 2, 5, 5, 3, 4, 7, 6, 6, 2, 1, 1, 7, 8, 7, 9, 3, 6, 5, 2, 10, 2, 4
|3, 6, 6, 8, 9, 8, 4, 9, 2, 4, 3, 5, 8, 4, 1, 4, 9, 9, 3, 8, 2, 5, 10, 2, 0, 4, 5, 8, 5, 7, 5, 4, 4, 5, 1, 5, 2, 3, 2, 8, 4, 6, 9, 3, 8, 4, 1, 7, 5, 8
|9, 2, 7, 6, 1, 4, 9, 2, 5, 7, 2, 5, 2, 5, 5, 3, 6, 4, 8, 4, 8, 6, 10, 1, 6, 0, 6, 4, 3, 3, 4, 3, 7, 3, 3, 7, 8, 10, 7, 1, 2, 5, 4, 5, 8, 4, 7, 7, 2, 9
|2, 10, 9, 3, 1, 9, 7, 10, 8, 5, 10, 8, 4, 6, 9, 2, 3, 9, 4, 10, 9, 8, 7, 4, 6, 8, 0, 8, 7, 2, 2, 9, 7, 6, 9, 4, 3, 8, 4, 2, 8, 1, 1, 9, 4, 10, 2, 8, 8, 2
|1, 4, 4, 8, 8, 8, 3, 6, 7, 8, 1, 2, 10, 2, 2, 5, 4, 4, 8, 8, 2, 8, 5, 5, 2, 9, 9, 0, 4, 6, 10, 8, 3, 5, 2, 8, 4, 7, 2, 3, 4, 6, 3, 9, 6, 3, 8, 10, 3, 2
|9, 10, 1, 9, 8, 9, 6, 3, 3, 8, 9, 8, 7, 6, 6, 7, 10, 8, 5, 6, 6, 4, 2, 6, 9, 2, 10, 10, 0, 5, 9, 4, 3, 10, 9, 8, 3, 1, 5, 8, 1, 9, 7, 5, 4, 6, 10, 10, 7, 2
|9, 4, 6, 2, 2, 2, 2, 6, 6, 5, 5, 1, 6, 5, 6, 4, 7, 6, 4, 9, 2, 10, 9, 10, 2, 4, 1, 9, 1, 0, 5, 9, 3, 8, 10, 7, 4, 3, 10, 1, 8, 1, 7, 10, 5, 6, 1, 10, 10, 3
|4, 10, 3, 7, 3, 7, 2, 9, 10, 2, 2, 4, 3, 9, 5, 5, 9, 8, 3, 5, 2, 9, 7, 1, 4, 6, 2, 5, 4, 6, 0, 6, 1, 4, 5, 10, 8, 3, 2, 8, 7, 6, 10, 2, 5, 1, 7, 4, 10, 3
|6, 8, 3, 6, 2, 3, 5, 1, 10, 6, 8, 4, 6, 5, 7, 1, 6, 7, 1, 3, 7, 6, 10, 5, 5, 5, 10, 7, 2, 10, 9, 0, 1, 9, 2, 2, 8, 3, 6, 7, 3, 10, 5, 5, 7, 4, 6, 7, 7, 10
|3, 1, 5, 9, 6, 8, 5, 8, 4, 9, 3, 3, 6, 6, 7, 6, 1, 8, 7, 10, 2, 2, 8, 7, 4, 6, 3, 2, 6, 3, 4, 9, 0, 2, 7, 2, 7, 3, 3, 4, 3, 9, 3, 2, 4, 10, 1, 7, 2, 7
|10, 10, 4, 3, 5, 1, 7, 10, 6, 3, 5, 10, 3, 9, 7, 2, 5, 10, 4, 3, 10, 1, 7, 9, 1, 1, 5, 4, 3, 3, 7, 2, 5, 0, 10, 10, 1, 9, 2, 3, 6, 6, 7, 1, 9, 6, 5, 1, 1, 10
|5, 8, 7, 3, 2, 1, 5, 1, 1, 4, 9, 4, 6, 3, 9, 10, 1, 3, 4, 1, 9, 2, 10, 6, 10, 7, 6, 6, 10, 7, 5, 3, 2, 8, 0, 3, 3, 5, 8, 5, 2, 6, 2, 10, 5, 4, 3, 7, 1, 7
|10, 7, 7, 3, 7, 3, 2, 3, 2, 5, 7, 8, 1, 8, 10, 1, 1, 2, 7, 2, 6, 10, 9, 7, 10, 1, 7, 8, 9, 5, 3, 1, 10, 3, 5, 0, 6, 3, 5, 9, 4, 7, 3, 7, 7, 7, 1, 6, 9, 5
|8, 7, 8, 7, 10, 1, 3, 5, 4, 1, 8, 10, 8, 1, 7, 5, 1, 8, 5, 9, 3, 10, 9, 4, 7, 4, 2, 9, 1, 5, 8, 6, 8, 10, 1, 7, 0, 8, 8, 8, 1, 1, 3, 1, 1, 4, 9, 3, 8, 6
|10, 4, 1, 4, 3, 8, 1, 10, 3, 9, 4, 3, 5, 10, 5, 10, 10, 2, 6, 10, 10, 1, 1, 4, 7, 7, 2, 1, 4, 8, 2, 9, 4, 7, 1, 7, 6, 0, 7, 10, 2, 1, 8, 5, 2, 7, 6, 7, 1, 9
|10, 6, 5, 8, 7, 6, 9, 5, 6, 8, 9, 9, 9, 1, 3, 4, 7, 9, 5, 7, 6, 1, 1, 5, 1, 1, 5, 10, 3, 6, 9, 3, 4, 4, 9, 10, 9, 1, 0, 10, 7, 5, 4, 10, 8, 6, 2, 10, 4, 5
|5, 9, 1, 7, 9, 9, 5, 9, 5, 4, 10, 5, 8, 2, 7, 1, 5, 8, 4, 7, 1, 7, 7, 5, 2, 4, 9, 5, 7, 5, 8, 4, 1, 7, 7, 8, 4, 7, 4, 0, 4, 1, 2, 1, 5, 7, 9, 1, 10, 2
|9, 5, 7, 7, 6, 7, 10, 7, 1, 3, 2, 8, 4, 1, 8, 2, 6, 2, 10, 3, 5, 10, 6, 4, 10, 7, 7, 5, 10, 2, 10, 6, 1, 7, 10, 9, 2, 8, 3, 5, 0, 3, 10, 4, 4, 9, 9, 5, 10, 6
|8, 9, 3, 5, 10, 8, 3, 9, 1, 10, 1, 9, 7, 7, 3, 1, 10, 9, 1, 3, 5, 10, 2, 8, 10, 5, 4, 10, 9, 4, 7, 5, 2, 7, 10, 1, 8, 5, 1, 4, 4, 0, 2, 4, 6, 4, 8, 10, 9, 3
|5, 2, 1, 2, 9, 8, 8, 5, 4, 8, 1, 2, 3, 9, 2, 5, 9, 5, 6, 9, 1, 3, 2, 4, 1, 9, 4, 6, 1, 5, 9, 6, 1, 6, 8, 8, 8, 6, 7, 9, 8, 7, 0, 10, 8, 3, 3, 4, 2, 10
|1, 4, 8, 7, 8, 10, 4, 7, 7, 4, 2, 1, 3, 4, 1, 3, 5, 10, 3, 5, 10, 6, 5, 7, 10, 3, 6, 2, 5, 2, 8, 7, 2, 10, 4, 7, 7, 7, 5, 4, 9, 2, 5, 0, 3, 1, 3, 7, 3, 6
|6, 10, 4, 6, 7, 8, 1, 4, 9, 10, 5, 1, 3, 7, 5, 5, 1, 9, 2, 1, 8, 8, 3, 1, 6, 2, 9, 6, 9, 9, 8, 3, 8, 2, 5, 8, 3, 9, 3, 4, 10, 10, 7, 3, 0, 9, 6, 5, 3, 4
|4, 1, 1, 4, 8, 2, 3, 5, 4, 4, 5, 2, 6, 6, 2, 4, 2, 10, 9, 7, 3, 6, 9, 6, 10, 10, 8, 1, 10, 8, 5, 3, 8, 10, 3, 9, 8, 3, 8, 10, 4, 9, 2, 5, 3, 0, 5, 9, 5, 4
|2, 9, 7, 10, 9, 1, 2, 9, 3, 8, 1, 4, 4, 10, 9, 1, 4, 4, 2, 8, 1, 9, 9, 7, 8, 7, 5, 2, 1, 6, 10, 5, 1, 8, 10, 1, 4, 4, 7, 1, 7, 3, 3, 7, 4, 10, 0, 1, 2, 5
|5, 9, 4, 6, 5, 5, 7, 5, 9, 5, 5, 9, 8, 2, 5, 5, 2, 9, 7, 4, 5, 5, 8, 5, 2, 1, 2, 7, 7, 2, 9, 10, 4, 2, 9, 6, 9, 4, 8, 4, 10, 8, 2, 9, 10, 10, 9, 0, 3, 5
|3, 10, 8, 7, 5, 5, 9, 2, 5, 8, 3, 8, 1, 1, 7, 4, 8, 3, 1, 4, 7, 4, 3, 9, 1, 8, 5, 9, 9, 7, 2, 6, 6, 10, 1, 6, 7, 3, 8, 1, 6, 10, 10, 1, 1, 5, 8, 2, 0, 2
|6, 6, 8, 8, 8, 10, 8, 10, 8, 3, 4, 5, 8, 4, 10, 6, 8, 10, 2, 8, 10, 7, 10, 3, 9, 9, 5, 9, 5, 8, 8, 10, 1, 1, 8, 4, 2, 2, 9, 10, 4, 5, 4, 1, 4, 5, 3, 3, 2, 0
|]; 

 TimeWindows = [| 7, 504
|10, 582
|6, 552
|3, 531
|8, 538
|7, 520
|7, 514
|7, 585
|10, 599
|5, 585
|1, 549
|7, 531
|3, 526
|1, 553
|8, 562
|3, 575
|6, 534
|1, 574
|5, 554
|6, 577
|7, 532
|6, 605
|9, 531
|8, 509
|9, 529
|2, 532
|2, 559
|4, 584
|6, 535
|8, 574
|9, 580
|7, 571
|7, 511
|7, 596
|5, 607
|4, 536
|5, 593
|1, 575
|2, 565
|9, 525
|]; 

这个的关键好像是超时了。对于更高的超时,两种方法应该始终给出相同的结果。但这并不能真正解释为什么 MiniZincIDE 和 MiniZinc-Python 给出不同的结果,但这可能只是侥幸。

我用 Chuffed 求解器(+ 免费搜索标志)测试了模型,它用了 3.4 秒:

...
----------
obj = 73 
----------
==========

Google OR-tools 花费了大约相同的时间(12 个线程花费了 0.9 秒)。

正如在 Placing array of rectangles inside a given area using Minizinc ,可能需要尝试不同的 solvers/search 策略和模型变体以获得更快的时间。

对于这个模型,似乎只需更改求解器就足够了(如果这是可接受的操作)。