From c5d0db0a3a3500f81edfe697bc05168fafdb58f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=81=D0=B5=D0=BB=D1=91=D0=B2=20=D0=92=D0=BB?= =?UTF-8?q?=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2?= Date: Mon, 19 Nov 2018 09:20:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A5=D1=80=D0=B0=D0=BD=D0=B8=D0=BB=D0=B8?= =?UTF-8?q?=D1=89=D0=B0=20-=20=D0=BE=D0=B1=D1=89=D0=B8=D0=B5=20=D1=83?= =?UTF-8?q?=D1=81=D0=BB=D0=BE=D0=B2=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/inport/ConversionUtil.java | 132 ++++++++++++++++++++++++++++----- test/conversion_0.mzn | 26 +++++++ 2 files changed, 139 insertions(+), 19 deletions(-) diff --git a/src/inport/ConversionUtil.java b/src/inport/ConversionUtil.java index ffbd1d2..48820b0 100644 --- a/src/inport/ConversionUtil.java +++ b/src/inport/ConversionUtil.java @@ -19,12 +19,41 @@ public class ConversionUtil { } } - static private void write2DArray(FileWriter writer, + static private void write2DArrayOfInt(FileWriter writer, + String name, + ArrayList> operations) throws IOException { + locWrite2DArray(writer, name, operations, Object::toString); + } + + static private void write2DArrayOfSet(FileWriter writer, + String name, + ArrayList>> operations) throws IOException { + locWrite2DArray(writer, name, operations, + (ArrayList a) -> { + StringBuilder s = new StringBuilder(); + s.append('{'); + boolean isFirst2 = true; + for (Integer val : a) { + if (isFirst2) { + isFirst2 = false; + } else { + s.append(", "); + } + s.append((val + 1)); + } + s.append('}'); + return s.toString(); + } + ); + } + + static private void locWrite2DArray(FileWriter writer, String name, - ArrayList>> operations) throws IOException { + ArrayList> operations, + Function toMZNFormat) throws IOException { writer.write(name + " = \n"); boolean isFirst0 = true; - for (ArrayList> m1 : operations) { + for (ArrayList a : operations) { if (isFirst0) { isFirst0 = false; writer.write(" [| "); @@ -32,23 +61,13 @@ public class ConversionUtil { writer.write(" | "); } boolean isFirst1 = true; - for (ArrayList m2 : m1) { + for (T val : a) { if (isFirst1) { isFirst1 = false; } else { writer.write(", "); } - writer.write("{"); - boolean isFirst2 = true; - for (Integer val : m2) { - if (isFirst2) { - isFirst2 = false; - } else { - writer.write(", "); - } - writer.write((val + 1) + ""); - } - writer.write("}"); + writer.write(toMZNFormat.apply(val)); } writer.write("\n"); } @@ -237,8 +256,8 @@ public class ConversionUtil { } } } - write2DArray(writer, "arrival_op", arrivalOp); - write2DArray(writer, "departure_op", departureOp); + write2DArrayOfSet(writer, "arrival_op", arrivalOp); + write2DArrayOfSet(writer, "departure_op", departureOp); } { // Начальные положения объектов. ArrayList initialStates = integerArray(movingObjects.size(), 0); @@ -258,8 +277,8 @@ public class ConversionUtil { operationTemplates.get(i).getTimeWindows().forEach( (Double start, Double duration) -> { bw_op.add(id + 1); - bw_start.add((int)Math.ceil(start)); - bw_fin.add((int)Math.floor(start + duration)); + bw_start.add((int)Math.floor(start)); + bw_fin.add((int)Math.ceil(start + duration)); } ); } @@ -331,6 +350,81 @@ public class ConversionUtil { writer.write("n_conflicting_op = " + conflictingPairs.size() + ";\n"); writeArray(writer, "confl_op_1", conflictingPairs, Pair::getKey); writeArray(writer, "confl_op_2", conflictingPairs, Pair::getValue); + writer.write("\n"); + } + // Грузоообработка. + + ArrayList storages = new ArrayList<>(task.getStorages()); + ArrayList cargoes = new ArrayList<>(task.getCargoes()); + + Map storNById = new TreeMap<>(); + for (int i = 0; i < storages.size(); i++) { + storNById.put(storages.get(i).getId(), i); + } + + Map cargoNById = new TreeMap<>(); + for (int i = 0; i < task.getCargoes().size(); i++) { + cargoNById.put(cargoes.get(i).getId(), i); + } + + int nObjWithStorage = movingObjects.size() + storages.size(); + + writer.write("n_obj_with_storage = " + nObjWithStorage + ";\n"); + writer.write("n_cargo_types = " + cargoes.size() + ";\n"); + + { // Ограничения на вместимость. + ArrayList maxStorageVol = new ArrayList<>(); + + for (MovingObject obj : movingObjects) { + if (obj instanceof TransportShip) { + maxStorageVol.add((int)Math.ceil(((TransportShip) obj).getCargoMax())); + } else { + maxStorageVol.add(0); + } + } + for (Storage storage : storages) { + maxStorageVol.add((int)Math.ceil(storage.getVolume())); + } + writeArray(writer, "max_storage_vol", maxStorageVol); + writer.write("\n"); + } + { // Граничные условия хранилищ. + // TODO выделить отдельно общий код. + ArrayList> initialStorageVol = new ArrayList<>(); + ArrayList> finalStorageVol = new ArrayList<>(); + + for (int i = 0; i < nObjWithStorage; i++) { + initialStorageVol.add(integerArray(cargoes.size(), 0)); + finalStorageVol .add(integerArray(cargoes.size(), -1)); + } + for (StorageState st : task.getStorageInitialState()) { + int cargoN = cargoNById.get(st.getCargo().getId()); + int val = (int)st.getCargoState(); + + if (st.getStorage() instanceof Storage) { + Storage storage = (Storage) st.getStorage(); + int stN = storNById.get(storage.getId()); + initialStorageVol.get(movingObjects.size() + stN).set(cargoN, val); + } else if (st.getStorage() instanceof TransportShip) { + TransportShip ship = (TransportShip) st.getStorage(); + initialStorageVol.get(mObjToN.apply(ship)).set(cargoN, val); + } + } + for (StorageState st : task.getStorageEndState()) { + int cargoN = cargoNById.get(st.getCargo().getId()); + int val = (int)st.getCargoState(); + + if (st.getStorage() instanceof Storage) { + Storage storage = (Storage) st.getStorage(); + int stN = storNById.get(storage.getId()); + finalStorageVol.get(movingObjects.size() + stN).set(cargoN, val); + } else if (st.getStorage() instanceof TransportShip) { + TransportShip ship = (TransportShip) st.getStorage(); + finalStorageVol.get(mObjToN.apply(ship)).set(cargoN, val); + } + } + write2DArrayOfInt(writer, "initial_storage_vol", initialStorageVol); + write2DArrayOfInt(writer, "final_storage_vol", finalStorageVol); } } } diff --git a/test/conversion_0.mzn b/test/conversion_0.mzn index 8611cec..4db8b24 100644 --- a/test/conversion_0.mzn +++ b/test/conversion_0.mzn @@ -118,6 +118,32 @@ constraint forall (i in 1..n_bad_weather_windows) ( forall (t in bw_start[i]..bw_fin[i]) (op_status[bw_op[i], t] == 0) ); +% Грузоообработка. +int : n_cargo_types; +int : n_obj_with_storage; +array [1..n_obj_with_storage, 0..(n_intervals + 1), 1..n_cargo_types] of var int : storage_used_volume; % Первые n_moving_obj соответствуют наполненности соответствующих движущихся объектов. + +% Ограничения на вместимость. +array [1..n_obj_with_storage] of int : max_storage_vol; +constraint forall (storage in 1..n_obj_with_storage, t in 0..(n_intervals + 1)) ( + (sum (cargo in 1..n_cargo_types) (storage_used_volume[storage, t, cargo]) <= max_storage_vol[storage]) + /\ + (forall (cargo in 1..n_cargo_types) (0 <= storage_used_volume[storage, t, cargo])) +); + + +% Ограничения на граничные значения. +array [1..n_obj_with_storage, 1..n_cargo_types] of int : initial_storage_vol; +array [1..n_obj_with_storage, 1..n_cargo_types] of int : final_storage_vol; +constraint forall (storage in 1..n_obj_with_storage, cargo in 1..n_cargo_types) ( + (storage_used_volume[storage, 0, cargo] == initial_storage_vol[storage, cargo]) + /\ + if final_storage_vol[storage, cargo] >= 0 then + (storage_used_volume[storage, (n_intervals + 1), cargo] == final_storage_vol[storage, cargo]) + else true + endif +); + % Критерий оптимизации array [0..(n_intervals + 1)] of var bool : is_not_terminated; constraint (is_not_terminated[0] == 0 /\ is_not_terminated[n_intervals + 1] == 0); -- GitLab