diff --git a/src/inport/ConversionUtil.java b/src/inport/ConversionUtil.java index 48820b047a57616127db7a9cac1c4b42b27e28f1..fb0d07480cff338e8585743215641c7f30448e47 100644 --- a/src/inport/ConversionUtil.java +++ b/src/inport/ConversionUtil.java @@ -39,7 +39,7 @@ public class ConversionUtil { } else { s.append(", "); } - s.append((val + 1)); + s.append(val); } s.append('}'); return s.toString(); @@ -238,8 +238,8 @@ public class ConversionUtil { movingObjN.add(mObjToN.apply(op.getMover())); for (Integer n : movingObjN) { - arrivalOp .get(n).get(getLocNById.apply(op.getDestination().getId(), false)).add(i); - departureOp.get(n).get(getLocNById.apply(op.getStartLocation().getId(), false)).add(i); + arrivalOp .get(n).get(getLocNById.apply(op.getDestination().getId(), false)).add(i + 1); + departureOp.get(n).get(getLocNById.apply(op.getStartLocation().getId(), false)).add(i + 1); } } else if (operationTemplates.get(i) instanceof MooringTemplate) { MooringTemplate op = (MooringTemplate)operationTemplates.get(i); @@ -251,8 +251,8 @@ public class ConversionUtil { movingObjN.add(mObjToN.apply(op.getMoorer())); for (Integer n : movingObjN) { - arrivalOp .get(n).get(getLocNById.apply(op.getStartLocation().getId(), !op.isDirect())).add(i); - departureOp.get(n).get(getLocNById.apply(op.getStartLocation().getId(), op.isDirect())).add(i); + arrivalOp .get(n).get(getLocNById.apply(op.getStartLocation().getId(), !op.isDirect())).add(i + 1); + departureOp.get(n).get(getLocNById.apply(op.getStartLocation().getId(), op.isDirect())).add(i + 1); } } } @@ -316,13 +316,13 @@ public class ConversionUtil { } writeArray(writer, "final_m_obj_loc", finalStates, (Integer p) -> p + 1); } - { // Наличие всех ресурсов на месте. - // TODO покрывается "Конфликтующими операциями". + { // Наличие всех ресурсов на месте, в том числе и самого корабля. + // TODO ресурсы покрываются "Конфликтующими операциями" (кроме наличия корабля на месте). ArrayList> operationsResources = new ArrayList<>(); ArrayList operationsStartLoc = integerArray(operationTemplates.size(), 0); for (int i = 0; i < operationTemplates.size(); i++) { operationsResources.add(new TreeSet<>()); - if (operationTemplates.get(i) instanceof MovingTemplate) { + if (operationTemplates.get(i) instanceof MovingTemplate) { // Перемещение. MovingTemplate op = (MovingTemplate)operationTemplates.get(i); Set s = new TreeSet<>(); @@ -332,6 +332,26 @@ public class ConversionUtil { } operationsResources.set(i, s); operationsStartLoc.set(i, getLocNById.apply(op.getStartLocation().getId(), false) + 1); + } else if (operationTemplates.get(i) instanceof MooringTemplate) { // Швартовка. + MooringTemplate op = (MooringTemplate)operationTemplates.get(i); + + Set s = new TreeSet<>(); + s.add(mObjToN.apply(op.getMoorer()) + 1); + for (MovingObject obj : op.getResources()) { + s.add(mObjToN.apply(obj) + 1); + } + operationsResources.set(i, s); + operationsStartLoc.set(i, getLocNById.apply(op.getStartLocation().getId(), !op.isDirect()) + 1); + } else if (operationTemplates.get(i) instanceof LoadingTemplate) { // Погрузка. + LoadingTemplate op = (LoadingTemplate) operationTemplates.get(i); + + Set s = new TreeSet<>(); + s.add(mObjToN.apply(op.getLoader()) + 1); + + // TODO ресурсы у операции погрузки. + + operationsResources.set(i, s); + operationsStartLoc.set(i, getLocNById.apply(op.getStartLocation().getId(), true) + 1); } // TODO швартовка, погрузка. } @@ -426,6 +446,73 @@ public class ConversionUtil { write2DArrayOfInt(writer, "initial_storage_vol", initialStorageVol); write2DArrayOfInt(writer, "final_storage_vol", finalStorageVol); } + { // Потоки грузов. + ArrayList>> cargoFlows = new ArrayList<>(); + for (int i = 0; i < nObjWithStorage; i++) { + cargoFlows.add(new ArrayList<>()); + for (int j = 0; j < n_intervals + 2; j++) { + cargoFlows.get(i).add(new ArrayList<>()); + for (int k = 0; k < cargoes.size(); k++) { + cargoFlows.get(i).get(j).add(0); + } + } + } + for (CargoFlow flow : task.getCargoFlows()) { + int storageN = storNById.get(flow.getStorage().getId()); + int cargoN = cargoNById.get(flow.getCargo().getId()); + for (int i = 1; i < n_intervals + 2; i++) { + cargoFlows.get(storageN + movingObjects.size()).get(i).set(cargoN, (int)flow.getCurrentValue(i)); + } + } + writer.write("cargo_flows = array3d(1..n_obj_with_storage, 0..(n_intervals + 1), 1..n_cargo_types, ["); + boolean isFirst = true; + for (int i = 0; i < nObjWithStorage; i++) { + for (int j = 0; j < n_intervals + 2; j++) { + for (int k = 0; k < cargoes.size(); k++) { + if (isFirst) { + isFirst = false; + } else { + writer.write(", "); + } + writer.write(cargoFlows.get(i).get(j).get(k).toString()); + } + } + } + writer.write("]);\n\n"); + } + { // Грузовые операции со всеми хранилищами. + ArrayList>> involvedOperations = new ArrayList<>(); + ArrayList loadingOpDelta = new ArrayList<>(); + ArrayList loadingOpN = new ArrayList<>(); + + for (int i = 0; i < nObjWithStorage; i++) { + involvedOperations.add(new ArrayList<>()); + for (int j = 0; j < cargoes.size(); j++) { + involvedOperations.get(i).add(new ArrayList<>()); + } + } + + for (int i = 0; i < operationTemplates.size(); i++) { + if (operationTemplates.get(i) instanceof LoadingTemplate) { + LoadingTemplate op = (LoadingTemplate) operationTemplates.get(i); + int storageN = storNById.get(op.getStorage().getId()); + int shipN = mObjToN.apply(op.getLoader()); + int cargoN = 0; // TODO в TaskCase пока не реализовано, пересмотреть. + + loadingOpDelta.add(-(int)op.getIntensity()); + loadingOpN.add(i); + involvedOperations.get(storageN + movingObjects.size()).get(cargoN).add(loadingOpDelta.size()); + + loadingOpDelta.add((int)op.getIntensity()); + loadingOpN.add(i); + involvedOperations.get(shipN).get(cargoN).add(loadingOpDelta.size()); + } + } + writer.write("n_loading_op = " + loadingOpDelta.size() + ";\n"); + write2DArrayOfSet(writer, "involved_operations", involvedOperations); + writeArray(writer, "loading_op_delta", loadingOpDelta); + writeArray(writer, "loading_op_n", loadingOpN); + } } } diff --git a/test/conversion_0.mzn b/test/conversion_0.mzn index 4db8b24da0ddf50e01a730f39cefe1b069b07774..ad5a95ec3d47edce4193d90915d7144028dc2481 100644 --- a/test/conversion_0.mzn +++ b/test/conversion_0.mzn @@ -138,10 +138,27 @@ 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 + (if final_storage_vol[storage, cargo] >= 0 then (storage_used_volume[storage, (n_intervals + 1), cargo] == final_storage_vol[storage, cargo]) else true - endif + endif) +); + +% Изменение грузов в хранилищах. +array [1..n_obj_with_storage, 0..(n_intervals + 1), 1..n_cargo_types] of int : cargo_flows; + +int : n_loading_op; +array [1..n_obj_with_storage, 1..n_cargo_types] of set of 1..n_loading_op : involved_operations; +array [1..n_loading_op] of int : loading_op_delta; +array [1..n_loading_op] of 1..n_operations : loading_op_n; % Номера среди общего списка операций. + +constraint forall (storage in 1..n_obj_with_storage, cargo in 1..n_cargo_types, t in 1..(n_intervals + 1)) ( + storage_used_volume[storage, t, cargo] = + storage_used_volume[storage, t - 1, cargo] + + cargo_flows[storage, t, cargo] + + sum (inv_op in involved_operations[storage, cargo]) ( + loading_op_delta[inv_op] * op_status[loading_op_n[inv_op], t] + ) ); % Критерий оптимизации @@ -164,5 +181,6 @@ output [show(sum(is_not_terminated)), "\n", "op_start = ", show(op_start), "\n\n", "arrival_op = ", show(arrival_op), "\n\n", "departure_op = ", show(departure_op), "\n\n", - "is_not_terminated = ", show(is_not_terminated), "\n\n" + "is_not_terminated = ", show(is_not_terminated), "\n\n", + "storage_used_volume = ", show(storage_used_volume), "\n\n" ];