package inport.ConversionUtils; import inport.*; import java.io.FileWriter; import java.io.IOException; import java.io.UncheckedIOException; import java.util.*; import java.util.function.BiConsumer; import java.util.function.Consumer; import static inport.ConversionUtils.MZnFormat.*; import static inport.ConversionUtils.Utils.*; public class Task { private FileWriter writer = null; private final String fileName; private final TaskCase task; private final int n_intervals; private final ArrayList berths; private final Map, Integer> locationNumberById; private int getLocNById(int id, boolean isMoored) { return locationNumberById.get(new Pair<>(id, isMoored)); } private final ArrayList movingObjects; public Map getMObjNumberById() { return mObjNumberById; } private final Map mObjNumberById; private int mObjToN(MovingObject obj) { return mObjNumberById.get(obj.getId()); } private ArrayList operationTemplates; private final ArrayList storages; private final ArrayList cargoes; private final int nObjWithStorage; class StorageSectionId implements Comparable { boolean isRealStorage; // Not transport ship. Integer localN; Integer typeN; StorageSectionId(boolean isRealStorage, Integer localN, Integer typeN) { this.isRealStorage = isRealStorage; this.localN = localN; this.typeN = typeN; } @Override public int compareTo(StorageSectionId id) { if (isRealStorage != id.isRealStorage) { return (isRealStorage ? 1 : -1); } if (! localN.equals(id.localN)) { return localN.compareTo(id.localN); } if (! typeN.equals(id.typeN)) { return typeN.compareTo(id.typeN); } return 0; } } private final Map sectionNById; private int sectionIdToN(Storage storage, Cargo cargo) { return sectionNById.get(new StorageSectionId( true, storageNById.get(storage.getId()), cargoNById.get(cargo.getId()))); } private int sectionIdToN(TransportShip transportShip, Cargo cargo) { return sectionNById.get(new StorageSectionId( false, mObjToN(transportShip), cargoNById.get(cargo.getId()))); } private final Map storageNById; private final Map cargoNById; private final Map typeToN; private ArrayList> movingOpOfObj; private ArrayList operationsDestination; private ArrayList mainObjOfOperation; private ArrayList isMooringOp; private ArrayList> objectsOfType; public ArrayList getMovingObjects() { return movingObjects; } private final int nSectionsOfRealStorageAndBunkers; private final ArrayList initialStorageVol; private final ArrayList finalStorageVol; private final ArrayList maxStorageVol; public Task(TaskCase task, String fileName) { this.fileName = fileName; this.task = task; n_intervals = (int)task.getPlanningInterval(); berths = new ArrayList<>(task.getBerths()); locationNumberById = new TreeMap<>(new PairComparator<>()); for (Berth berth : berths) { locationNumberById.put(new Pair<>(berth.getId(), false), locationNumberById.size()); locationNumberById.put(new Pair<>(berth.getId(), true), locationNumberById.size()); } movingObjects = calcMovingObjects(task); mObjNumberById = new TreeMap<>(); for (int i = 0; i < movingObjects.size(); i++) { mObjNumberById.put(movingObjects.get(i).getId(), i); } operationTemplates = new ArrayList<>(task.getTemplates()); if (task.isTypified()) { operationTemplates = renumberOperations(task); } storages = new ArrayList<>(task.getStorages()); cargoes = new ArrayList<>(task.getCargoes()); cargoNById = new TreeMap<>(); for (int i = 0; i < task.getCargoes().size(); i++) { cargoNById.put(cargoes.get(i).getId(), i); } int nextStorageNo = 0; storageNById = new TreeMap<>(); sectionNById = new TreeMap<>(); for (int i = 0; i < storages.size(); i++) { // Сначала реальные хранилища. storageNById.put(storages.get(i).getId(), i); for (Pair p : storages.get(i).getStorageSections()) { sectionNById.put(new StorageSectionId(true, i, cargoNById.get(p.getKey().getId())), nextStorageNo++); } } for (MovingObject obj : movingObjects) { // Затем бункеровщики. if (obj instanceof Bunker) { for (Pair p : ((TransportShip) obj).getStorageSections()) { sectionNById.put(new StorageSectionId(false, mObjToN(obj), cargoNById.get(p.getKey().getId())), nextStorageNo++); } } } nSectionsOfRealStorageAndBunkers = sectionNById.size(); for (MovingObject obj : movingObjects) { // Дальше - все остальные. if ((obj instanceof TransportShip) && (!(obj instanceof Bunker))) { for (Pair p : ((TransportShip) obj).getStorageSections()) { sectionNById.put(new StorageSectionId(false, mObjToN(obj), cargoNById.get(p.getKey().getId())), nextStorageNo++); } } } nObjWithStorage = movingObjects.size() + storages.size(); { typeToN = new TreeMap<>(); int next = 0; for (Integer type : task.getVesselTypes().keySet()) { typeToN.put(type, next); next++; } for (Integer type : task.getBunkerTypes().keySet()) { typeToN.put(type, next); next++; } for (Integer type : task.getEquipmentsTypes().keySet()) { typeToN.put(type, next); next++; } } { objectsOfType = arrayOfIntegerSet(typeToN.size()); for (MovingObject obj : movingObjects) { if (obj.getType().isPresent()) { objectsOfType.get(typeToN.get(obj.getType().getAsInt())).add(mObjToN(obj) + 1); } } } { movingOpOfObj = arrayOfIntegerArrays(movingObjects.size()); operationsDestination = new ArrayList<>(); mainObjOfOperation = new ArrayList<>(); isMooringOp = new ArrayList<>(); initMovingObjectLocationDefinition(); } { initialStorageVol = integerArray(sectionNById.size(), 0); finalStorageVol = integerArray(sectionNById.size(), -1); BiConsumer, StorageState> f = (ArrayList a, StorageState st) -> { int val = (int)st.getCargoState(); int sectionN; if (st.getStorage() instanceof Storage) { sectionN = sectionIdToN((Storage) st.getStorage(), st.getCargo()); } else { assert st.getStorage() instanceof TransportShip; sectionN = sectionIdToN((TransportShip) st.getStorage(), st.getCargo()); } a.set(sectionN, val); }; for (StorageState st : task.getStorageInitialState()) { f.accept(initialStorageVol, st); } for (StorageState st : task.getStorageEndState()) { f.accept(finalStorageVol, st); } } { // maxStorageVol maxStorageVol = integerArray(sectionNById.size(), 0); for (MovingObject obj : movingObjects) { if (obj instanceof TransportShip) { for (Pair p : ((TransportShip) obj).getStorageSections()) { maxStorageVol.set(sectionIdToN((TransportShip) obj, p.getKey()), (int)Math.ceil(p.getValue())); } } } for (Storage storage : storages) { for (Pair p : storage.getStorageSections()) { maxStorageVol.set(sectionIdToN(storage, p.getKey()), (int)Math.ceil(p.getValue())); } } } } private ArrayList getNumbersOfResourcesTypes(OperationTemplate t) { ArrayList res = new ArrayList<>(); if (t instanceof LoadingTemplate) { res.addAll(((LoadingTemplate) t).getResourcesTypes()); } if (t instanceof MooringTemplate) { res.addAll(((MooringTemplate) t).getResourcesTypes()); } if (t instanceof MovingTemplate) { res.addAll(((MovingTemplate) t).getResourcesTypes()); } res.replaceAll(typeToN::get); return res; } /* Операции прибытия/отбытия в локацию. (В том числе и швартовка.) */ private void arrivalAndDepartureOperations() throws IOException { ArrayList>> arrivalOp = new ArrayList<>(); ArrayList>> departureOp = new ArrayList<>(); for (int i = 0; i < movingObjects.size(); i++) { arrivalOp.add(new ArrayList<>()); departureOp.add(new ArrayList<>()); for (int j = 0; j < locationNumberById.size(); j++) { arrivalOp.get(i).add(new ArrayList<>()); departureOp.get(i).add(new ArrayList<>()); } } for (int i = 0; i < operationTemplates.size(); i++) { if (operationTemplates.get(i) instanceof MovingTemplate) { MovingTemplate op = (MovingTemplate)operationTemplates.get(i); ArrayList movingObjN = new ArrayList<>(); for (MovingObject obj : op.getResources()) { movingObjN.add(mObjToN(obj)); } movingObjN.add(mObjToN(op.getMover())); for (Integer n : movingObjN) { arrivalOp .get(n).get(getLocNById(op.getDestination().getId(), false)).add(i + 1); departureOp.get(n).get(getLocNById(op.getStartLocation().getId(), false)).add(i + 1); } } else if (operationTemplates.get(i) instanceof MooringTemplate) { MooringTemplate op = (MooringTemplate)operationTemplates.get(i); ArrayList movingObjN = new ArrayList<>(); for (MovingObject obj : op.getResources()) { movingObjN.add(mObjToN(obj)); } movingObjN.add(mObjToN(op.getMoorer())); for (Integer n : movingObjN) { arrivalOp .get(n).get(getLocNById(op.getStartLocation().getId(), op.isDirect())).add(i + 1); departureOp.get(n).get(getLocNById(op.getStartLocation().getId(), !op.isDirect())).add(i + 1); } } } write2DArrayOfSetAs3DArray(writer, "arrival_op", arrivalOp); write2DArrayOfSetAs3DArray(writer, "departure_op", departureOp); writer.write("\n"); } /* Начальные положения объектов. */ private void initialLocations() throws IOException { ArrayList initialStates = integerArray(movingObjects.size(), 0); for (MovingObjectState state : task.getVesselInitialState()) { initialStates.set(mObjToN(state.getVessel()), getLocNById(state.getLocation().getId(), false)); } writeArray(writer, "initial_m_obj_loc", initialStates, (Integer p) -> p + 1, Optional.of(-1)); writer.write("\n"); } /* Окна погоды. */ private void weatherWindows() throws IOException { ArrayList bw_op = new ArrayList<>(); ArrayList bw_start = new ArrayList<>(); ArrayList bw_fin = new ArrayList<>(); for (int i = 0; i < operationTemplates.size(); i++) { final int id = i; operationTemplates.get(i).getTimeWindows().forEach( (Double start, Double duration) -> { bw_op.add(id + 1); bw_start.add((int)Math.floor(start)); bw_fin.add((int)Math.ceil(start + duration)); } ); } writer.write("n_bad_weather_windows = " + bw_op.size() + ";\n"); writeArray(writer, "bw_op", bw_op); writeArray(writer, "bw_start", bw_start); writeArray(writer, "bw_fin", bw_fin); writer.write("\n"); } /* Окна погоды. Новый формат. */ private void weatherWindowsNewFormat() throws IOException { ArrayList> badWeather = new ArrayList<>(); badWeather.add(new ArrayList<>()); for (int j = 0; j <= n_intervals; j++) { badWeather.get(0).add(false); } for (OperationTemplate operationTemplate : operationTemplates) { ArrayList curLine = new ArrayList<>(); for (int j = 0; j <= n_intervals; j++) { curLine.add(false); } operationTemplate.getTimeWindows().forEach( (Double start, Double duration) -> { for (int j = (int) Math.floor(start); j < (int) Math.ceil(start + duration); j++) { curLine.set(j + 1, true); } } ); badWeather.add(curLine); } locWrite2DArray(writer, "bad_weather", badWeather, Objects::toString, true); } /* Непрерывность перемещения и швартовки. */ private void operationsContinuity() throws IOException { ArrayList operationsDuration = integerArray(operationTemplates.size(), 0); ArrayList isMovingObj = new ArrayList<>(); for (int i = 0; i < operationTemplates.size(); i++) { if (operationTemplates.get(i) instanceof MovingTemplate) { MovingTemplate op = (MovingTemplate)operationTemplates.get(i); operationsDuration.set(i, (int)Math.ceil(op.getDuration())); isMovingObj.add(true); } else if (operationTemplates.get(i) instanceof MooringTemplate) { MooringTemplate op = (MooringTemplate) operationTemplates.get(i); operationsDuration.set(i, (int)Math.ceil(op.getDuration())); isMovingObj.add(true); } else { isMovingObj.add(false); } } writeArray(writer, "operations_duration", operationsDuration, Optional.of(1)); writeArray(writer, "is_continuous_operation", isMovingObj, Optional.of(false)); } /* Конечные положения объектов. */ private void finalLocations() throws IOException { ArrayList finalStates = integerArray(movingObjects.size(), -1); for (MovingObjectState state : task.getVesselEndState()) { finalStates.set(mObjToN(state.getVessel()), getLocNById(state.getLocation().getId(), false)); } writeArray(writer, "final_m_obj_loc", finalStates, (Integer p) -> p + 1, Optional.of(-1)); } /* Наличие всех ресурсов на месте, в том числе и самого корабля. */ private void presenceOfResourcesInLocation() throws IOException { ArrayList> operationsResources = new ArrayList<>(); ArrayList> operationsResourcesStartLoc = new ArrayList<>(); BiConsumer addResource = (MovingObject r, Integer stLoc) -> { operationsResources.get(operationsResources.size() - 1).add(mObjToN(r) + 1); operationsResourcesStartLoc.get(operationsResourcesStartLoc.size() - 1).add(stLoc + 1); }; for (OperationTemplate operationTemplate : operationTemplates) { operationsResources.add(new ArrayList<>()); operationsResourcesStartLoc.add(new ArrayList<>()); if (operationTemplate instanceof MovingTemplate) { // Перемещение. MovingTemplate op = (MovingTemplate) operationTemplate; addResource.accept(op.getMover(), getLocNById(op.getStartLocation().getId(), false)); for (MovingObject obj : op.getResources()) { addResource.accept(obj, getLocNById(op.getStartLocation().getId(), false)); } } else if (operationTemplate instanceof MooringTemplate) { // Швартовка. MooringTemplate op = (MooringTemplate) operationTemplate; addResource.accept(op.getMoorer(), getLocNById(op.getStartLocation().getId(), !op.isDirect())); for (MovingObject obj : op.getResources()) { addResource.accept(obj, getLocNById(op.getStartLocation().getId(), false)); } } else if (operationTemplate instanceof LoadingTemplate) { // Погрузка. LoadingTemplate op = (LoadingTemplate) operationTemplate; addResource.accept(op.getLoader(), getLocNById(op.getStartLocation().getId(), op.getWithMooring())); for (MovingObject obj : op.getResources()) { addResource.accept(obj, getLocNById(op.getStartLocation().getId(), false)); } } } writeArrayOfSetAs2DArray(writer, "operations_resources", operationsResources); writeArrayOfSetAs2DArray(writer, "operations_resources_start_loc", operationsResourcesStartLoc, false, false); writer.write("\n"); } /* Конфликтующие операции. */ private void conflictingOperations() throws IOException { ArrayList> conflictingPairs = new ArrayList<>(); for (int i = 0; i < operationTemplates.size(); i++) { for (int j = i + 1; j < operationTemplates.size(); j++) { if (!isCompatible(operationTemplates.get(i), operationTemplates.get(j))) { conflictingPairs.add(new Pair<>(i + 1, j + 1)); } } } 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"); } /* Ограничения на вместимость. */ private void maxStorageVolume() throws IOException { writeArray(writer, "max_storage_vol", maxStorageVol, Optional.of(0)); writer.write("\n"); } /* Граничные состояния хранилищ. */ private void boundaryStorageStates() throws IOException { writeArray(writer, "initial_storage_vol", initialStorageVol, Optional.of(0)); writeArray(writer, "final_storage_vol", finalStorageVol, Optional.of(-1)); } /* Потоки грузов. */ private void cargoFlows() throws IOException { ArrayList> cargoFlows = new ArrayList<>(); for (int i = 0; i <= sectionNById.size(); i++) { cargoFlows.add(integerArray(n_intervals + 2, 0)); } for (CargoFlow flow : task.getCargoFlows()) { int storageN = sectionIdToN(flow.getStorage(), flow.getCargo()); for (int i = 1; i < n_intervals + 2; i++) { cargoFlows.get(storageN + 1).set(i, (int)flow.getCurrentValue(i - 0.1)); } } write2DArrayOfInt(writer,"cargo_flows", cargoFlows, true); } /* Грузовые операции со всеми хранилищами. */ private void cargoOperations() throws IOException { ArrayList> involvedOperations = new ArrayList<>(); ArrayList loadingOpDelta = new ArrayList<>(); ArrayList loading_op_local_direction = new ArrayList<>(); ArrayList loadingOpN = new ArrayList<>(); ArrayList loading_op_delta_of_main_obj = new ArrayList<>(); ArrayList loading_op_abs_delta = new ArrayList<>(); ArrayList loading_op_direction = new ArrayList<>(); ArrayList operations_main_stor = new ArrayList<>(); ArrayList operations_secondary_stor = new ArrayList<>(); ArrayList operations_cargo_t = new ArrayList<>(); ArrayList bunker_of_cargo_op = new ArrayList<>(); for (int i = 0; i < sectionNById.size(); i++) { involvedOperations.add(new ArrayList<>()); } for (int i = 0; i < operationTemplates.size(); i++) { if (operationTemplates.get(i) instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate) operationTemplates.get(i); int cargoN = cargoNById.get(op.getCargo().getId()); int storageN; if (op.getBunker().isPresent()) { storageN = sectionIdToN(op.getBunker().get(), op.getCargo()); } else { storageN = sectionIdToN(op.getStorage(), op.getCargo()); } int shipStorageN = sectionIdToN(op.getLoader(), op.getCargo()); loadingOpDelta.add(-(int)op.getIntensity()); loading_op_local_direction.add(-(int)op.getIntensity() > 0 ? 1 : -1); loadingOpN.add(i); involvedOperations.get(storageN).add(loadingOpDelta.size()); loadingOpDelta.add((int)op.getIntensity()); loading_op_local_direction.add( (int)op.getIntensity() > 0 ? 1 : -1); loadingOpN.add(i); involvedOperations.get(shipStorageN).add(loadingOpDelta.size()); loading_op_delta_of_main_obj.add((int)op.getIntensity()); loading_op_abs_delta.add(Math.abs((int)op.getIntensity())); loading_op_direction.add((int)op.getIntensity() > 0 ? 1 : -1); operations_main_stor.add(shipStorageN + 1); operations_secondary_stor.add(storageN + 1); operations_cargo_t.add(cargoN + 1); bunker_of_cargo_op.add(op.getBunker().isPresent() ? mObjToN(op.getBunker().get()) + 1 : 0); } else { loading_op_delta_of_main_obj.add(0); loading_op_abs_delta.add(0); loading_op_direction.add(1); operations_main_stor.add(1); operations_secondary_stor.add(1); operations_cargo_t.add(1); bunker_of_cargo_op.add(0); } } ArrayList> sections_of_moving_obj = arrayOfIntegerArrays(movingObjects.size()); for (int i = 0; i < movingObjects.size(); i++) { if (movingObjects.get(i) instanceof TransportShip) { TransportShip ship = ((TransportShip) movingObjects.get(i)); for (Pair p : ship.getStorageSections()) { sections_of_moving_obj.get(i).add(sectionIdToN(ship, p.getKey()) + 1); } } } ArrayList is_sections_of_moving_obj_empty = new ArrayList<>(); for (ArrayList sections : sections_of_moving_obj) { is_sections_of_moving_obj_empty.add(sections.isEmpty()); } writer.write("n_loading_op = " + loadingOpDelta.size() + ";\n"); writeArray(writer, "involved_operations", involvedOperations, MZnFormat::arrayToStringAsSet); writeArray(writer, "loading_op_delta", loadingOpDelta); writeArray(writer, "loading_op_local_direction", loading_op_local_direction); writeArray(writer, "loading_op_n", loadingOpN, (Integer i) -> i + 1); writeArray(writer, "loading_op_delta_of_main_obj", loading_op_delta_of_main_obj, Optional.of(0)); writeArray(writer, "loading_op_abs_delta", loading_op_abs_delta, Optional.of(0)); writeArray(writer, "loading_op_direction", loading_op_direction, Optional.of(1)); writeArray(writer, "operations_main_stor", operations_main_stor, Optional.of(1)); writeArray(writer, "operations_secondary_stor", operations_secondary_stor, Optional.of(1)); writeArray(writer, "operations_cargo_t", operations_cargo_t, Optional.of(1)); writeArray(writer, "bunker_of_cargo_op", bunker_of_cargo_op, Optional.of(0)); writeArray(writer, "sections_of_moving_obj", sections_of_moving_obj, MZnFormat::arrayToStringAsSet); writeArray(writer, "is_sections_of_moving_obj_empty", is_sections_of_moving_obj_empty); writer.write("\n"); } /* Ограничение на необходимость полезной операции между движениями к одному пункту назначения. */ private void constraintOnUsefulOperationBetweenMovements_0() throws IOException { ArrayList> objUsefulOperations = new ArrayList<>(); ArrayList> movingOpOfObj = new ArrayList<>(); BiConsumer addUsOp = (MovingObject obj, Integer op) -> objUsefulOperations.get(mObjToN(obj)).add(op + 1); BiConsumer addMovingOp = (MovingObject obj, Integer op) -> movingOpOfObj.get(mObjToN(obj)).add(op + 1); for (int i = 0; i < movingObjects.size(); i++) { movingOpOfObj.add(new ArrayList<>()); objUsefulOperations.add(new ArrayList<>()); } for (int i = 0; i < operationTemplates.size(); i++) { OperationTemplate t = operationTemplates.get(i); if (t instanceof MovingTemplate) { MovingTemplate op = (MovingTemplate)t; addMovingOp.accept(op.getMover(), i); for (MovingObject obj : op.getResources()) { addUsOp.accept(obj, i); addMovingOp.accept(obj, i); } } else if (t instanceof MooringTemplate) { MooringTemplate op = (MooringTemplate)t; addMovingOp.accept(op.getMoorer(), i); for (MovingObject obj : op.getResources()) { addUsOp.accept(obj, i); addMovingOp.accept(obj, i); } if (!op.isDirect()) { // Отшвартовка. addUsOp.accept(op.getMoorer(), i); } } else if (t instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate)t; addUsOp.accept(op.getLoader(), i); } } writeArrayOfSetAs2DArray(writer, "obj_useful_operations", objUsefulOperations); writeArrayOfSetAs2DArray(writer, "moving_op_of_obj", movingOpOfObj); writer.write("\n"); } private void constraintOnUsefulOperationBetweenMovements_1() throws IOException { ArrayList> objUsefulOperations = new ArrayList<>(); BiConsumer addUsOp = (MovingObject obj, Integer op) -> objUsefulOperations.get(mObjToN(obj)).add(op + 1); for (int i = 0; i < movingObjects.size(); i++) { objUsefulOperations.add(new ArrayList<>()); } for (int i = 0; i < operationTemplates.size(); i++) { OperationTemplate t = operationTemplates.get(i); if (t instanceof MovingTemplate) { MovingTemplate op = (MovingTemplate)t; for (MovingObject obj : op.getResources()) { addUsOp.accept(obj, i); } } else if (t instanceof MooringTemplate) { MooringTemplate op = (MooringTemplate)t; for (MovingObject obj : op.getResources()) { addUsOp.accept(obj, i); } if (!op.isDirect()) { // Отшвартовка. addUsOp.accept(op.getMoorer(), i); } } else if (t instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate)t; addUsOp.accept(op.getLoader(), i); } } writeArrayOfSetAs2DArray(writer, "obj_useful_operations", objUsefulOperations); writer.write("\n"); } private void initMovingObjectLocationDefinition() { BiConsumer addMovingOp = (MovingObject obj, Integer op) -> movingOpOfObj.get(mObjToN(obj)).add(op + 1); for (int i = 0; i < operationTemplates.size(); i++) { OperationTemplate t = operationTemplates.get(i); mainObjOfOperation.add(mObjToN(getExecutor(t))); isMooringOp.add(t instanceof MooringTemplate); if ((t instanceof MovingTemplate) || (t instanceof MooringTemplate)) { addMovingOp.accept(getExecutor(t), i); if (!task.isTypified()) { for (MovingObject obj : getResources(t)) { addMovingOp.accept(obj, i); } } else { for (Integer typeId : new TreeSet<>(getNumbersOfResourcesTypes(t))) { for (Integer objId : objectsOfType.get(typeId)) { movingOpOfObj.get(objId - 1).add(i + 1); } } } } if (t instanceof MovingTemplate) { MovingTemplate op = (MovingTemplate)t; operationsDestination.add(getLocNById(op.getDestination().getId(), false)); } else if (t instanceof MooringTemplate) { MooringTemplate op = (MooringTemplate)t; operationsDestination.add(getLocNById(op.getStartLocation().getId(), op.isDirect())); } else { operationsDestination.add(getLocNById(t.getStartLocation().getId(), false)); } } } private void movingObjectLocationDefinition(boolean isV1) throws IOException { writeArray(writer, "is_mooring_op", isMooringOp, Optional.of(false)); writeArray(writer, "operations_destination", operationsDestination, (Integer val) -> val + 1, Optional.of(-1)); writer.write("\n"); } private void cargoOpUsingObj() throws IOException { ArrayList> relatedCargoOp = new ArrayList<>(); for (int i = 0; i < movingObjects.size(); i++) { relatedCargoOp.add(new TreeSet<>()); } for (int i = 0; i < operationTemplates.size(); i++) { if (operationTemplates.get(i) instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate) operationTemplates.get(i); relatedCargoOp.get(mObjToN(op.getLoader())).add(i + 1); if (op.getBunker().isPresent()) { relatedCargoOp.get(mObjToN(op.getBunker().get())).add(i + 1); } } } writeArray(writer, "related_cargo_op", relatedCargoOp, MZnFormat::setToString, Optional.of(new TreeSet<>())); } private void unmooringOpUsingObj() throws IOException { ArrayList> relatedUnmooringOp = new ArrayList<>(); for (int i = 0; i < movingObjects.size(); i++) { relatedUnmooringOp.add(new TreeSet<>()); } for (int i = 0; i < operationTemplates.size(); i++) { if (operationTemplates.get(i) instanceof MooringTemplate) { MooringTemplate op = (MooringTemplate) operationTemplates.get(i); if (! op.isDirect()) { relatedUnmooringOp.get(mObjToN(op.getMoorer())).add(i + 1); } } } writeArray(writer, "related_unmooring_op", relatedUnmooringOp, MZnFormat::setToString, Optional.of(new TreeSet<>())); } // related_unmooring_op private void addOpWithNominallyMooring() throws IOException { ArrayList>> opWithNominallyMooring = new ArrayList<>(); for (int loc = 0; loc <= locationNumberById.size(); loc++) { opWithNominallyMooring.add(new ArrayList<>()); for (int obj = 0; obj <= movingObjects.size(); obj++) { opWithNominallyMooring.get(loc).add(new TreeSet<>()); } } for (int i = 0; i < operationTemplates.size(); i++) { OperationTemplate t = operationTemplates.get(i); if ((t instanceof MooringTemplate) || ((t instanceof LoadingTemplate) && (! ((LoadingTemplate)t).getWithMooring()))) { opWithNominallyMooring.get(getLocNById(t.getStartLocation().getId(), true) + 1) .get(mObjToN(getExecutor(t)) + 1) .add(i + 1); } } write2DArrayOfSetAs3DArray(writer, "op_with_nominally_mooring", opWithNominallyMooring, true); } void portToMiniZinc_0() { if (task.isTypified()) { throw new ParserException("Attempt to convert typified task as untyped."); } try { writer.write("n_intervals = " + n_intervals + ";\n"); writer.write("n_operations = " + task.getTemplates().size() + ";\n"); writer.write("n_locations = " + locationNumberById.size() + ";\n"); writer.write("n_moving_obj = " + movingObjects.size() + ";\n"); writer.write("\n"); arrivalAndDepartureOperations(); initialLocations(); weatherWindows(); operationsContinuity(); finalLocations(); presenceOfResourcesInLocation(); conflictingOperations(); writer.write("n_obj_with_storage = " + nObjWithStorage + ";\n"); writer.write("n_cargo_types = " + cargoes.size() + ";\n"); maxStorageVolume(); boundaryStorageStates(); cargoFlows(); cargoOperations(); constraintOnUsefulOperationBetweenMovements_0(); } catch (IOException e) { throw new UncheckedIOException(e); } } void portToMiniZinc_1() { if (task.isTypified()) { throw new ParserException("Attempt to convert typified task as untyped."); } try { writer.write("n_intervals = " + n_intervals + ";\n"); writer.write("n_operations = " + task.getTemplates().size() + ";\n"); writer.write("n_locations = " + locationNumberById.size() + ";\n"); writer.write("n_moving_obj = " + movingObjects.size() + ";\n"); writer.write("\n"); movingObjectLocationDefinition(true); initialLocations(); weatherWindows(); operationsContinuity(); finalLocations(); presenceOfResourcesInLocation(); conflictingOperations(); writer.write("n_obj_with_storage = " + nObjWithStorage + ";\n"); writer.write("n_cargo_types = " + cargoes.size() + ";\n"); maxStorageVolume(); boundaryStorageStates(); cargoFlows(); cargoOperations(); // constraintOnUsefulOperationBetweenMovements_1(); } catch (IOException e) { throw new UncheckedIOException(e); } } public static ArrayList calcMovingObjects(TaskCase taskCase) { ArrayList movingObjects = new ArrayList<>(); movingObjects.addAll(taskCase.getShips()); movingObjects.addAll(taskCase.getBunkers()); movingObjects.addAll(taskCase.getTows()); movingObjects.addAll(taskCase.getEquipments()); return movingObjects; } /* Каждую операцию лишает типизации по главному действующему лицу. */ public static ArrayList renumberOperations(TaskCase task) { TreeMap> shipsByType = new TreeMap<>(); for (Integer type : task.getVesselTypes().keySet()) { shipsByType.put(type, new ArrayList<>()); } for (Integer type : task.getBunkerTypes().keySet()) { shipsByType.put(type, new ArrayList<>()); } for (Integer type : task.getEquipmentsTypes().keySet()) { shipsByType.put(type, new ArrayList<>()); } for (MovingObject obj : calcMovingObjects(task)) { if (obj.getType().isPresent()) { shipsByType.get(obj.getType().getAsInt()).add(obj); } } ArrayList result = new ArrayList<>(); for (OperationTemplate op : task.getTemplates()) { if (op instanceof LoadingTemplate) { LoadingTemplate t = (LoadingTemplate)op; if (t.getLoaderType().isPresent()) { for (MovingObject obj : shipsByType.get(t.getLoaderType().getAsInt())) { assert(obj instanceof TransportShip); if (t.getBunkerType().isPresent()) { for (MovingObject bunker : shipsByType.get(t.getBunkerType().getAsInt())) { assert(obj instanceof Bunker); result.add(new LoadingTemplate( (TransportShip)obj, t.getStartLocation(), t.getStorage(), t.getCargo(), Optional.of((Bunker)bunker), t.getResourcesTypes(), t.getWithMooring(), t.getIntensity(), t.getId() )); } } else { result.add(new LoadingTemplate( (TransportShip)obj, t.getStartLocation(), t.getStorage(), t.getCargo(), Optional.empty(), t.getResourcesTypes(), t.getWithMooring(), t.getIntensity(), t.getId() )); } } } } if (op instanceof MooringTemplate) { MooringTemplate t = (MooringTemplate)op; if (t.getMoorerType().isPresent()) { for (MovingObject obj : shipsByType.get(t.getMoorerType().getAsInt())) { assert(obj instanceof TransportShip); result.add(new MooringTemplate((TransportShip)obj, t.getStartLocation(), t.getResourcesTypes(), t.getDuration(), t.isDirect(), t.getId())); } } } if (op instanceof MovingTemplate) { MovingTemplate t = (MovingTemplate)op; if (t.getMoverType().isPresent()) { for (MovingObject obj : shipsByType.get(t.getMoverType().getAsInt())) { result.add(new MovingTemplate(obj, t.getStartLocation(), t.getDestination(), t.getResourcesTypes(), t.getDuration(), t.getId())); } } } } return result; } private void conflictingOperationsOnStorageAndOnTypeOnMainObject() throws IOException { ArrayList> conflictingOperationsG = new ArrayList<>(); for (int i = 0; i < operationTemplates.size(); i++) { conflictingOperationsG.add(new TreeSet<>()); for (int j = 0; j < operationTemplates.size(); j++) { if (i == j) { continue; } if ((operationTemplates.get(i) instanceof LoadingTemplate) && (operationTemplates.get(j) instanceof LoadingTemplate)) { LoadingTemplate op1 = (LoadingTemplate) operationTemplates.get(i); LoadingTemplate op2 = (LoadingTemplate) operationTemplates.get(j); if ((op1.getStorage() == op2.getStorage()) && (op1.getStartLocation() == op2.getStartLocation()) && (op1.getLoader() == op2.getLoader())) { conflictingOperationsG.get(i).add(j + 1); } } { // Взаимоисключение операций погрузки без швартовки на одном причале с разными субъектами. // + операций бункеровки без швартовки на одном причалое // TODO переделать if ((operationTemplates.get(i) instanceof LoadingTemplate) && (operationTemplates.get(j) instanceof LoadingTemplate)) { LoadingTemplate op1 = (LoadingTemplate) operationTemplates.get(i); LoadingTemplate op2 = (LoadingTemplate) operationTemplates.get(j); if ((! op1.getWithMooring()) && (! op2.getWithMooring()) && (op1.getStartLocation() == op2.getStartLocation()) && (op1.getBunker().isPresent()) && (op2.getBunker().isPresent())) { conflictingOperationsG.get(i).add(j + 1); } } } { // Взаимоисключение операций перемещения и грузообработки с общим деятелем. // TODO вынести в отдельный constraint OperationTemplate t1 = operationTemplates.get(i); OperationTemplate t2 = operationTemplates.get(j); if (t1 instanceof LoadingTemplate) { OperationTemplate t3 = t1; t1 = t2; t2 = t3; } if (((t1 instanceof MovingTemplate) || (t1 instanceof MooringTemplate)) && (t2 instanceof LoadingTemplate)) { if (getExecutor(t1) == getExecutor(t2)) { conflictingOperationsG.get(i).add(j + 1); } } } { // Взаимоисключение всех возможных пар операций перемещения с одним деятелем и пунктом отправления. if ((operationTemplates.get(i) instanceof MovingTemplate) && (operationTemplates.get(j) instanceof MovingTemplate)) { MovingTemplate op1 = (MovingTemplate) operationTemplates.get(i); MovingTemplate op2 = (MovingTemplate) operationTemplates.get(j); if ((op1.getMover() == op2.getMover()) && (op1.getStartLocation() == op2.getStartLocation())) { conflictingOperationsG.get(i).add(j + 1); } } } } } writeArray(writer, "conflicting_operations", conflictingOperationsG, MZnFormat::setToString, Optional.of(new TreeSet<>())); } public ArrayList> getIsFixedArray() { Map, Integer> opNoByOpIdAndExecutorNo = new TreeMap<>(new PairComparator<>()); for (int i = 0; i < operationTemplates.size(); i++) { OperationTemplate op = operationTemplates.get(i); opNoByOpIdAndExecutorNo.put(new Pair<>(op.getId(), getExecutor(op).getId()), i); } ArrayList> isFixed = new ArrayList<>(); for (int i = 0; i <= operationTemplates.size(); i++) { isFixed.add(new ArrayList<>()); for (int j = 0; j <= n_intervals; j++) { isFixed.get(i).add(false); } } for (Operation op : task.getFixedOperations()) { if (op.getFixation()) { int operation = opNoByOpIdAndExecutorNo.get(new Pair<>(op.getTemplate().getId(), op.getExecutor().getId())); for (int i = (int)Math.floor(op.getStart()); i < (int)Math.ceil(op.getDuration() + op.getStart()); i++) { isFixed.get(operation + 1).set(i + 1, true); } } } return isFixed; } private void fixedOperations() throws IOException { ArrayList fixedOp = new ArrayList<>(); ArrayList> fixedOpResources = new ArrayList<>(); ArrayList fixedOpStart = new ArrayList<>(); ArrayList fixedOpEnd = new ArrayList<>(); ArrayList fixedOpIntensity = new ArrayList<>(); ArrayList>> is_fixed_op_planned_in_future = new ArrayList<>(); class OperationData implements Comparable { private int opId, executorId; private OptionalInt bunkerId; OperationData(int opId, int executorId, OptionalInt bunkerId) { this.opId = opId; this.executorId = executorId; this.bunkerId = bunkerId; } @Override public int compareTo(OperationData o) { if (opId != o.opId) { return Integer.compare(opId, o.opId); } if (executorId != o.executorId) { return Integer.compare(executorId, o.executorId); } if (! bunkerId.isPresent()) { return (! o.bunkerId.isPresent()) ? 0 : -1; } if (! o.bunkerId.isPresent()) { return 1; } return Integer.compare(bunkerId.getAsInt(), o.bunkerId.getAsInt()); } }; Map opNoByOpData = new TreeMap<>(); for (int i = 0; i < operationTemplates.size(); i++) { OperationTemplate op = operationTemplates.get(i); OptionalInt bunkerId = OptionalInt.empty(); if ((op instanceof LoadingTemplate) && (((LoadingTemplate)op).getBunker().isPresent())) { bunkerId = OptionalInt.of(((LoadingTemplate)op).getBunker().get().getId()); } opNoByOpData.put(new OperationData(op.getId(), getExecutor(op).getId(), bunkerId), i); } ArrayList> is_obj_involved_in_fixed_op = new ArrayList<>(); for (int i = 0; i <= movingObjects.size(); i++) { is_obj_involved_in_fixed_op.add(new ArrayList<>()); for (int j = 0; j < n_intervals + 2; j++) { is_obj_involved_in_fixed_op.get(i).add(false); } } for (int i = 0; i < movingObjects.size(); i++) { is_fixed_op_planned_in_future.add(new ArrayList<>()); for (int j = 0; j < locationNumberById.size(); j++) { is_fixed_op_planned_in_future.get(i).add(new ArrayList<>()); for (int k = 0; k < n_intervals; k++) { is_fixed_op_planned_in_future.get(i).get(j).add(false); } } } for (Operation op : task.getFixedOperations()) { if (op.getFixation()) { OptionalInt bunkerId = op.getBunker().map(b -> OptionalInt.of(b.getId())).orElse(OptionalInt.empty()); int opNo = opNoByOpData.get(new OperationData(op.getTemplate().getId(), op.getExecutor().getId(), bunkerId)); int start = (int)Math.floor(op.getStart()); int end = (int)Math.ceil(op.getDuration() + op.getStart()); { ArrayList involvedMovingObj = new ArrayList<>(); involvedMovingObj.add(mObjToN(op.getExecutor())); if (op.getBunker().isPresent()) { involvedMovingObj.add(mObjToN(op.getBunker().get())); } for (MovingObject obj : op.getResources()) { involvedMovingObj.add(mObjToN(obj)); } for (int t = start; t < end; t++) { for (Integer obj : involvedMovingObj) { is_obj_involved_in_fixed_op.get(obj + 1).set(t + 1, true); } } } int loc = getLocNById(op.getTemplate().getStartLocation().getId(), false); int executor = mObjToN(op.getExecutor()); for (int i = 0; i < end; i++) { is_fixed_op_planned_in_future.get(executor).get(loc).set(i, true); } fixedOp.add(opNo + 1); TreeSet resources = new TreeSet<>(); for (MovingObject obj : op.getResources()) { resources.add(mObjToN(obj)); } fixedOpResources.add(resources); fixedOpStart.add(start + 1); fixedOpEnd.add(end); fixedOpIntensity.add((int)Math.ceil(op.getIntensity().orElse(0))); } } writer.write("n_fixed_op = " + fixedOp.size() + ";\n"); writeArray(writer, "fixed_op", fixedOp); writeArray(writer, "fixed_op_resources", fixedOpResources, MZnFormat::setToString); writeArray(writer, "fixed_op_start", fixedOpStart); writeArray(writer, "fixed_op_end", fixedOpEnd); writeArray(writer, "fixed_op_intensity", fixedOpIntensity); locWrite2DArray(writer, "is_fixed", getIsFixedArray(), Objects::toString, true); locWrite2DArray(writer, "is_obj_involved_in_fixed_op", is_obj_involved_in_fixed_op, Objects::toString, true); write3dArray(writer, "is_fixed_op_planned_in_future", is_fixed_op_planned_in_future, Objects::toString); } void defDataForCurMovingOp() throws IOException { ArrayList isMovingOp = new ArrayList<>(); for (OperationTemplate op : operationTemplates) { isMovingOp.add((op instanceof MovingTemplate) || (op instanceof MooringTemplate)); } writeArray(writer, "is_moving_operation", isMovingOp, Optional.of(false)); writer.write("\n"); writeArray(writer, "main_obj_of_operation", mainObjOfOperation, (Integer val) -> val + 1, Optional.of(-1)); ArrayList> locMovingOpOfObj = new ArrayList<>(); locMovingOpOfObj.add(new ArrayList<>()); for (int i = 0; i <= operationTemplates.size(); i++) { locMovingOpOfObj.get(0).add(false); } for (ArrayList operations : movingOpOfObj) { ArrayList lOperations = new ArrayList<>(); lOperations.add(false); for (int i = 0; i < operationTemplates.size(); i++) { lOperations.add(false); } for (Integer op : operations) { lOperations.set(op, true); } locMovingOpOfObj.add(lOperations); } locWrite2DArray(writer, "moving_op_of_obj", locMovingOpOfObj, Objects::toString, true); } private void typifiedResourcesDefinition() throws IOException { { // objects_of_type и operations_that_used_obj_as_resource writer.write("n_resources_types = " + typeToN.size() + ";\n"); writeArray(writer, "objects_of_type", objectsOfType, MZnFormat::setToString); ArrayList> res = arrayOfIntegerSet(movingObjects.size()); for (int i = 0; i < operationTemplates.size(); i++) { for (Integer typeNo : getNumbersOfResourcesTypes(operationTemplates.get(i))) { for (int obj : objectsOfType.get(typeNo)) { res.get(obj - 1).add(i + 1); } } } writeArray(writer, "operations_that_used_obj_as_resource", res, MZnFormat::setToString, Optional.of(new TreeSet<>())); writer.write("\n"); } { // counters, operations_resources_start_loc ArrayList counterType = new ArrayList<>(); ArrayList operationOfCounter = new ArrayList<>(); ArrayList requiredCounterValues = new ArrayList<>(); ArrayList> countersOfOperation = arrayOfIntegerSet(operationTemplates.size()); ArrayList operationsResourcesStartLoc = new ArrayList<>(); for (int i = 0; i < operationTemplates.size(); i++) { Map numberOfTypes = new TreeMap<>(); for (int type : getNumbersOfResourcesTypes(operationTemplates.get(i))) { if (!numberOfTypes.containsKey(type)) { numberOfTypes.put(type, 1); } else { numberOfTypes.put(type, numberOfTypes.get(type) + 1); } } for (Map.Entry p : numberOfTypes.entrySet()) { counterType.add(p.getKey()); operationOfCounter.add(i); requiredCounterValues.add(p.getValue()); countersOfOperation.get(i).add(counterType.size()); operationsResourcesStartLoc.add(locationNumberById.get(new Pair<>(operationTemplates.get(i).getStartLocation().getId(), false))); } } writer.write("n_resources_counters = " + counterType.size() + ";\n"); writeArray(writer, "counter_type", counterType, (Integer val) -> val + 1); writeArray(writer, "operation_of_counter", operationOfCounter, (Integer val) -> val + 1); writeArray(writer, "required_counter_values", requiredCounterValues); writeArray(writer, "operations_resources_start_loc", operationsResourcesStartLoc, (Integer val) -> val + 1); writeArray(writer, "counters_of_operation", countersOfOperation, MZnFormat::setToString, Optional.of(new TreeSet<>())); } } void requiredLocationsOnOpStart() throws IOException { ArrayList mainObjStartLoc = new ArrayList<>(); ArrayList bunkerStartLoc = new ArrayList<>(); for (OperationTemplate op : operationTemplates) { boolean isMoored = false; if ((op instanceof LoadingTemplate) && (((LoadingTemplate) op).getWithMooring())) { isMoored = true; } if ((op instanceof MooringTemplate) && (!((MooringTemplate)op).isDirect())) { isMoored = true; } mainObjStartLoc.add(getLocNById(op.getStartLocation().getId(), isMoored)); bunkerStartLoc.add(getLocNById(op.getStartLocation().getId(), false)); } writeArray(writer, "main_obj_start_loc", mainObjStartLoc, (Integer val) -> val + 1, Optional.of(-1)); writeArray(writer, "bunker_start_loc", bunkerStartLoc, (Integer val) -> val + 1, Optional.of(-1)); } void dataForOptimization3(boolean isInseparable) throws IOException { ArrayList> min_positive_cargo_val = arrayOfIntegerArrays(sectionNById.size()); ArrayList> max_negative_cargo_val = arrayOfIntegerArrays(sectionNById.size()); ArrayList> can_obj_leave_loc_only_alone = new ArrayList<>(); for (int i = 0; i < sectionNById.size(); i++) { for (int j = 0; j < locationNumberById.size(); j++) { min_positive_cargo_val.get(i).add(maxStorageVol.get(i) + 1); max_negative_cargo_val.get(i).add(-maxStorageVol.get(i) - 1); } } for (int i = 0; i < movingObjects.size(); i++) { can_obj_leave_loc_only_alone.add(new ArrayList<>()); for (int j = 0; j < locationNumberById.size(); j++) { can_obj_leave_loc_only_alone.get(i).add((j + 1) % 2 == 1); } } for (OperationTemplate t : operationTemplates) { if (t instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate) t; int val = (int) op.getIntensity(); int loc = getLocNById(op.getStartLocation().getId(), false) ; ArrayList> sections = new ArrayList<>(); sections.add(new Pair<>(sectionIdToN(op.getLoader(), op.getCargo()), val)); if (op.getBunker().isPresent()) { sections.add(new Pair<>(sectionIdToN(op.getBunker().get(), op.getCargo()), -val)); } else { sections.add(new Pair<>(sectionIdToN(op.getStorage(), op.getCargo()), -val)); } for (Pair p : sections) { Integer value = p.getValue(); if (! isInseparable) { if (value < 0) { value = -1; } if (value > 0) { value = 1; } } if (value > 0) { min_positive_cargo_val.get(p.getKey()).set(loc, Math.min(value, min_positive_cargo_val.get(p.getKey()).get(loc))); } else { max_negative_cargo_val.get(p.getKey()).set(loc, Math.max(value, max_negative_cargo_val.get(p.getKey()).get(loc))); } } } else if (t instanceof MovingTemplate) { int loc = getLocNById(t.getStartLocation().getId(), false); int obj = mObjToN(getExecutor(t)); if (! ((MovingTemplate) t).getResourcesTypes().isEmpty()) { can_obj_leave_loc_only_alone.get(obj).set(loc, false); } } } write2DArrayOfInt(writer, "min_positive_cargo_val", min_positive_cargo_val, false); write2DArrayOfInt(writer, "max_negative_cargo_val", max_negative_cargo_val, false); locWrite2DArray(writer, "can_obj_leave_loc_only_alone", can_obj_leave_loc_only_alone, Objects::toString); writer.write("\n"); } void portToMiniZinc_2_sep() { portToMiniZinc_2(false); } void portToMiniZinc_2_inSep() { portToMiniZinc_2(true); } /* С типизацией. */ private void portToMiniZinc_2(boolean isInseparable) { if (!task.isTypified()) { throw new ParserException("Attempt to convert untyped task as typified."); } try { writer.write("n_intervals = " + n_intervals + ";\n"); writer.write("n_operations = " + operationTemplates.size() + ";\n"); writer.write("n_locations = " + locationNumberById.size() + ";\n"); writer.write("n_moving_obj = " + movingObjects.size() + ";\n"); writer.write("\n"); movingObjectLocationDefinition(false); initialLocations(); finalLocations(); defDataForCurMovingOp(); weatherWindowsNewFormat(); conflictingOperationsOnStorageAndOnTypeOnMainObject(); requiredLocationsOnOpStart(); operationsContinuity(); typifiedResourcesDefinition(); cargoOpUsingObj(); unmooringOpUsingObj(); addOpWithNominallyMooring(); writer.write("n_all_storage_sections = " + sectionNById.size() + ";\n"); writer.write("n_cargo_types = " + cargoes.size() + ";\n"); maxStorageVolume(); boundaryStorageStates(); cargoFlows(); cargoOperations(); dataForOptimization3(isInseparable); fixedOperations(); } catch (IOException e) { throw new UncheckedIOException(e); } } private void dataForGreediness() throws IOException { ArrayList> connectedSections = arrayOfIntegerArrays(sectionNById.size()); ArrayList> connectedSectionsSet = arrayOfIntegerSet(sectionNById.size()); for (OperationTemplate t : operationTemplates) { if (t instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate) t; int section1 = sectionIdToN(op.getLoader(), op.getCargo()); int section2; if (op.getBunker().isPresent()) { section2 = sectionIdToN(op.getBunker().get(), op.getCargo()); } else { section2 = sectionIdToN(op.getStorage(), op.getCargo()); } connectedSectionsSet.get(section2).add(section1); } } ArrayList> positionsOfConnectedSections = arrayOfIntegerArrays(sectionNById.size()); for (int i = 0; i < sectionNById.size(); i++) { positionsOfConnectedSections.set(i, integerArray(sectionNById.size(), 0)); } for (int i = 0; i < sectionNById.size(); i++) { connectedSections.set(i, new ArrayList<>(connectedSectionsSet.get(i))); for (int j = 0; j < connectedSections.get(i).size(); j++) { positionsOfConnectedSections.get(connectedSections.get(i).get(j)).set(i, j); } } ArrayList operationsMainStorNoInSecondary = new ArrayList<>(); ArrayList operationsSecondaryStorNoInMain = new ArrayList<>(); for (OperationTemplate t : operationTemplates) { if (t instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate) t; int section1 = sectionIdToN(op.getLoader(), op.getCargo()); int section2; if (op.getBunker().isPresent()) { section2 = sectionIdToN(op.getBunker().get(), op.getCargo()); } else { section2 = sectionIdToN(op.getStorage(), op.getCargo()); } operationsMainStorNoInSecondary.add(positionsOfConnectedSections.get(section1).get(section2)); operationsSecondaryStorNoInMain.add(positionsOfConnectedSections.get(section2).get(section1)); } else { operationsMainStorNoInSecondary.add(-1); operationsSecondaryStorNoInMain.add(-1); } } int max_number_of_connected_sections = 0; ArrayList number_of_connected_sections = new ArrayList<>(); for (int i = 0; i < nSectionsOfRealStorageAndBunkers; i++) { number_of_connected_sections.add(connectedSections.get(i).size()); max_number_of_connected_sections = Math.max(max_number_of_connected_sections, connectedSections.get(i).size()); } writer.write("n_sections_of_real_storage_and_bunkers = " + nSectionsOfRealStorageAndBunkers + ";\n"); writer.write("max_number_of_connected_sections = " + max_number_of_connected_sections + ";\n"); writeArray(writer, "number_of_connected_sections", number_of_connected_sections, Optional.of(0)); writeArray(writer, "operations_main_stor_no_in_secondary", operationsMainStorNoInSecondary, (Integer i) -> i + 1, Optional.of(-1)); writeArray(writer, "operations_secondary_stor_no_in_main", operationsSecondaryStorNoInMain, (Integer i) -> i + 1, Optional.of(-1)); ArrayList>> connected_op_to_pair_of_sections = new ArrayList<>(); for (int i = 0; i <= nSectionsOfRealStorageAndBunkers; i++) { connected_op_to_pair_of_sections.add(new ArrayList<>()); for (int j = 0; j <= max_number_of_connected_sections; j++) { connected_op_to_pair_of_sections.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 section1 = sectionIdToN(op.getLoader(), op.getCargo()); int section2; if (op.getBunker().isPresent()) { section2 = sectionIdToN(op.getBunker().get(), op.getCargo()); } else { section2 = sectionIdToN(op.getStorage(), op.getCargo()); } connected_op_to_pair_of_sections.get(section2 + 1).get(operationsMainStorNoInSecondary.get(i) + 1).add(i + 1); } } locWrite2DArray(writer, "connected_op_to_pair_of_sections", connected_op_to_pair_of_sections, MZnFormat::arrayToStringAsSet, true); { ArrayList storage_greedy_upper_limit = new ArrayList<>(maxStorageVol); ArrayList storage_greedy_lower_limit = integerArray(sectionNById.size(), 0); for (int i = 0; i < sectionNById.size(); i++) { if (finalStorageVol.get(i) >= 0) { if (finalStorageVol.get(i) <= initialStorageVol.get(i)) { storage_greedy_lower_limit.set(i, finalStorageVol.get(i)); } else { storage_greedy_upper_limit.set(i, Math.min(storage_greedy_upper_limit.get(i), finalStorageVol.get(i))); } } } writeArray(writer, "storage_greedy_upper_limit", storage_greedy_upper_limit, Optional.of(0)); writeArray(writer, "storage_greedy_lower_limit", storage_greedy_lower_limit, Optional.of(0)); } { ArrayList> all_used_positions_in_real_cargo_value = arrayOfIntegerArrays(sectionNById.size()); for (int i = 0; i < sectionNById.size(); i++) { for (int j = 0; j < connectedSections.get(i).size(); j++) { all_used_positions_in_real_cargo_value.get(connectedSections.get(i).get(j)).add(i + 1); } } locWrite2DArray(writer, "positions_of_connected_sections", positionsOfConnectedSections, (Integer i) -> Integer.toString(i + 1), false); writeArray(writer, "all_used_positions_in_real_cargo_value", all_used_positions_in_real_cargo_value, MZnFormat::arrayToStringAsSet, Optional.of(new ArrayList<>())); } } private void addIsOpUsedStorAsSecondary() throws IOException { ArrayList> is_op_used_stor_as_secondary = new ArrayList<>(); for (int i = 0; i <= nSectionsOfRealStorageAndBunkers; i++) { is_op_used_stor_as_secondary.add(new ArrayList<>()); for (int j = 0; j <= operationTemplates.size(); j++) { is_op_used_stor_as_secondary.get(i).add(false); } } for (int j = 0; j < operationTemplates.size(); j++) { if (operationTemplates.get(j) instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate) operationTemplates.get(j); int section; if (op.getBunker().isPresent()) { section = sectionIdToN(op.getBunker().get(), op.getCargo()); } else { section = sectionIdToN(op.getStorage(), op.getCargo()); } is_op_used_stor_as_secondary.get(section + 1).set(j + 1, true); } } locWrite2DArray(writer, "is_op_used_stor_as_secondary", is_op_used_stor_as_secondary, Objects::toString, true); } private void addInvolvedOperations() throws IOException { ArrayList> involved_operations_as_main_stor = arrayOfIntegerSet(sectionNById.size()); ArrayList> involved_operations_as_sec_stor = arrayOfIntegerSet(sectionNById.size()); for (int i = 0; i < operationTemplates.size(); i++) { if (operationTemplates.get(i) instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate) operationTemplates.get(i); int section_1 = sectionIdToN(op.getLoader(), op.getCargo()); int section_2; if (op.getBunker().isPresent()) { section_2 = sectionIdToN(op.getBunker().get(), op.getCargo()); } else { section_2 = sectionIdToN(op.getStorage(), op.getCargo()); } involved_operations_as_main_stor.get(section_1).add(i + 1); involved_operations_as_sec_stor .get(section_2).add(i + 1); } } writeArray(writer, "involved_operations_as_main_stor", involved_operations_as_main_stor, MZnFormat::setToString); writeArray(writer, "involved_operations_as_sec_stor", involved_operations_as_sec_stor, MZnFormat::setToString); } void portToMiniZinc_2_greedy() { if (!task.isTypified()) { throw new ParserException("Attempt to convert untyped task as typified."); } try { portToMiniZinc_2(false); dataForGreediness(); } catch (IOException e) { throw new UncheckedIOException(e); } } void portToMiniZinc_2_greedy_v2() { if (!task.isTypified()) { throw new ParserException("Attempt to convert untyped task as typified."); } try { portToMiniZinc_2_greedy(); addIsOpUsedStorAsSecondary(); addInvolvedOperations(); } catch (IOException e) { throw new UncheckedIOException(e); } } static public void portToMiniZinc_0(TaskCase task, String fileName) { startConversion(task, fileName, Task::portToMiniZinc_0); } static public void portToMiniZinc_1(TaskCase task, String fileName) { startConversion(task, fileName, Task::portToMiniZinc_1); } static public void portToMiniZinc_2(TaskCase task, String fileName) { startConversion(task, fileName, Task::portToMiniZinc_2_inSep); } static public void portToMiniZinc_2_separable(TaskCase task, String fileName) { startConversion(task, fileName, Task::portToMiniZinc_2_sep); } static public void portToMiniZincGreedy(TaskCase task, String fileName) { startConversion(task, fileName, Task::portToMiniZinc_2_greedy); } static public void portToMiniZincGreedyV2(TaskCase task, String fileName) { startConversion(task, fileName, Task::portToMiniZinc_2_greedy_v2); } static private void startConversion(TaskCase task, String fileName, Consumer conversion) { try { Task taskData = new Task(task, fileName); try { taskData.writer = new FileWriter(fileName, false); conversion.accept(taskData); } finally { if (taskData.writer != null) { taskData.writer.close(); } } } catch (IOException e) { throw new UncheckedIOException(e); } } }