package inport; import javafx.util.Pair; import java.io.*; import java.util.*; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; public class ConversionUtil { static class PairComparator implements Comparator> { public int compare(Pair p1, Pair p2) { int res = p1.getKey().compareTo(p2.getKey()); if (res != 0) { return res; } else { return p1.getValue().compareTo(p2.getValue()); } } } 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); } s.append('}'); return s.toString(); } ); } static private void write2DArrayOfSetAs3DArray(FileWriter writer, String name, ArrayList>> operations) throws IOException { int maxSize = 0; ArrayList> sizes = new ArrayList<>(); int dim1 = operations.size(); int dim2 = 0; for (ArrayList> a1 : operations) { dim2 = a1.size(); ArrayList locSizes = new ArrayList<>(); for (ArrayList a2 : a1) { maxSize = Math.max(maxSize, a2.size()); locSizes.add(a2.size()); } sizes.add(locSizes); } writer.write(name + "_max_size = " + maxSize + ";\n"); write2DArrayOfInt(writer, name + "_sizes", sizes); writer.write(name + " = array3d(1.." + dim1 + ", 1.." + dim2 + ", 1.." + name + "_max_size, ["); boolean isFirst = true; for (ArrayList> a1 : operations) { for (ArrayList a2 : a1) { for (int i = 0; i < maxSize; i++) { if (isFirst) { isFirst = false; } else { writer.write(", "); } writer.write(Integer.toString(i < a2.size() ? a2.get(i) : 1)); } } } writer.write("]);\n"); } static private void writeArrayOfSetAs2DArray(FileWriter writer, String name, ArrayList> operations) throws IOException { int maxSize = 0; ArrayList sizes = new ArrayList<>(); for (Set s : operations) { maxSize = Math.max(maxSize, s.size()); sizes.add(s.size()); } writer.write(name + "_max_size = " + maxSize + ";\n"); writeArray(writer, name + "_sizes", sizes); writer.write(name + " = array2d(1.." + operations.size() + ", 1.." + name + "_max_size, ["); boolean isFirst = true; for (Set s : operations) { for (Integer val : s) { if (isFirst) { isFirst = false; } else { writer.write(", "); } writer.write(Integer.toString(val)); } for (int i = s.size(); i < maxSize; i++) { if (isFirst) { isFirst = false; } else { writer.write(", "); } writer.write("1"); } } writer.write("]);\n"); } static private void locWrite2DArray(FileWriter writer, String name, ArrayList> operations, Function toMZNFormat) throws IOException { writer.write(name + " = \n"); boolean isFirst0 = true; for (ArrayList a : operations) { if (isFirst0) { isFirst0 = false; writer.write(" [| "); } else { writer.write(" | "); } boolean isFirst1 = true; for (T val : a) { if (isFirst1) { isFirst1 = false; } else { writer.write(", "); } writer.write(toMZNFormat.apply(val)); } writer.write("\n"); } writer.write(" |];\n"); } static private void writeArray(FileWriter writer, String name, ArrayList data, Function f) throws IOException { writer.write(name + " = ["); for (int i = 0; i < data.size(); i++) { if (i != 0) { writer.write(", "); } writer.write(f.apply(data.get(i)).toString() + ""); } writer.write("];\n"); } static private void writeArray(FileWriter writer, String name, ArrayList data) throws IOException { writeArray(writer, name, data, (T val) -> val); } static private String setToString(Set s) { StringBuilder res = new StringBuilder(); res.append("{"); boolean isFirst = true; for (T t : s) { if (isFirst) { isFirst = false; } else { res.append(", "); } res.append(t.toString()); } res.append("}"); return res.toString(); } static private ArrayList integerArray(int size, int initVal) { ArrayList res = new ArrayList<>(); for (int i = 0; i < size; i++) { res.add(initVal); } return res; } static private MovingObject getExecutor(OperationTemplate t) { if (t instanceof LoadingTemplate) { return ((LoadingTemplate) t).getLoader(); } if (t instanceof MooringTemplate) { return ((MooringTemplate) t).getMoorer(); } if (t instanceof MovingTemplate) { return ((MovingTemplate) t).getMover(); } return null; } static private List getResources(OperationTemplate t) { List res = new ArrayList<>(); if (t instanceof LoadingTemplate) { res.addAll(((LoadingTemplate) t).getResources()); } if (t instanceof MooringTemplate) { res.addAll(((MooringTemplate) t).getResources()); } if (t instanceof MovingTemplate) { res.addAll(((MovingTemplate) t).getResources()); } return res; } static private boolean isCompatible(OperationTemplate t1, OperationTemplate t2) { MovingObject exec1 = getExecutor(t1); Berth place1 = t1.getStartLocation(); List resources1 = getResources(t1); MovingObject exec2 = getExecutor(t2); Berth place2 = t2.getStartLocation(); List resources2 = getResources(t2); // Пересекаемость ресурсов for (Object res2 : resources2) if (resources1.contains(res2)) return false; // Выполнитель = ресурс if (resources1.contains(exec2)) return false; // Ресурс = выполнитель if (resources2.contains(exec1)) return false; // Выполнитель = выполнитель if (exec1.equals(exec2)) { // Это не погрузка if (!(t1 instanceof LoadingTemplate) || (!(t2 instanceof LoadingTemplate))) return false; // Разные причалы if (!place1.equals(place2)) return false; Storage s1 = ((LoadingTemplate)t1).getStorage(); Storage s2 = ((LoadingTemplate)t2).getStorage(); // В одно хранилище if (s1.equals(s2)) return false; } else // На одном причале и это не перемещения if (place1.equals(place2) && (!(t1 instanceof MovingTemplate)) && (!(t2 instanceof MovingTemplate))) return false; return true; } private static 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 final BiFunction getLocNById; private final ArrayList movingObjects; private final Function mObjToN; private final ArrayList operationTemplates; private final ArrayList storages; private final ArrayList cargoes; private final int nObjWithStorage; private final Map storNById; private final Map cargoNById; 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()); } getLocNById = (Integer id, Boolean isMoored) -> locationNumberById.get(new Pair<>(id, isMoored)); movingObjects = new ArrayList<>(); Map mObjNumberById = new TreeMap<>(); for (MovingObject obj : task.getShips()) { mObjNumberById.put(obj.getId(), movingObjects.size()); movingObjects.add(obj); } for (MovingObject obj : task.getTows()) { mObjNumberById.put(obj.getId(), movingObjects.size()); movingObjects.add(obj); } for (MovingObject obj : task.getEquipments()) { mObjNumberById.put(obj.getId(), movingObjects.size()); movingObjects.add(obj); } mObjToN = (MovingObject obj) -> mObjNumberById.get(obj.getId()); operationTemplates = new ArrayList<>(task.getTemplates()); storages = new ArrayList<>(task.getStorages()); cargoes = new ArrayList<>(task.getCargoes()); storNById = new TreeMap<>(); for (int i = 0; i < storages.size(); i++) { storNById.put(storages.get(i).getId(), i); } cargoNById = new TreeMap<>(); for (int i = 0; i < task.getCargoes().size(); i++) { cargoNById.put(cargoes.get(i).getId(), i); } nObjWithStorage = movingObjects.size() + storages.size(); } /* Операции прибытия/отбытия в локацию. (В том числе и швартовка.) */ 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.apply(obj)); } movingObjN.add(mObjToN.apply(op.getMover())); for (Integer n : movingObjN) { 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); ArrayList movingObjN = new ArrayList<>(); for (MovingObject obj : op.getResources()) { movingObjN.add(mObjToN.apply(obj)); } movingObjN.add(mObjToN.apply(op.getMoorer())); for (Integer n : movingObjN) { 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); } } } 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.apply(state.getVessel()), getLocNById.apply(state.getLocation().getId(), false)); } writeArray(writer, "initial_m_obj_loc", initialStates, (Integer p) -> p + 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 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); writeArray(writer, "is_continuous_operation", isMovingObj); } /* Конечные положения объектов. */ private void finalLocations() throws IOException { ArrayList finalStates = integerArray(movingObjects.size(), -1); for (MovingObjectState state : task.getVesselEndState()) { finalStates.set(mObjToN.apply(state.getVessel()), getLocNById.apply(state.getLocation().getId(), false)); } writeArray(writer, "final_m_obj_loc", finalStates, (Integer p) -> p + 1); } /* Наличие всех ресурсов на месте, в том числе и самого корабля. */ private void presenceOfResourcesInLocation() throws IOException { // 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) { // Перемещение. MovingTemplate op = (MovingTemplate)operationTemplates.get(i); Set s = new TreeSet<>(); s.add(mObjToN.apply(op.getMover()) + 1); for (MovingObject obj : op.getResources()) { s.add(mObjToN.apply(obj) + 1); } 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(), op.getWithMooring()) + 1); } // TODO швартовка, погрузка. } writeArray(writer, "operations_start_loc", operationsStartLoc); //writeArray(writer, "operations_resources", operationsResources, ConversionUtil::setToString); writeArrayOfSetAs2DArray(writer, "operations_resources", operationsResources); 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 { 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"); } /* Граничные состояния хранилищ. */ private void boundaryStorageStates() throws IOException { // 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); } /* Потоки грузов. */ private void cargoFlows() throws IOException { 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 - 0.1)); } } 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"); } /* Грузовые операции со всеми хранилищами. */ private void cargoOperations() throws IOException { 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 = cargoNById.get(op.getCargo().getId()); 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); write2DArrayOfSetAs3DArray(writer, "involved_operations", involvedOperations); writeArray(writer, "loading_op_delta", loadingOpDelta); writeArray(writer, "loading_op_n", loadingOpN, (Integer i) -> i + 1); 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.apply(obj)).add(op + 1); BiConsumer addMovingOp = (MovingObject obj, Integer op) -> movingOpOfObj.get(mObjToN.apply(obj)).add(op + 1); for (int i = 0; i < movingObjects.size(); i++) { movingOpOfObj.add(new TreeSet<>()); objUsefulOperations.add(new TreeSet<>()); } 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.apply(obj)).add(op + 1); for (int i = 0; i < movingObjects.size(); i++) { objUsefulOperations.add(new TreeSet<>()); } 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 movingObjectLocationDefinition() throws IOException { ArrayList> movingOpOfObj = new ArrayList<>(); ArrayList operationsDestination = new ArrayList<>(); for (int i = 0; i < movingObjects.size(); i++) { movingOpOfObj.add(new TreeSet<>()); } BiConsumer addMovingOp = (MovingObject obj, Integer op) -> movingOpOfObj.get(mObjToN.apply(obj)).add(op + 1); for (int i = 0; i < operationTemplates.size(); i++) { OperationTemplate t = operationTemplates.get(i); if ((t instanceof MovingTemplate) || (t instanceof MooringTemplate)) { addMovingOp.accept(getExecutor(t), i); for (MovingObject obj : getResources(t)) { addMovingOp.accept(obj, i); } } if (t instanceof MovingTemplate) { MovingTemplate op = (MovingTemplate)t; operationsDestination.add(getLocNById.apply(op.getDestination().getId(), false)); } else if (t instanceof MooringTemplate) { MooringTemplate op = (MooringTemplate)t; operationsDestination.add(getLocNById.apply(op.getStartLocation().getId(), op.isDirect())); } else { // TODO аккуратно обработать погрузку. operationsDestination.add(getLocNById.apply(t.getStartLocation().getId(), false)); } } writeArrayOfSetAs2DArray(writer, "moving_op_of_obj", movingOpOfObj); writeArray(writer, "operations_destination", operationsDestination, (Integer val) -> val + 1); writer.write("\n"); } void portToMiniZinc_0() throws IOException { try { writer = new FileWriter(fileName, false); 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(); } finally { if (writer != null) { writer.close(); } } } void portToMiniZinc_1() throws IOException { try { writer = new FileWriter(fileName, false); 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(); 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(); } finally { if (writer != null) { writer.close(); } } } } static public void portToMiniZinc_0(TaskCase task, String fileName) throws IOException { Task taskData = new Task(task, fileName); taskData.portToMiniZinc_0(); } static public void portToMiniZinc_1(TaskCase task, String fileName) throws IOException { Task taskData = new Task(task, fileName); taskData.portToMiniZinc_1(); } private static class OperationsComparator implements Comparator { public int compare(Operation op1, Operation op2) { return Double.compare(op1.getStart(), op2.getStart()); } } static public void resolveMiniZincResults(TaskCase task, String fileName) throws IOException, ParserException { ArrayList operations = null; Integer result = null; try (FileInputStream fstream = new FileInputStream(fileName)) { BufferedReader br = new BufferedReader(new InputStreamReader(fstream)); String line; while (((line = br.readLine()) != null)) { line = line.trim(); if (line.equals("")) { continue; } String regexpr = "^\\[.*]\\z"; if (line.matches(regexpr)) { if (operations != null) { continue; } String []rawTokens = line.split("[\\s\\[\\],]"); ArrayList tokens = new ArrayList<>(); for (String str : rawTokens) { if (!str.isEmpty()) { tokens.add(str); } } final int n_intervals = (int)task.getPlanningInterval(); if (tokens.size() != (n_intervals + 2) * task.getTemplates().size()) { throw new ParserException("Invalid length of \"op_status\""); } operations = new ArrayList<>(); for (int i = 0; i < task.getTemplates().size(); i++) { int duration = 0; for (int j = 0; j < n_intervals + 2; j++) { if (tokens.get(i * (n_intervals + 2) + j).equals("true")) { duration++; } else if (duration != 0) { Operation op = new Operation(); op.setStart(j - duration - 1); op.setDuration(duration); op.setTemplate(task.getTemplates().get(i)); operations.add(op); duration = 0; } } } continue; } if (line.matches("\\d+")) { if (result != null) { continue; } result = Integer.parseInt(line); continue; } if (line.equals("=====UNSATISFIABLE=====")) { throw new ParserException("No solution."); } break; } if (operations == null) { throw new ParserException("No \"op_status\" in input"); } if (result == null) { throw new ParserException("No result in input"); } operations.sort(new OperationsComparator()); task.setSolution(operations); task.setSolution_result(result); } } }