From 17da7eb201321c421043f50a1474add076838875 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, 15 Aug 2019 10:51:58 +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=BE=20=D0=BD=D0=B5=D1=81=D0=BA=D0=BE=D0=BB=D1=8C=D0=BA?= =?UTF-8?q?=D0=BE=20=D0=BE=D0=BF=D1=82=D0=B8=D0=BC=D0=B8=D0=B7=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B9=20=D0=B8=D0=B7=20conversion=5F2.mzn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constraints/conversion_2_greedy_v2.mzn | 90 ++++++++++++++++++- ...ersion_2_with_partial_cargo_operations.mzn | 90 +++++++++++++++++++ 2 files changed, 179 insertions(+), 1 deletion(-) diff --git a/src/constraints/conversion_2_greedy_v2.mzn b/src/constraints/conversion_2_greedy_v2.mzn index 8e640d3..ae7b8ed 100644 --- a/src/constraints/conversion_2_greedy_v2.mzn +++ b/src/constraints/conversion_2_greedy_v2.mzn @@ -82,6 +82,7 @@ array [0..n_moving_obj, 0..n_operations] of bool : moving_op_of_obj; ); array [1..n_locations] of 0..n_locations : twin_location = [i - 1 + (i mod 2) * 2 | i in 1..n_locations]; +array [1..n_locations] of 1..n_locations : main_location = [i - ((i + 1) mod 2)| i in 1..n_locations]; array [0..n_operations] of 0..n_locations : operations_destination; % Локация в которой окажется объект после завершения операции. @@ -637,13 +638,100 @@ 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_all_storage_sections, 1..n_locations] of int : min_positive_cargo_val; % Объём максимальной положительной операции, которая может быть произведена с этой секцией в этом хранилище. Если в локации таковой нет, то это значение объёма хранилища + 1. array [1..n_all_storage_sections, 1..n_locations] of int : max_negative_cargo_val; array [1..n_moving_obj, 1..n_locations] of bool : can_obj_leave_loc_only_alone; array [1..n_moving_obj, 1..n_locations, 1..n_intervals] of bool : is_fixed_op_planned_in_future; + array [0..n_moving_obj, 0..(n_intervals + 1)] of var bool : can_obj_theoretically_use_cargo_op; + % Определение can_obj_theoretically_use_cargo_op. + constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( + can_obj_theoretically_use_cargo_op[obj, t] = ( + is_sections_of_moving_obj_empty[obj] + \/ + exists (section in sections_of_moving_obj[obj]) ( + (storage_used_volume[section, t - 1] + min_positive_cargo_val[section, main_location[m_obj_loc[obj, t]]] <= max_storage_vol[section]) + \/ (storage_used_volume[section, t - 1] + max_negative_cargo_val[section, main_location[m_obj_loc[obj, t]]] >= 0) + ) + ) + ); + constraint forall (t in 0..(n_intervals + 1)) (can_obj_theoretically_use_cargo_op[0, t] = false); + constraint forall (obj in 1..n_moving_obj) (can_obj_theoretically_use_cargo_op[obj, 0] = false); + + % Остановился ли объект окончательно, начиная с данного интервала. + array [0..n_moving_obj, 0..(n_intervals + 1)] of var bool : is_obj_totally_terminated; + constraint forall (obj in 1..n_moving_obj) (is_obj_totally_terminated[obj, n_intervals + 1] = true); + constraint forall (t in 0..(n_intervals + 1)) (is_obj_totally_terminated[0, t] = true); + + constraint forall (obj in 1..n_moving_obj, t in 0..n_intervals) ( + is_obj_totally_terminated[obj, t] = ( + (current_moving_operation[obj, t] = 0) + /\ (not is_involved_in_cargo_op[obj, t]) + /\ (is_obj_totally_terminated[obj, t + 1]) + ) + ); + + % Само ограничение. + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( + ( (can_obj_leave_loc_only_alone[obj, m_obj_loc[obj, t]]) + /\ (not can_obj_theoretically_use_cargo_op[obj, t]) + /\ (not is_fixed_op_planned_in_future[obj, m_obj_loc[obj, t], t]) + ) -> + (is_obj_totally_terminated[obj, t] \/ (current_moving_operation[obj, t] != 0)) + ); + % Критерий оптимизации array [1..(n_intervals + 1)] of var bool : is_not_terminated; % В конце всё остановится. diff --git a/src/constraints/conversion_2_with_partial_cargo_operations.mzn b/src/constraints/conversion_2_with_partial_cargo_operations.mzn index 8d7d8c8..f110cee 100644 --- a/src/constraints/conversion_2_with_partial_cargo_operations.mzn +++ b/src/constraints/conversion_2_with_partial_cargo_operations.mzn @@ -81,6 +81,7 @@ array [0..n_moving_obj, 0..n_operations] of bool : moving_op_of_obj; ); array [1..n_locations] of 0..n_locations : twin_location = [i - 1 + (i mod 2) * 2 | i in 1..n_locations]; +array [1..n_locations] of 1..n_locations : main_location = [i - ((i + 1) mod 2)| i in 1..n_locations]; array [0..n_operations] of 0..n_locations : operations_destination; % Локация в которой окажется объект после завершения операции. @@ -499,12 +500,101 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац ) ); +% Оптимизация - судно возвращается откуда перед этим пришло -> оно сделало или делает что-то "полезное". + 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_all_storage_sections, 1..n_locations] of int : min_positive_cargo_val; % Объём максимальной положительной операции, которая может быть произведена с этой секцией в этом хранилище. Если в локации таковой нет, то это значение объёма хранилища + 1. array [1..n_all_storage_sections, 1..n_locations] of int : max_negative_cargo_val; array [1..n_moving_obj, 1..n_locations] of bool : can_obj_leave_loc_only_alone; array [1..n_moving_obj, 1..n_locations, 1..n_intervals] of bool : is_fixed_op_planned_in_future; + array [0..n_moving_obj, 0..(n_intervals + 1)] of var bool : can_obj_theoretically_use_cargo_op; + % Определение can_obj_theoretically_use_cargo_op. + constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( + can_obj_theoretically_use_cargo_op[obj, t] = ( + is_sections_of_moving_obj_empty[obj] + \/ + exists (section in sections_of_moving_obj[obj]) ( + (storage_used_volume[section, t - 1] + min_positive_cargo_val[section, main_location[m_obj_loc[obj, t]]] <= max_storage_vol[section]) + \/ (storage_used_volume[section, t - 1] + max_negative_cargo_val[section, main_location[m_obj_loc[obj, t]]] >= 0) + ) + ) + ); + constraint forall (t in 0..(n_intervals + 1)) (can_obj_theoretically_use_cargo_op[0, t] = false); + constraint forall (obj in 1..n_moving_obj) (can_obj_theoretically_use_cargo_op[obj, 0] = false); + + % Остановился ли объект окончательно, начиная с данного интервала. + array [0..n_moving_obj, 0..(n_intervals + 1)] of var bool : is_obj_totally_terminated; + constraint forall (obj in 1..n_moving_obj) (is_obj_totally_terminated[obj, n_intervals + 1] = true); + constraint forall (t in 0..(n_intervals + 1)) (is_obj_totally_terminated[0, t] = true); + + constraint forall (obj in 1..n_moving_obj, t in 0..n_intervals) ( + is_obj_totally_terminated[obj, t] = ( + (current_moving_operation[obj, t] = 0) + /\ (not is_involved_in_cargo_op[obj, t]) + /\ (is_obj_totally_terminated[obj, t + 1]) + ) + ); + + % Само ограничение. + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( + ( (can_obj_leave_loc_only_alone[obj, m_obj_loc[obj, t]]) + /\ (not can_obj_theoretically_use_cargo_op[obj, t]) + /\ (not is_fixed_op_planned_in_future[obj, m_obj_loc[obj, t], t]) + ) -> + (is_obj_totally_terminated[obj, t] \/ (current_moving_operation[obj, t] != 0)) + ); + + % Критерий оптимизации array [1..(n_intervals + 1)] of var bool : is_not_terminated; % В конце всё остановится. -- GitLab