From dbe1706c9ceb93ff21e0a69cb0cc544bedac0bc6 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, 20 Jun 2019 18:38:45 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BE=D0=BF=D1=82=D0=B8=D0=BC=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20-=20=D0=BF=D1=80=D0=B5=D0=B6=D0=B4=D0=B5?= =?UTF-8?q?=20=D1=87=D0=B5=D0=BC=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0?= =?UTF-8?q?=D1=89=D0=B0=D1=82=D1=8C=D1=81=D1=8F=20=D0=B2=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B5=D0=B4=D1=8B=D0=B4=D1=83=D1=89=D1=83=D1=8E=20=D0=BB=D0=BE?= =?UTF-8?q?=D0=BA=D0=B0=D1=86=D0=B8=D1=8E=20=D1=81=D1=83=D0=B4=D0=BD=D0=BE?= =?UTF-8?q?=20=D0=B4=D0=BE=D0=BB=D0=B6=D0=BD=D0=BE=20=D1=81=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D1=82=D1=8C=20=D1=87=D1=82=D0=BE-=D1=82=D0=BE=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=B5=D0=B7=D0=BD=D0=BE=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constraints/conversion_2.mzn | 59 +++++++++++++++++++++++++++++++- src/inport/ConversionUtil.java | 53 ++++++++++++++++++++++++++-- 2 files changed, 108 insertions(+), 4 deletions(-) diff --git a/src/constraints/conversion_2.mzn b/src/constraints/conversion_2.mzn index 2bee6ae..41a329b 100644 --- a/src/constraints/conversion_2.mzn +++ b/src/constraints/conversion_2.mzn @@ -219,6 +219,9 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац % Операции погрузки, которые используют этот объект в качестве главного или в качестве бункеровщика. array [0..n_moving_obj] of set of 0..n_operations : related_cargo_op; + % Операции отшвартовки, которые используют объект в качестве главного. + array [0..n_moving_obj] of set of 1..n_operations : related_unmooring_op; + % TODO узнать про where % Определение is_involved_in_cargo_op. constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( @@ -369,6 +372,7 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац array [1..n_fixed_op] of int : fixed_op_intensity; array [0..n_operations, 0..n_intervals] of bool : is_fixed; + array [0..n_moving_obj, 0..(n_intervals + 1)] of bool : is_obj_involved_in_fixed_op; constraint forall (no in 1..n_fixed_op, op = fixed_op[no]) ( forall (t in fixed_op_start[no]..fixed_op_end[no]) ( @@ -457,6 +461,55 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац (op_start[op, t] /\ (not is_fixed[op, t])) -> not is_op_possible[op, t - 1] ); +% Оптимизация - судно возвращается откуда перед этим пришло -> оно сделало или делает что-то "полезное". + array [0..n_moving_obj, 0..(n_intervals + 1)] of var 1..n_locations : prev_m_obj_loc; + array [0..n_moving_obj, 0..(n_intervals + 1)] of var bool : is_obj_involved_in_useful_operation; + + constraint forall (t in 0..(n_intervals + 1)) (prev_m_obj_loc[0, t] = 1); + constraint forall (t in 0..(n_intervals + 1)) (is_obj_involved_in_useful_operation[0, t] = false); + + % Определение prev_m_obj_loc + constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( + (m_obj_loc[obj, t - 1] != m_obj_loc[obj, t]) -> (prev_m_obj_loc[obj, t] = m_obj_loc[obj, t - 1]) + ); + constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( + (m_obj_loc[obj, t - 1] == m_obj_loc[obj, t]) -> (prev_m_obj_loc[obj, t] = prev_m_obj_loc[obj, t - 1]) + ); + constraint forall (obj in 1..n_moving_obj) (prev_m_obj_loc[obj, 0] = m_obj_loc[obj, 0]); + + % Определение is_obj_involved_in_useful_operation + constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( + is_obj_involved_in_useful_operation[obj, t] = ( + (participation_as_resource[obj, t] != 0) + \/ (exists (op in related_cargo_op[obj]) (op_status[op, t])) + \/ (is_obj_involved_in_fixed_op[obj, t]) + \/ (exists (op in related_unmooring_op[obj]) (op_status[op, t])) + ) + ); + constraint forall (obj in 1..n_moving_obj) (is_obj_involved_in_useful_operation[obj, 0] = false); + + % Успел ли объект поучаствовать в полезной операции к концу данного интервала. + array [0..n_moving_obj, 0..(n_intervals + 1)] of var bool : is_attended_useful_op_in_cur_loc; + % Определение is_attended_useful_op_in_cur_loc + constraint forall (t in 0..(n_intervals + 1)) (is_attended_useful_op_in_cur_loc[0, t] = false); + + constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( + is_attended_useful_op_in_cur_loc[obj, t] = ( + (is_attended_useful_op_in_cur_loc[obj, t - 1] /\ (m_obj_loc[obj, t - 1] == m_obj_loc[obj, t])) % Предыдущее значение в текущей локации. + \/ + is_obj_involved_in_useful_operation[obj, t] + \/ + is_obj_involved_in_useful_operation[obj, t - 1] % Учитывает случай когда операция перемещения, из-за которой объект попал в локацию была нужна. + ) + ); + + % Сама оптимизация - если объект + constraint forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) ( + ((m_obj_loc[obj, t - 1] != m_obj_loc[obj, t]) /\ (prev_m_obj_loc[obj, t - 1] == m_obj_loc[obj, t]) + ) -> is_attended_useful_op_in_cur_loc[obj, t - 1] + ); + + % Критерий оптимизации array [1..(n_intervals + 1)] of var bool : is_not_terminated; % В конце всё остановится. @@ -487,7 +540,11 @@ output [show(sum(is_not_terminated)), "\n", "is_involved_in_cargo_op = {", show(n_intervals), "} ", show(is_involved_in_cargo_op), "\n\n", - "current_moored_obj = ", show(current_moored_obj), "\n\n", + "m_obj_loc = ", show(m_obj_loc), "\n\n", + + "prev_m_obj_loc = {", show(n_intervals + 2), "} ", show(prev_m_obj_loc), "\n\n", + "is_obj_involved_in_useful_operation = {", show(n_intervals + 2), "} ", show(is_obj_involved_in_useful_operation), "\n\n", + "is_attended_useful_op_in_cur_loc = {", show(n_intervals + 2), "} ", show(is_attended_useful_op_in_cur_loc), "\n\n", /* "is_op_possible {", show(n_intervals), "} = ", show(is_op_possible), "\n\n", diff --git a/src/inport/ConversionUtil.java b/src/inport/ConversionUtil.java index 865ed27..6ad9923 100644 --- a/src/inport/ConversionUtil.java +++ b/src/inport/ConversionUtil.java @@ -1066,6 +1066,24 @@ public class ConversionUtil { 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, ConversionUtil::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++) { @@ -1378,18 +1396,45 @@ public class ConversionUtil { 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 (Operation op : task.getFixedOperations()) { if (op.getFixation()) { OptionalInt bunkerId = op.getBunker().map(b -> OptionalInt.of(b.getId())).orElse(OptionalInt.empty()); - fixedOp.add(opNoByOpData.get(new OperationData(op.getTemplate().getId(), op.getExecutor().getId(), bunkerId)) + 1); + 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); + } + } + } + + fixedOp.add(opNo + 1); TreeSet resources = new TreeSet<>(); for (MovingObject obj : op.getResources()) { resources.add(mObjToN(obj)); } fixedOpResources.add(resources); - fixedOpStart.add((int)Math.floor(op.getStart()) + 1); - fixedOpEnd.add((int)Math.ceil(op.getDuration() + op.getStart())); + fixedOpStart.add(start + 1); + fixedOpEnd.add(end); fixedOpIntensity.add((int)Math.ceil(op.getIntensity().orElse(0))); } } @@ -1401,6 +1446,7 @@ public class ConversionUtil { 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); } void defDataForCurMovingOp() throws IOException { @@ -1532,6 +1578,7 @@ public class ConversionUtil { typifiedResourcesDefinition(); cargoOpUsingObj(); + unmooringOpUsingObj(); addOpWithNominallyMooring(); writer.write("n_all_storage_sections = " + sectionNById.size() + ";\n"); -- GitLab