From 3c72d73dcbd814d820c0546e6910a194a60ccb94 Mon Sep 17 00:00:00 2001 From: Vlad_kv Date: Tue, 27 Nov 2018 22:04:54 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D0=B5=D0=B7=D0=BD=D0=B0?= =?UTF-8?q?=D1=8F=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BC=D0=B5=D0=B6=D0=B4=D1=83=20=D0=B4=D0=B2=D0=B8=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=D0=BC=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- constraints/conversion_0.mzn | 79 +++++++++++++++++++++++++++++++++- src/inport/ConversionUtil.java | 59 +++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/constraints/conversion_0.mzn b/constraints/conversion_0.mzn index ed1d547..76f22b1 100644 --- a/constraints/conversion_0.mzn +++ b/constraints/conversion_0.mzn @@ -112,6 +112,8 @@ constraint forall (storage in 1..n_obj_with_storage, cargo in 1..n_cargo_types) /\ (if final_storage_vol[storage, cargo] >= 0 then (storage_used_volume[storage, (n_intervals + 1), cargo] == final_storage_vol[storage, cargo]) + else + true endif) ); @@ -145,6 +147,78 @@ constraint forall (t in 1..n_intervals) ( ) ); +% Ограничение на совершение полезной операции при движении назад (окончание отшвартовки - "полезная операция"). + +array [1..n_moving_obj, 0..(n_intervals + 1)] of var 0..n_locations : next_m_obj_loc; % Позиция движущегося объекта на ближайшей остановке. + constraint forall (obj in 1..n_moving_obj) (next_m_obj_loc[obj, n_intervals + 1] = m_obj_loc[obj, n_intervals + 1]); + + constraint forall (obj in 1..n_moving_obj, t in 0..n_intervals) ( + next_m_obj_loc[obj, t] = + if (m_obj_loc[obj, t] = 0) then + next_m_obj_loc[obj, t + 1] + else + m_obj_loc[obj, t] + endif + ); + +array [1..n_moving_obj, 0..(n_intervals + 1)] of var 0..n_locations : prev_m_obj_loc; % Строго предыдущая позиция объекта. + constraint forall (obj in 1..n_moving_obj) (prev_m_obj_loc[obj, 0] = 0); + + constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( + prev_m_obj_loc[obj, t] = + if ((m_obj_loc[obj, t - 1] != 0) /\ (m_obj_loc[obj, t] != m_obj_loc[obj, t - 1])) then + m_obj_loc[obj, t - 1] + else + prev_m_obj_loc[obj, t - 1] + endif + ); + +int : n_useful_op; +array [1..n_useful_op] of 1..n_moving_obj : useful_op_obj; +array [1..n_useful_op] of 1..n_operations : useful_op_id; + +array [1..n_moving_obj] of set of 1..n_operations : obj_useful_operations; % Все полезные операции касающиеся данного объекта. + +array [1..n_moving_obj, 0..(n_intervals + 1)] of var bool : is_m_obj_useful; % Был ли объект задействован в "полезной" операции (не движении в качестве главного объекта). + constraint forall (i in 1..n_useful_op, t in 0..(n_intervals + 1)) ( + op_status[useful_op_id[i], t] -> is_m_obj_useful[useful_op_obj[i], t] + ); + constraint forall (obj in 1..n_moving_obj, t in 0..(n_intervals + 1)) ( % Недопущение "ложного срабатывания" is_m_obj_useful. + is_m_obj_useful[obj, t] -> exists (useful_op in obj_useful_operations[obj]) ( + op_status[useful_op, t] == true + ) + ); + +array [1..n_moving_obj, 0..(n_intervals + 1)] of var bool : is_obj_in_moving; +array [1..n_moving_obj] of set of 1..n_operations : moving_op_of_obj; % Операции перемещения затрагивающие данный объект. + constraint forall (obj in 1..n_moving_obj, t in 0..(n_intervals + 1)) ( + is_obj_in_moving[obj, t] = exists (moving_op in moving_op_of_obj[obj]) (op_status[moving_op, t] = true) + ); + +array [1..n_moving_obj, 0..(n_intervals + 1)] of var bool : is_interval_useful; % Была ли на текущем интервале полезная операция. + % Ось времени нарежим по моментам начал свершившихся операций перемещения соответствующего движущегося объекта. Речь идёт о интервале который включает в себя данный атомарный промежуток времени. + % !!! Важен только самый правый элемент интервала!!! (Значения на времени покрывающимся операцией движения могут быть 0 если они не с правого края интервала.) + % И в фиктивном нуле false. + + constraint forall (obj in 1..n_moving_obj) (is_interval_useful[obj, 0] = false); + + constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( + is_interval_useful[obj, t] = + if (is_obj_in_moving[obj, t]) then + is_m_obj_useful[obj, t] + else + is_m_obj_useful[obj, t] \/ is_interval_useful[obj, t - 1] + endif + ); + +constraint forall (obj in 1..n_moving_obj, t in 0..n_intervals) ( % Само ограничение. + if ((m_obj_loc[obj, t] != 0) /\ (next_m_obj_loc[obj, t + 1] != 0) /\ (m_obj_loc[obj, t + 1] == 0)) then + if (next_m_obj_loc[obj, t + 1] == prev_m_obj_loc[obj, t]) then + is_interval_useful[obj, t] == true + endif + endif +); + solve minimize sum(is_not_terminated); output [show(sum(is_not_terminated)), "\n", @@ -155,5 +229,8 @@ output [show(sum(is_not_terminated)), "\n", "arrival_op = ", show(arrival_op), "\n\n", "departure_op = ", show(departure_op), "\n\n", "is_not_terminated = ", show(is_not_terminated), "\n\n", - "storage_used_volume = ", show(storage_used_volume), "\n\n" + "storage_used_volume = ", show(storage_used_volume), "\n\n", + "prev_m_obj_loc = ", show(prev_m_obj_loc), "\n\n", + "next_m_obj_loc = ", show(next_m_obj_loc), "\n\n", + "is_interval_useful = ", show(is_interval_useful), "\n\n" ]; diff --git a/src/inport/ConversionUtil.java b/src/inport/ConversionUtil.java index 43eac8e..fd57e5e 100644 --- a/src/inport/ConversionUtil.java +++ b/src/inport/ConversionUtil.java @@ -4,6 +4,7 @@ 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; @@ -516,6 +517,64 @@ public class ConversionUtil { write2DArrayOfSet(writer, "involved_operations", involvedOperations); writeArray(writer, "loading_op_delta", loadingOpDelta); writeArray(writer, "loading_op_n", loadingOpN, (Integer i) -> i + 1); + writer.write("\n"); + } + { // Ограничение на необходимость полезной операции между движениями к одному пункту назначения. + ArrayList usefulOpObj = new ArrayList<>(); + ArrayList usefulOpId = new ArrayList<>(); + + ArrayList> objUsefulOperations = new ArrayList<>(); + + ArrayList> movingOpOfObj = new ArrayList<>(); + + BiConsumer addUsOp = (MovingObject obj, Integer op) -> { + usefulOpObj.add(mObjToN.apply(obj)); + usefulOpId.add(op); + objUsefulOperations.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; + + int id = mObjToN.apply(op.getMover()); + movingOpOfObj.get(id).add(i + 1); + + for (MovingObject obj : op.getResources()) { + addUsOp.accept(obj, i); + } + } else if (t instanceof MooringTemplate) { + MooringTemplate op = (MooringTemplate)t; + + int id = mObjToN.apply(op.getMoorer()); + movingOpOfObj.get(id).add(i + 1); + + 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); + } + } + + writer.write("n_useful_op = " + usefulOpObj.size() + ";\n"); + writeArray(writer, "useful_op_obj", usefulOpObj, (Integer i) -> i + 1); + writeArray(writer, "useful_op_id", usefulOpId, (Integer i) -> i + 1); + + writeArray(writer, "obj_useful_operations", objUsefulOperations, ConversionUtil::setToString); + writeArray(writer, "moving_op_of_obj", movingOpOfObj, ConversionUtil::setToString); + writer.write("\n"); } } } -- GitLab