From c8542a5d9812e9bb0894037b66362056b1855768 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: Thu, 28 Mar 2019 20:52:58 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=B8=D0=BF=D0=B8=D0=B7=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constraints/conversion_2.mzn | 170 ++++++---- src/inport/ConversionUtil.java | 523 ++++++++++++++++++++++++++----- src/inport/LoadingEquipment.java | 4 +- src/inport/LoadingTemplate.java | 7 +- src/inport/Main.java | 172 +++++++++- src/inport/MooringTemplate.java | 4 +- src/inport/MovingTemplate.java | 6 +- src/inport/Operation.java | 41 ++- src/inport/TaskCase.java | 2 +- src/inport/Testing.java | 17 +- src/inport/Tow.java | 4 +- src/inport/TransportShip.java | 4 +- 12 files changed, 796 insertions(+), 158 deletions(-) diff --git a/src/constraints/conversion_2.mzn b/src/constraints/conversion_2.mzn index 71ad496..8d32349 100644 --- a/src/constraints/conversion_2.mzn +++ b/src/constraints/conversion_2.mzn @@ -11,7 +11,7 @@ array [1..n_operations, 0..(n_intervals + 1)] of var bool : op_fin; int : moving_op_of_obj_max_size; array [1..n_moving_obj] of 0..moving_op_of_obj_max_size : moving_op_of_obj_sizes; -array [1..n_moving_obj, 1..moving_op_of_obj_max_size] of 1..n_operations : moving_op_of_obj; % Операции перемещения затрагивающие данный объект. +array [1..n_moving_obj, 0..moving_op_of_obj_max_size] of 1..n_operations : moving_op_of_obj; % Операции перемещения затрагивающие данный объект. % Определение current_moving_operation. % Текущая операция операция перемещения, в которой задействован данный объект. @@ -21,16 +21,34 @@ array [1..n_moving_obj, 1..moving_op_of_obj_max_size] of 1..n_operations : movin constraint forall (obj in 1..n_moving_obj, t in 0..(n_intervals + 1)) ( current_moving_operation[obj, t] <= moving_op_of_obj_sizes[obj] ); + % Если операция, затрагивающая данный объект в качестве главного, выполняется - то именно она текущая операция перемещения для этого объекта. + constraint forall (op in 1..n_operations, t in 0..(n_intervals + 1), obj = main_obj_of_operation[op] + where is_moving_operation[op]) ( + op_status[op, t] -> ((current_moving_operation[obj, t] != 0) /\ + (moving_op_of_obj[obj, current_moving_operation[obj, t]] = op)) + ); + % Если операция, затрагивающая данный объект в качестве ресурса + +% TODO упростить в conversion_1 + % Связь current_moving_operation c op_status. + constraint forall (obj in 1..n_moving_obj, + t in 0..(n_intervals + 1)) ( + (current_moving_operation[obj, t] != 0) + -> (op_status[moving_op_of_obj[obj, current_moving_operation[obj, t]], t]) + ); - % Если операция, затрагивающая данный объект, выполняется - то именно она текущая операция перемещения для этого объекта. - constraint forall (obj in 1..n_moving_obj, op_no in 1..moving_op_of_obj_sizes[obj], t in 0..(n_intervals + 1)) ( - (op_status[moving_op_of_obj[obj, op_no], t]) -> (current_moving_operation[obj, t] = op_no) +% Ограничение на количество пришвартованных кораблей. + % Счётчик объектов в локации (только в чётных - в состоянии пришвартованности). + array [1..n_locations, 0..(n_intervals + 1)] of var int : obj_in_loc_counter; + + % Определение obj_in_loc_counter. + constraint forall (loc in 1..n_locations, t in 0..(n_intervals + 1)) ( + obj_in_loc_counter[loc, t] = sum (obj in 1..n_moving_obj) (m_obj_loc[obj, t] = loc) ); - % Если объект движется, то выполняется какая-то операция перемещения, касаящаяся этого объекта. - constraint forall (obj in 1..n_moving_obj, t in 0..(n_intervals + 1)) ( - (current_moving_operation[obj, t] > 0) -> - (exists (op_no in 1..moving_op_of_obj_sizes[obj]) (op_status[moving_op_of_obj[obj, op_no], t])) + % Само ограничение. + constraint forall (loc in 1..n_locations, t in 0..(n_intervals + 1) where (loc mod 2) = 0) ( + obj_in_loc_counter[loc, t] <= 1 ); % Определение is_m_obj_in_movement_before_start. @@ -43,40 +61,63 @@ array [1..n_moving_obj, 1..moving_op_of_obj_max_size] of 1..n_operations : movin constraint forall (obj in 1..n_moving_obj) (not is_m_obj_in_movement_before_start[obj, 1]); % Если в предыдущем интервале объект не движется - то в начале этого он не движется, иначе он движется если предыдущая операция не закончилась. - constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( - if (current_moving_operation[obj, t - 1] = 0) then - is_m_obj_in_movement_before_start[obj, t] = false - else - is_m_obj_in_movement_before_start[obj, t] = (current_moving_operation[obj, t - 1] == current_moving_operation[obj, t]) - endif - ); + constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( + (current_moving_operation[obj, t - 1] = 0) + -> is_m_obj_in_movement_before_start[obj, t] = false + ); + constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( + (current_moving_operation[obj, t - 1] != 0) + -> is_m_obj_in_movement_before_start[obj, t] = (current_moving_operation[obj, t - 1] == current_moving_operation[obj, t]) + ); array [1..n_operations] of 1..n_locations : operations_destination; % Локация в которой окажется объект после завершения операции. % Определение m_obj_loc. % Местоположение объекта или пункт назначения (если объект движется) перед началом определённого интервала. array [1..n_moving_obj, 0..(n_intervals + 1)] of var 1..n_locations : m_obj_loc; + + % Главный объект (субъект) операции. + array [1..n_operations] of 1..n_moving_obj : main_obj_of_operation; + + % Является ли операция швартовкой/отшвартовкой. + array [1..n_operations] of bool : is_mooring_op; + % За фиктивный нулевой интервал объект не успевает ничего сделать с начальным положением. constraint forall (obj in 1..n_moving_obj) ( m_obj_loc[obj, 1] = m_obj_loc[obj, 0] ); - +% TODO исправить в conversion_1.mzn % Направление движения/местоположение объекта может измениться только если перед этим началась операция перемещения. - constraint forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) ( - if ((current_moving_operation[obj, t - 1] != current_moving_operation[obj, t - 2]) /\ - (current_moving_operation[obj, t - 1] != 0)) then - m_obj_loc[obj, t] = operations_destination[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]] - else - m_obj_loc[obj, t] = m_obj_loc[obj, t - 1] - endif - ); + constraint forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) ( + ((current_moving_operation[obj, t - 1] != current_moving_operation[obj, t - 2]) /\ + (current_moving_operation[obj, t - 1] != 0) /\ + ((obj = main_obj_of_operation[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]]) + \/ + (not is_mooring_op[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]]) + ) + ) -> (m_obj_loc[obj, t] = operations_destination[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]]) + ); + constraint forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) ( + ((current_moving_operation[obj, t - 1] != current_moving_operation[obj, t - 2]) /\ + (current_moving_operation[obj, t - 1] != 0) /\ + ((obj != main_obj_of_operation[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]]) + /\ + (is_mooring_op[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]]) + ) + ) -> (m_obj_loc[obj, t] = m_obj_loc[obj, t - 1]) + ); + constraint forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) ( + ((current_moving_operation[obj, t - 1] = current_moving_operation[obj, t - 2]) \/ + (current_moving_operation[obj, t - 1] = 0) + ) -> (m_obj_loc[obj, t] = m_obj_loc[obj, t - 1]) + ); % Начальное состояние. - array [1..n_moving_obj] of var 0..n_locations : initial_m_obj_loc; + array [1..n_moving_obj] of 0..n_locations : initial_m_obj_loc; constraint forall (i in 1..n_moving_obj) (m_obj_loc[i, 0] = initial_m_obj_loc[i]); % Конечное состояние. - array [1..n_moving_obj] of var 0..n_locations : final_m_obj_loc; + array [1..n_moving_obj] of 0..n_locations : final_m_obj_loc; constraint forall (i in 1..n_moving_obj) ( (final_m_obj_loc[i] != 0) -> (m_obj_loc[i, n_intervals + 1] = final_m_obj_loc[i]) @@ -94,9 +135,6 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац % Операции, которые могут задействовать данный объект как ресурс. array [1..n_moving_obj] of set of 1..n_operations : operations_that_used_obj_as_resource; - % Главный объект (субъект) операции. - array [1..n_operations] of 1..n_moving_obj : main_obj_of_operation; - % Является ли данная операция операцией перемещения. array [1..n_operations] of bool : is_moving_operation; @@ -109,7 +147,8 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац % Только те операции, которые затрагивают данный объект. constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( - participation_as_resource[obj, t] in operations_that_used_obj_as_resource[obj] + (participation_as_resource[obj, t] != 0) + -> participation_as_resource[obj, t] in operations_that_used_obj_as_resource[obj] ); % Связь с текущими операциями перемещения. @@ -123,29 +162,37 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац (participation_as_resource[obj, t] = moving_op_of_obj[obj, current_moving_operation[obj, t]]) ) ); - % { Если объект участвует как ресурс в операции перемещения, то это согласованно с current_moving_operation, - % иначе (как ресурс в погрузке) - он должен стоять на месте. } + + % { Если объект участвует как ресурс в операции перемещения (не швартовки), то это согласованно с current_moving_operation, + % иначе (как ресурс в погрузке или швартове) - он должен стоять на месте. } constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( (participation_as_resource[obj, t] != 0) -> ( - if (is_moving_operation[participation_as_resource[obj, t]]) then - (participation_as_resource[obj, t] = moving_op_of_obj[obj, current_moving_operation[obj, t]]) - else - current_moving_operation[obj, t] = 0 - end + ( (is_moving_operation[participation_as_resource[obj, t]] /\ + (not is_mooring_op[participation_as_resource[obj, t]]) + ) -> ( + (current_moving_operation[obj, t] != 0) + /\ + (participation_as_resource[obj, t] = moving_op_of_obj[obj, current_moving_operation[obj, t]]) + ) + ) + /\ + (not (is_moving_operation[participation_as_resource[obj, t]] /\ + (not is_mooring_op[participation_as_resource[obj, t]]) + ) -> current_moving_operation[obj, t] = 0) ) ); + % { Объект участвует где-то в качестве ресурса - соответствующая операция обязана быть активной. } - constraint forall (obj in n_moving_obj, t in 1..n_intervals) ( + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( (participation_as_resource[obj, t] != 0) -> op_status[participation_as_resource[obj, t], t] ); + % От начала операции и до конца её ресурсы не могут измениться (в том числе и для погрузки). constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals - 1)) ( - if participation_as_resource[obj, t] != 0 then - op_status[participation_as_resource[obj, t], t + 1] -> ( - participation_as_resource[obj, t + 1] = participation_as_resource[obj, t] + (participation_as_resource[obj, t] != 0) -> + (op_status[participation_as_resource[obj, t], t + 1] + -> participation_as_resource[obj, t + 1] = participation_as_resource[obj, t] ) - else true - end ); int : n_resources_types; % Количество различных типов ресурсов. @@ -167,7 +214,7 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац % Определение resources_counter. constraint forall (counter in 1..n_resources_counters, t in 1..n_intervals) ( resources_counter[counter, t] = sum (obj in objects_of_type[counter_type[counter]]) ( - participation_as_resource[obj] = operation_of_counter[counter] + participation_as_resource[obj, t] = operation_of_counter[counter] ) ); @@ -183,24 +230,27 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац op in 1..n_operations, t in 1..n_intervals, counter in counters_of_operation[op], - obj in objects_of_type[counter_type[counter]] - where (participation_as_resource[obj, t] = op)) ( - op_start[op, t] -> ((m_obj_loc[obj, t] == operations_resources_start_loc[counter]) /\ - (not is_m_obj_in_movement_before_start[obj, t])) + obj in objects_of_type[counter_type[counter]]) ( + ((participation_as_resource[obj, t] = op) /\ (op_start[op, t]) + ) -> ((m_obj_loc[obj, t] == operations_resources_start_loc[counter]) /\ + (not is_m_obj_in_movement_before_start[obj, t]) /\ + ((not is_moving_operation[op]) -> (current_moving_operation[obj, t] = 0)) + ) ); % Наличие и готовность главных объектов (субъектов). - constraint forall (op in 1..n_operations, t in 1..n_intervals) ( - op_start[op, t] -> ((m_obj_loc[main_obj_of_operation[op], t] == main_obj_start_loc[op]) /\ - (not is_m_obj_in_movement_before_start[main_obj_of_operation[op], t])) + constraint forall (op in 1..n_operations, t in 1..n_intervals, obj = main_obj_of_operation[op]) ( + op_start[op, t] -> ((m_obj_loc[obj, t] == main_obj_start_loc[op]) /\ + (not is_m_obj_in_movement_before_start[obj, t]) /\ + ((not is_moving_operation[op]) -> (current_moving_operation[obj, t] = 0)) + ) ); % Непрерывность перемещения и швартовки. array [1..n_operations] of int : operations_duration; array [1..n_operations] of bool : is_continuous_operation; - constraint forall (i in 1..n_operations where is_continuous_operation[i]) ( - let {var int : len = operations_duration[i]} in + constraint forall (i in 1..n_operations, len = operations_duration[i] where is_continuous_operation[i]) ( (forall (j in 1..(n_intervals - len + 1)) ( (op_start[i, j] == 1) -> ( (forall (k in 1..(len - 1)) (op_status[i, j + k])) @@ -300,12 +350,20 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац solve minimize sum(is_not_terminated); output [show(sum(is_not_terminated)), "\n", - show(op_status), "\n\n", + "op_status = ", show(op_status), "\n\n", "m_obj_loc = ", show(m_obj_loc), "\n\n", "op_fin = ", show(op_fin), "\n\n", "op_start = ", show(op_start), "\n\n", "is_not_terminated = ", show(is_not_terminated), "\n\n", "storage_used_volume = ", show(storage_used_volume), "\n\n", "is_m_obj_in_movement_before_start = ", show(is_m_obj_in_movement_before_start), "\n\n", - "current_moving_operation = ", show(current_moving_operation), "\n\n" - ]; + "obj_in_loc_counter = ", show(obj_in_loc_counter), "\n\n", + "m_obj_loc = ", show(m_obj_loc), "\n\n", + "current_moving_operation = ", show(current_moving_operation), "\n\n", + "resources_counter {", show(n_intervals), "} = ", show(resources_counter), "\n\n", + "operation_of_counter {", show(n_resources_counters), "} = ", show(operation_of_counter), "\n\n", + "participation_as_resource = ", show(participation_as_resource), "\n\n", + + "real_current_moving_operation = ", show(current_moving_operation), "\n\n", + "moving_op_of_obj {", show(moving_op_of_obj_max_size + 1), "}= ", show(moving_op_of_obj), "\n\n", + ""]; diff --git a/src/inport/ConversionUtil.java b/src/inport/ConversionUtil.java index 8411f49..003418a 100644 --- a/src/inport/ConversionUtil.java +++ b/src/inport/ConversionUtil.java @@ -5,7 +5,6 @@ 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 { @@ -90,13 +89,14 @@ public class ConversionUtil { static private void writeArrayOfSetAs2DArray(FileWriter writer, String name, ArrayList> operations) throws IOException { - writeArrayOfSetAs2DArray(writer, name, operations, true); + writeArrayOfSetAs2DArray(writer, name, operations, true, false); } static private void writeArrayOfSetAs2DArray(FileWriter writer, String name, ArrayList> operations, - boolean addAdditionalInfo) throws IOException { + boolean addAdditionalInfo, + boolean addDummyZeroElement) throws IOException { int maxSize = 0; ArrayList sizes = new ArrayList<>(); for (ArrayList s : operations) { @@ -107,10 +107,18 @@ public class ConversionUtil { writer.write(name + "_max_size = " + maxSize + ";\n"); writeArray(writer, name + "_sizes", sizes); } - writer.write(name + " = array2d(1.." + operations.size() + ", 1.." + maxSize + ", ["); + writer.write(name + " = array2d(1.." + operations.size() + ", " + (addDummyZeroElement ? "0" : "1") + ".." + maxSize + ", ["); boolean isFirst = true; for (ArrayList s : operations) { + if (addDummyZeroElement) { + if (isFirst) { + isFirst = false; + } else { + writer.write(", "); + } + writer.write("1"); + } for (Integer val : s) { if (isFirst) { isFirst = false; @@ -197,7 +205,23 @@ public class ConversionUtil { return res; } - static private MovingObject getExecutor(OperationTemplate t) { + static private ArrayList> arrayOfIntegerArrays(int size) { + ArrayList> res = new ArrayList<>(); + for (int i = 0; i < size; i++) { + res.add(new ArrayList<>()); + } + return res; + } + + static private ArrayList> arrayOfIntegerSet(int size) { + ArrayList> res = new ArrayList<>(); + for (int i = 0; i < size; i++) { + res.add(new TreeSet<>()); + } + return res; + } + + static MovingObject getExecutor(OperationTemplate t) { if (t instanceof LoadingTemplate) { return ((LoadingTemplate) t).getLoader(); } @@ -210,7 +234,7 @@ public class ConversionUtil { return null; } - static private List getResources(OperationTemplate t) { + static List getResources(OperationTemplate t) { List res = new ArrayList<>(); if (t instanceof LoadingTemplate) { res.addAll(((LoadingTemplate) t).getResources()); @@ -266,7 +290,7 @@ public class ConversionUtil { return true; } - private static class Task { + static class Task { private FileWriter writer = null; private final String fileName; private final TaskCase task; @@ -280,9 +304,17 @@ public class ConversionUtil { } private final ArrayList movingObjects; - private final Function mObjToN; - private final ArrayList operationTemplates; + 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; @@ -292,6 +324,19 @@ public class ConversionUtil { private final Map storNById; private final Map cargoNById; + private final Map typeToN; + + private ArrayList> movingOpOfObj; + private ArrayList operationsDestination; + private ArrayList mainObjOfOperation; + private ArrayList isMooringOp; + + public ArrayList> getMovingOpOfObj() { + return movingOpOfObj; + } + + private ArrayList> objectsOfType; + Task(TaskCase task, String fileName) { this.fileName = fileName; this.task = task; @@ -306,7 +351,7 @@ public class ConversionUtil { } movingObjects = new ArrayList<>(); - Map mObjNumberById = new TreeMap<>(); + mObjNumberById = new TreeMap<>(); for (MovingObject obj : task.getShips()) { mObjNumberById.put(obj.getId(), movingObjects.size()); movingObjects.add(obj); @@ -320,8 +365,10 @@ public class ConversionUtil { movingObjects.add(obj); } - mObjToN = (MovingObject obj) -> mObjNumberById.get(obj.getId()); operationTemplates = new ArrayList<>(task.getTemplates()); + if (task.isTypified()) { + operationTemplates = renumberOperations(task); + } storages = new ArrayList<>(task.getStorages()); cargoes = new ArrayList<>(task.getCargoes()); @@ -337,6 +384,50 @@ public class ConversionUtil { } 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.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(); + } + } + + 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; } /* Операции прибытия/отбытия в локацию. (В том числе и швартовка.) */ @@ -358,9 +449,9 @@ public class ConversionUtil { ArrayList movingObjN = new ArrayList<>(); for (MovingObject obj : op.getResources()) { - movingObjN.add(mObjToN.apply(obj)); + movingObjN.add(mObjToN(obj)); } - movingObjN.add(mObjToN.apply(op.getMover())); + movingObjN.add(mObjToN(op.getMover())); for (Integer n : movingObjN) { arrivalOp .get(n).get(getLocNById(op.getDestination().getId(), false)).add(i + 1); @@ -371,9 +462,9 @@ public class ConversionUtil { ArrayList movingObjN = new ArrayList<>(); for (MovingObject obj : op.getResources()) { - movingObjN.add(mObjToN.apply(obj)); + movingObjN.add(mObjToN(obj)); } - movingObjN.add(mObjToN.apply(op.getMoorer())); + movingObjN.add(mObjToN(op.getMoorer())); for (Integer n : movingObjN) { arrivalOp .get(n).get(getLocNById(op.getStartLocation().getId(), op.isDirect())).add(i + 1); @@ -390,7 +481,7 @@ public class ConversionUtil { private void initialLocations() throws IOException { ArrayList initialStates = integerArray(movingObjects.size(), 0); for (MovingObjectState state : task.getVesselInitialState()) { - initialStates.set(mObjToN.apply(state.getVessel()), getLocNById(state.getLocation().getId(), false)); + initialStates.set(mObjToN(state.getVessel()), getLocNById(state.getLocation().getId(), false)); } writeArray(writer, "initial_m_obj_loc", initialStates, (Integer p) -> p + 1); writer.write("\n"); @@ -446,7 +537,7 @@ public class ConversionUtil { private void finalLocations() throws IOException { ArrayList finalStates = integerArray(movingObjects.size(), -1); for (MovingObjectState state : task.getVesselEndState()) { - finalStates.set(mObjToN.apply(state.getVessel()), getLocNById(state.getLocation().getId(), false)); + finalStates.set(mObjToN(state.getVessel()), getLocNById(state.getLocation().getId(), false)); } writeArray(writer, "final_m_obj_loc", finalStates, (Integer p) -> p + 1); } @@ -457,7 +548,7 @@ public class ConversionUtil { ArrayList> operationsResourcesStartLoc = new ArrayList<>(); BiConsumer addResource = (MovingObject r, Integer stLoc) -> { - operationsResources.get(operationsResources.size() - 1).add(mObjToN.apply(r) + 1); + operationsResources.get(operationsResources.size() - 1).add(mObjToN(r) + 1); operationsResourcesStartLoc.get(operationsResourcesStartLoc.size() - 1).add(stLoc + 1); }; @@ -486,7 +577,7 @@ public class ConversionUtil { } } writeArrayOfSetAs2DArray(writer, "operations_resources", operationsResources); - writeArrayOfSetAs2DArray(writer, "operations_resources_start_loc", operationsResourcesStartLoc, false); + writeArrayOfSetAs2DArray(writer, "operations_resources_start_loc", operationsResourcesStartLoc, false, false); writer.write("\n"); } @@ -544,7 +635,7 @@ public class ConversionUtil { 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); + initialStorageVol.get(mObjToN(ship)).set(cargoN, val); } } for (StorageState st : task.getStorageEndState()) { @@ -557,7 +648,7 @@ public class ConversionUtil { 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); + finalStorageVol.get(mObjToN(ship)).set(cargoN, val); } } write2DArrayOfInt(writer, "initial_storage_vol", initialStorageVol); @@ -617,7 +708,7 @@ public class ConversionUtil { 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 shipN = mObjToN(op.getLoader()); int cargoN = cargoNById.get(op.getCargo().getId()); loadingOpDelta.add(-(int)op.getIntensity()); @@ -644,9 +735,9 @@ public class ConversionUtil { ArrayList> movingOpOfObj = new ArrayList<>(); BiConsumer addUsOp = (MovingObject obj, Integer op) -> - objUsefulOperations.get(mObjToN.apply(obj)).add(op + 1); + objUsefulOperations.get(mObjToN(obj)).add(op + 1); BiConsumer addMovingOp = (MovingObject obj, Integer op) -> - movingOpOfObj.get(mObjToN.apply(obj)).add(op + 1); + movingOpOfObj.get(mObjToN(obj)).add(op + 1); for (int i = 0; i < movingObjects.size(); i++) { movingOpOfObj.add(new ArrayList<>()); @@ -692,7 +783,7 @@ public class ConversionUtil { ArrayList> objUsefulOperations = new ArrayList<>(); BiConsumer addUsOp = (MovingObject obj, Integer op) -> - objUsefulOperations.get(mObjToN.apply(obj)).add(op + 1); + objUsefulOperations.get(mObjToN(obj)).add(op + 1); for (int i = 0; i < movingObjects.size(); i++) { objUsefulOperations.add(new ArrayList<>()); @@ -726,24 +817,28 @@ public class ConversionUtil { 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 ArrayList<>()); - } - + private void initMovingObjectLocationDefinition() { BiConsumer addMovingOp = (MovingObject obj, Integer op) -> - movingOpOfObj.get(mObjToN.apply(obj)).add(op + 1); + 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); - for (MovingObject obj : getResources(t)) { - addMovingOp.accept(obj, 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) { @@ -756,8 +851,12 @@ public class ConversionUtil { operationsDestination.add(getLocNById(t.getStartLocation().getId(), false)); } } + } - writeArrayOfSetAs2DArray(writer, "moving_op_of_obj", movingOpOfObj); + private void movingObjectLocationDefinition() throws IOException { + writeArray(writer, "is_mooring_op", isMooringOp); + writeArray(writer, "main_obj_of_operation", mainObjOfOperation, (Integer val) -> val + 1); + writeArrayOfSetAs2DArray(writer, "moving_op_of_obj", movingOpOfObj, true, true); writeArray(writer, "operations_destination", operationsDestination, (Integer val) -> val + 1); writer.write("\n"); } @@ -838,6 +937,181 @@ public class ConversionUtil { } } + /* Каждую операцию лишает типизации по главному действующему лицу. */ + 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.getEquipmentsTypes().keySet()) { + shipsByType.put(type, new ArrayList<>()); + } + + ArrayList movingObjects = new ArrayList<>(); + movingObjects.addAll(task.getTows()); + movingObjects.addAll(task.getShips()); + movingObjects.addAll(task.getEquipments()); + + for (MovingObject obj : movingObjects) { + 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); + result.add(new LoadingTemplate((TransportShip)obj, t.getStartLocation(), t.getStorage(), + t.getCargo(), 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> conflictingPairs = new ArrayList<>(); + for (int i = 0; i < operationTemplates.size(); i++) { + for (int j = i + 1; j < operationTemplates.size(); j++) { + 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.getLoader() == op2.getLoader()) && + (op1.getStorage() == op2.getStorage()) && + (op1.getStartLocation() == op2.getStartLocation())) { + conflictingPairs.add(new Pair<>(i + 1, 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)) { + conflictingPairs.add(new Pair<>(i + 1, j + 1)); + } + } + } + { // Взаимоисключение операций швартовки/отшвартовки с одним причалом. + // TODO выделить в отдельный constraint + if ((operationTemplates.get(i) instanceof MooringTemplate) && + (operationTemplates.get(j) instanceof MooringTemplate)) { + MooringTemplate op1 = (MooringTemplate) operationTemplates.get(i); + MooringTemplate op2 = (MooringTemplate) operationTemplates.get(j); + + if (op1.getStartLocation() == op2.getStartLocation()) { + 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 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, ConversionUtil::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, ConversionUtil::setToString); + writer.write("\n"); + } + { // main_obj_start_loc, is_moving_operation + ArrayList mainObjStartLoc = new ArrayList<>(); + ArrayList isMovingOp = 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(locationNumberById.get(new Pair<>(op.getStartLocation().getId(), isMoored))); + isMovingOp.add((op instanceof MovingTemplate) || (op instanceof MooringTemplate)); + } + writeArray(writer, "main_obj_start_loc", mainObjStartLoc, (Integer val) -> val + 1); + writeArray(writer, "is_moving_operation", isMovingOp); + 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, ConversionUtil::setToString); + } + } /* С типизацией. */ void portToMiniZinc_2() throws IOException { @@ -848,7 +1122,7 @@ public class ConversionUtil { writer = new FileWriter(fileName, false); writer.write("n_intervals = " + n_intervals + ";\n"); - writer.write("n_operations = " + task.getTemplates().size() + ";\n"); + writer.write("n_operations = " + operationTemplates.size() + ";\n"); writer.write("n_locations = " + locationNumberById.size() + ";\n"); writer.write("n_moving_obj = " + movingObjects.size() + ";\n"); @@ -856,11 +1130,12 @@ public class ConversionUtil { movingObjectLocationDefinition(); initialLocations(); + finalLocations(); weatherWindows(); + conflictingOperationsOnStorageAndOnTypeOnMainObject(); + operationsContinuity(); - finalLocations(); - presenceOfResourcesInLocation(); - conflictingOperations(); + typifiedResourcesDefinition(); writer.write("n_obj_with_storage = " + nObjWithStorage + ";\n"); writer.write("n_cargo_types = " + cargoes.size() + ";\n"); @@ -891,13 +1166,22 @@ public class ConversionUtil { } } + static public void portToMiniZinc_2(TaskCase task, String fileName) { + try { + Task taskData = new Task(task, fileName); + taskData.portToMiniZinc_2(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + 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) { + public static void resolveMiniZincResults(TaskCase task, String fileName) { ArrayList operations = null; Integer result = null; @@ -906,72 +1190,147 @@ public class ConversionUtil { String line; + Map>> arrays = new TreeMap<>(); + while (((line = br.readLine()) != null)) { line = line.trim(); if (line.equals("")) { continue; } - String regexpr = "^\\[.*]\\z"; - if (line.matches(regexpr)) { - if (operations != null) { + int pos = 0; + while ((pos < line.length()) && (line.charAt(pos) != ' ')) { + pos++; + } + String name = line.substring(0, pos); + + if (name.equals("=====UNSATISFIABLE=====")) { + result = -1; + break; + } + if (name.equals("----------")) { + break; + } + if (name.matches("\\d+")) { + if (result != 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(); + result = Integer.parseInt(name); + continue; + } + + while ((pos < line.length()) && (line.charAt(pos) != '[') && (line.charAt(pos) != '{')) { + pos++; + } + int arrayFirstDim = ((int) task.getPlanningInterval()) + 2; - if (tokens.size() != (n_intervals + 2) * task.getTemplates().size()) { - throw new ParserException("Invalid length of \"op_status\""); + if (line.charAt(pos) == '{') { + pos++; + int nextPos = pos; + while (line.charAt(nextPos) != '}') { + nextPos++; + } + arrayFirstDim = Integer.valueOf(line.substring(pos, nextPos).trim()); + pos = nextPos + 1; + while (line.charAt(pos) != '[') { + pos++; } + } - operations = new ArrayList<>(); + int pos2 = pos; + while ((pos2 < line.length()) && (line.charAt(pos2) != ']')) { + pos2++; + } + String values = line.substring(pos + 1, pos2); + ArrayList elements = 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)); + for (String val : values.split(",")) { + elements.add(val.trim()); + } - operations.add(op); + if ((arrayFirstDim != 0) && (elements.size() % arrayFirstDim == 0)) { + ArrayList> res = new ArrayList<>(); - duration = 0; - } + for (int i = 0; i < elements.size(); i += arrayFirstDim) { + ArrayList subRes = new ArrayList<>(); + for (int j = 0; j < arrayFirstDim; j++) { + subRes.add(elements.get(i + j)); } + res.add(subRes); } - continue; + arrays.put(name, res); } - if (line.matches("\\d+")) { - if (result != null) { - continue; - } - result = Integer.parseInt(line); - continue; - } - if (line.equals("=====UNSATISFIABLE=====")) { - result = -1; - } - break; } + if (result == null) { throw new ParserException("No result in input"); } - if (operations == null) { + if (!arrays.containsKey("op_status")) { if (result == -1) { operations = new ArrayList<>(); } else { throw new ParserException("No \"op_status\" in input"); } } + if (result != -1) { + operations = new ArrayList<>(); + ArrayList> opStatus = arrays.get("op_status"); + + ArrayList templates = new ArrayList<>(task.getTemplates()); + if (task.isTypified()) { + templates = Task.renumberOperations(task); + } + + Map operationById = new TreeMap<>(); + for (OperationTemplate operation : task.getTemplates()) { + operationById.put(operation.getId(), operation); + } + + Map objByNo = new TreeMap<>(); + { + Task t = new Task(task, ""); + ArrayList movingObjects = new ArrayList<>(); + movingObjects.addAll(task.getShips()); + movingObjects.addAll(task.getTows()); + movingObjects.addAll(task.getEquipments()); + + for (MovingObject obj : movingObjects) { + objByNo.put(t.getMObjNumberById().get(obj.getId()), obj); + } + } + + for (int opNo = 0; opNo < opStatus.size(); opNo++) { + int duration = 0; + for (int t = 0; t < opStatus.get(opNo).size(); t++) { + if (opStatus.get(opNo).get(t).equals("true")) { + duration++; + } else if (duration != 0) { + Operation op = new Operation(); + op.setStart(t - duration - 1); + op.setDuration(duration); + op.setTemplate(operationById.get(templates.get(opNo).getId())); + + if (task.isTypified()) { + op.setExecutor(ConversionUtil.getExecutor(templates.get(opNo))); + + ArrayList resources = new ArrayList<>(); + + // TODO ускорить. + ArrayList> opOfResource = arrays.get("participation_as_resource"); + for (int obj = 0; obj < opOfResource.size(); obj++) { + if (opOfResource.get(obj).get(t - 1).equals(Integer.toString(opNo + 1))) { + resources.add(objByNo.get(obj)); + } + } + op.setResources(resources); + } + + operations.add(op); + duration = 0; + } + } + } + } + operations.sort(new OperationsComparator()); task.setSolution(operations); task.setSolution_result(result); diff --git a/src/inport/LoadingEquipment.java b/src/inport/LoadingEquipment.java index ac69354..231e2ec 100644 --- a/src/inport/LoadingEquipment.java +++ b/src/inport/LoadingEquipment.java @@ -22,9 +22,9 @@ public class LoadingEquipment extends MovingObject{ @Override public String toString() { - String res = getId() + ";" + getName(); + String res = getId() + "; " + getName(); if (getType().isPresent()) { - res += ";" + getType().getAsInt(); + res += "; " + getType().getAsInt(); } return res; } diff --git a/src/inport/LoadingTemplate.java b/src/inport/LoadingTemplate.java index e62914e..80dc58f 100644 --- a/src/inport/LoadingTemplate.java +++ b/src/inport/LoadingTemplate.java @@ -95,13 +95,16 @@ public class LoadingTemplate extends OperationTemplate { return cargo; } - public LoadingTemplate(TransportShip loader, Berth berth, Storage storage, double intensity, int id) { + public LoadingTemplate(TransportShip loader, Berth berth, Storage storage, Cargo cargo, + List resourcesTypes, boolean withMooring, double intensity, int id) { super(id, berth); this.loader = loader; this.storage = storage; this.resources = new ArrayList<>(); - this.resourcesTypes = new ArrayList<>(); + this.resourcesTypes = new ArrayList<>(resourcesTypes); + this.withMooring = withMooring; this.intensity = intensity; + this.cargo = cargo; } public LoadingTemplate() { diff --git a/src/inport/Main.java b/src/inport/Main.java index 55bd4f3..e086396 100644 --- a/src/inport/Main.java +++ b/src/inport/Main.java @@ -1,9 +1,14 @@ package inport; import java.io.*; +import java.util.ArrayList; +import java.util.Map; +import java.util.TreeMap; import static inport.Testing.solveTask_1; +import static inport.Testing.solveTask_2; import static inport.Testing.test_1; +import inport.ConversionUtil.*; public class Main { @@ -27,7 +32,12 @@ public class Main { break; } - String error = solveTask_1(task); + String error; + if (!task.isTypified()) { + error = solveTask_1(task); + } else { + error = solveTask_2(task); + } long finish = System.currentTimeMillis(); System.out.println((finish - start) + " milliseconds"); @@ -81,16 +91,29 @@ public class Main { break; } case "debug" : { - String fileName = args[1]; - String output = args[2]; + String fileName = "experiment/in.ipp"; + String solverResults = "temp_data/solver_results.txt"; + String output = "experiment/debug_info.txt"; TaskCase task = new TaskCase(); try { task.deserialize(fileName); - task.serialize(output); } catch (IOException e) { System.out.println(e.getMessage()); + break; + } + + String error = solveTask_2(task); + + if (!error.isEmpty()) { + System.out.println("Error : " + error); + break; + } else { + task.serialize(fileName); } + + debugInfo(task, solverResults, output); + break; } case "testing" : @@ -100,4 +123,145 @@ public class Main { System.out.println("Unknown type \"" + type + "\""); } } + + private static void debugInfo(TaskCase task, String solverResults, String output) { + try (FileInputStream fstream = new FileInputStream(solverResults)) { + BufferedReader br = new BufferedReader(new InputStreamReader(fstream)); + FileWriter writer = new FileWriter(output, false); + + { + ArrayList operations = new ArrayList<>(task.getTemplates()); + if (task.isTypified()) { + operations = Task.renumberOperations(task); + } + writer.write("operations :\n"); + int no = 1; + for (OperationTemplate op : operations) { + writer.write(" " + no + " " + op.toString() + "\n"); + no++; + } + writer.write("\n"); + } + Task t = new Task(task, ""); + { + ArrayList movingObjects = new ArrayList<>(); + movingObjects.addAll(task.getShips()); + movingObjects.addAll(task.getTows()); + movingObjects.addAll(task.getEquipments()); + + Map objByNo = new TreeMap<>(); + for (MovingObject obj : movingObjects) { + objByNo.put(t.getMObjNumberById().get(obj.getId()), obj); + } + + writer.write("moving_objects : \n"); + for (int i = 0; i < movingObjects.size(); i++) { + writer.write(" " + (i + 1) + " " + objByNo.get(i).toString() + "\n"); + } + writer.write("\n"); + } + + String line; + int linesNumber = 0; + + while (((line = br.readLine()) != null)) { + line = line.trim(); + if (line.equals("")) { + continue; + } + linesNumber++; + if (linesNumber <= 1) { + continue; + } + int pos = 0; + while ((pos < line.length()) && (line.charAt(pos) != ' ')) { + pos++; + } + String name = line.substring(0, pos); + + if (name.equals("----------")) { + break; + } + + while ((pos < line.length()) && (line.charAt(pos) != '[') && (line.charAt(pos) != '{')) { + pos++; + } + + int arrayFirstDim = ((int) task.getPlanningInterval()) + 2; + + if (line.charAt(pos) == '{') { + pos++; + int nextPos = pos; + while (line.charAt(nextPos) != '}') { + nextPos++; + } + arrayFirstDim = Integer.valueOf(line.substring(pos, nextPos).trim()); + pos = nextPos + 1; + while (line.charAt(pos) != '[') { + pos++; + } + } + + int pos2 = pos; + while ((pos2 < line.length()) && (line.charAt(pos2) != ']')) { + pos2++; + } + String values = line.substring(pos + 1, pos2); + ArrayList elements = new ArrayList<>(); + + for (String val : values.split(",")) { + elements.add(val.trim()); + } + + if (name.equals("current_moving_operation")) { + ArrayList> movingOpOfObj = t.getMovingOpOfObj(); + for (int i = 0; i < elements.size(); i += arrayFirstDim) { + for (int j = 0; j < arrayFirstDim; j++) { + int val = Integer.valueOf(elements.get(i + j)); + if (val != 0) { + elements.set(i + j, Integer.toString(movingOpOfObj.get(i / arrayFirstDim).get(val - 1))); + } + } + } + name = name + " *"; + } + + { // bool to int + for (int i = 0; i < elements.size(); i++) { + if (elements.get(i).equals("true")) { + elements.set(i, "1"); + } + if (elements.get(i).equals("false")) { + elements.set(i, "0"); + } + } + } + + int maxLength = 0; + for (String val : elements) { + maxLength = Math.max(maxLength, val.length()); + } + + if ((arrayFirstDim != 0) && (elements.size() % arrayFirstDim == 0)) { + writer.write(name + " :\n"); + for (int i = 0; i < elements.size(); i += arrayFirstDim) { + writer.write(" "); + for (int j = 0; j < arrayFirstDim; j++) { + String val = elements.get(i + j); + for (int k = val.length(); k < maxLength; k++) { + writer.write(" "); + } + writer.write(val + " "); + } + writer.write("\n"); + } + writer.write("\n"); + } + } + + writer.close(); + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } } diff --git a/src/inport/MooringTemplate.java b/src/inport/MooringTemplate.java index b23ca85..1a2184b 100644 --- a/src/inport/MooringTemplate.java +++ b/src/inport/MooringTemplate.java @@ -4,6 +4,7 @@ */ package inport; +import java.util.List; import java.util.OptionalInt; /** @@ -59,10 +60,11 @@ public class MooringTemplate extends TowUsingTemplate { this.moorer = moorer; } - public MooringTemplate(TransportShip moorer, Berth berth, double duration, boolean direct, int id) { + public MooringTemplate(TransportShip moorer, Berth berth, List resourcesTypes, double duration, boolean direct, int id) { super(duration, id, berth); this.moorer = moorer; this.direct = direct; + this.setResourcesTypes(resourcesTypes); } public MooringTemplate() { diff --git a/src/inport/MovingTemplate.java b/src/inport/MovingTemplate.java index f90f76d..b63ea82 100644 --- a/src/inport/MovingTemplate.java +++ b/src/inport/MovingTemplate.java @@ -4,6 +4,7 @@ */ package inport; +import java.util.List; import java.util.OptionalInt; /** @@ -60,10 +61,11 @@ public class MovingTemplate extends TowUsingTemplate { this.moverType = moverType; } - public MovingTemplate(MovingObject mover, Berth source, Berth destination, double duration, int id) { + public MovingTemplate(MovingObject mover, Berth source, Berth destination, List resourcesTypes, double duration, int id) { super(duration, id, source); this.mover = mover; - this.destination = destination; + this.destination = destination; + this.setResourcesTypes(resourcesTypes); } public MovingTemplate() { diff --git a/src/inport/Operation.java b/src/inport/Operation.java index e97d0b8..70b5a8e 100644 --- a/src/inport/Operation.java +++ b/src/inport/Operation.java @@ -4,6 +4,8 @@ */ package inport; +import java.util.List; + /** * * @author topazh_ag @@ -13,6 +15,22 @@ public class Operation { private OperationTemplate template; private double start; private double duration; + private MovingObject executor; + private List resources; + + public List getResources() { + return resources; + } + public void setResources(List resources) { + this.resources = resources; + } + + public MovingObject getExecutor() { + return executor; + } + public void setExecutor(MovingObject executor) { + this.executor = executor; + } /** * Get the value of duration @@ -75,8 +93,25 @@ public class Operation { @Override public String toString() { - return template.getId() + "; R; " + start + "; " + duration; + if (executor == null) { + executor = ConversionUtil.getExecutor(template); + } + if (resources == null) { + resources = ConversionUtil.getResources(template); + } + StringBuilder sb = new StringBuilder(); + sb.append(template.getId()).append("; R; ").append(start).append("; ").append(duration); + sb.append(" (").append(executor.getId()).append(" ["); + boolean isFirst = true; + for (MovingObject obj : resources) { + if (isFirst) { + isFirst = false; + } else { + sb.append(", "); + } + sb.append(obj.getId()); + } + sb.append("])"); + return sb.toString(); } - - } diff --git a/src/inport/TaskCase.java b/src/inport/TaskCase.java index 04eb72b..56242d4 100644 --- a/src/inport/TaskCase.java +++ b/src/inport/TaskCase.java @@ -660,7 +660,7 @@ public class TaskCase { br.close(); } catch (FileNotFoundException ex) { Logger.getLogger(TaskCase.class.getName()).log(Level.SEVERE, null, ex); - } + } } public void serialize(String fileName) diff --git a/src/inport/Testing.java b/src/inport/Testing.java index 56c8e34..5a0d745 100644 --- a/src/inport/Testing.java +++ b/src/inport/Testing.java @@ -26,6 +26,14 @@ public class Testing { ConversionUtil::resolveMiniZincResults); } + public static String solveTask_2(TaskCase task) { + return solveTask( + task, + "conversion_2.mzn", + ConversionUtil::portToMiniZinc_2, + ConversionUtil::resolveMiniZincResults); + } + /* Возвращает описание ошибки, если ошибки не было, то пустую строку. */ public static String solveTask(TaskCase task, String constraintName, @@ -63,6 +71,13 @@ public class Testing { BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream())); String output = br.lines().collect(Collectors.joining("\n")); + BufferedReader br2 = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String errors = br.lines().collect(Collectors.joining("\n")); + + + System.out.println("output : " + output); + System.out.println("errors : " + errors); + if (output.trim().equals("=====UNSATISFIABLE=====")) { task.setSolution(new ArrayList<>()); task.setSolution_result(-1); @@ -72,7 +87,7 @@ public class Testing { } catch (UncheckedIOException | IOException | InterruptedException | ParserException ex) { return ex.getMessage(); } finally { - removeDirectory(directory); +// removeDirectory(directory); } return ""; } diff --git a/src/inport/Tow.java b/src/inport/Tow.java index f7498da..8c18860 100644 --- a/src/inport/Tow.java +++ b/src/inport/Tow.java @@ -21,9 +21,9 @@ public class Tow extends MovingObject { @Override public String toString() { - String res = getId() + ";" + getName() + ";1000000"; + String res = getId() + "; " + getName() + "; 1000000"; if (getType().isPresent()) { - res += ";" + getType().getAsInt(); + res += "; " + getType().getAsInt(); } return res; } diff --git a/src/inport/TransportShip.java b/src/inport/TransportShip.java index 4f395aa..407b86e 100644 --- a/src/inport/TransportShip.java +++ b/src/inport/TransportShip.java @@ -32,9 +32,9 @@ public class TransportShip extends MovingObject { @Override public String toString() { - String res = getId() + ";" + getName() + ";" + cargoMax; + String res = getId() + "; " + getName() + "; " + cargoMax; if (getType().isPresent()) { - res += ";" + getType().getAsInt(); + res += "; " + getType().getAsInt(); } return res; } -- GitLab