diff --git a/src/constraints/conversion_2.mzn b/src/constraints/conversion_2.mzn index 2ef635f48d661136442bdfec3e87a74e558d014b..5a9344392c9a388efa6d7996fc02d9abec7a1de5 100644 --- a/src/constraints/conversion_2.mzn +++ b/src/constraints/conversion_2.mzn @@ -336,11 +336,15 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац int : n_loading_op; array [0..n_operations] of int : loading_op_delta_of_main_obj; + array [0..n_operations] of int : loading_op_abs_delta; + array [0..n_operations] of {1, -1} : loading_op_direction; + array [0..n_operations] of 1..n_obj_with_storage : operations_main_stor; array [0..n_operations] of 1..n_obj_with_storage : operations_secondary_stor; array [0..n_operations] of 1..n_cargo_types : operations_cargo_t; array [1..n_loading_op] of int : loading_op_delta; + array [1..n_loading_op] of {1, -1} : loading_op_local_direction; array [1..n_loading_op] of 1..n_operations : loading_op_n; % Номера среди общего списка операций. array [1..n_obj_with_storage, 1..n_cargo_types] of set of 1..n_loading_op : involved_operations; diff --git a/src/constraints/conversion_2_with_partial_cargo_operations.mzn b/src/constraints/conversion_2_with_partial_cargo_operations.mzn new file mode 100644 index 0000000000000000000000000000000000000000..97a188889a3260535ea1190bd5e036de9b74429e --- /dev/null +++ b/src/constraints/conversion_2_with_partial_cargo_operations.mzn @@ -0,0 +1,531 @@ +include "globals.mzn"; + +int : n_intervals; +int : n_operations; +int : n_locations; +int : n_moving_obj; + +array [0..n_operations, 0..(n_intervals + 1)] of var bool : op_status; +array [0..n_operations, 0..(n_intervals + 1)] of var bool : op_start; + +constraint forall (t in 0..(n_intervals + 1)) (op_status[0, t] = false); % Фиктивная операция. +constraint forall (t in 0..(n_intervals + 1)) ( op_start[0, t] = false); % Фиктивная операция. + +array [0..n_moving_obj, 0..n_operations] of bool : moving_op_of_obj; + +% Определение current_moving_operation. + % Текущая операция операция перемещения, в которой задействован данный объект. + array [0..n_moving_obj, 0..(n_intervals + 1)] of var 0..n_operations : current_moving_operation; + + constraint forall (t in 0..(n_intervals + 1)) (current_moving_operation[0, t] = 0); % Фиктивный объект. + + % Крайние значения. + constraint forall (obj in 1..n_moving_obj, t in {0, n_intervals + 1}) ( + current_moving_operation[obj, t] = 0 + ); + + % Текущая операция лежит в множестве тех, которые затрагивают данный объект. + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( + (current_moving_operation[obj, t] != 0) -> moving_op_of_obj[obj, current_moving_operation[obj, t]] + ); + % Если операция, затрагивающая данный объект в качестве главного, выполняется - то именно она текущая операция перемещения для этого объекта. + constraint forall (op in 1..n_operations, t in 1..n_intervals where is_moving_operation[op]) ( + op_status[op, t] -> (current_moving_operation[main_obj_of_operation[op], t] = op) + ); + % Связь current_moving_operation c op_status. + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( + (current_moving_operation[obj, t] != 0) -> (op_status[current_moving_operation[obj, t], t]) + ); + +% Определение current_moored_obj. + % Объект, пришвартованный к данной локации. + array [0..n_locations, 0..(n_intervals + 1)] of var 0..n_moving_obj : current_moored_obj; + + constraint forall (t in 0..(n_intervals + 1)) (current_moored_obj[0, t] = 0); % Фиктивная локация. + + % Фиксирование неиспользуемых значений. + constraint forall (loc in 1..n_locations, t in 0..(n_intervals + 1) where loc mod 2 = 1) ( + current_moored_obj[loc, t] = 0 + ); + + % Крайние значения. + constraint forall (loc in 1..n_locations, t in {0, n_intervals + 1}) ( + current_moored_obj[loc, t] = 0 + ); + + % Операции с условной швартовкой. + int : op_with_nominally_mooring_max_size; + array [0..n_locations, 0..n_moving_obj] of 0..op_with_nominally_mooring_max_size : op_with_nominally_mooring_sizes; + array [0..n_locations, 0..n_moving_obj, 1..op_with_nominally_mooring_max_size] of 1..n_operations : op_with_nominally_mooring; + + % current_moored_obj соответствуе какому-либо реально пришвартованному объекту. + constraint forall (loc in 1..n_locations, t in 1..n_intervals, obj = current_moored_obj[loc, t] + where loc mod 2 = 0) ( + (obj != 0) -> ((m_obj_loc[obj, t] = loc) \/ + (exists (op in [op_with_nominally_mooring[loc, obj, id] | id in 1..op_with_nominally_mooring_sizes[loc, obj]]) + (op_status[op, t])) + ) + ); + + % Если объект пришвартован или швартуется, то current_moored_obj об это знает. + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals, loc = m_obj_loc[obj, t]) ( + (loc mod 2 = 0) -> (current_moored_obj[loc, t] = obj) + ); + + % Если выполняется операция, где судно условно пришвартовано, то current_moored_obj знает об этом. + constraint forall (loc in 1..n_locations, + obj in 1..n_moving_obj, + op in [op_with_nominally_mooring[loc, obj, id] | id in 1..op_with_nominally_mooring_sizes[loc, obj]], + t in 1..n_intervals) ( + op_status[op, t] -> (current_moored_obj[loc, t] = obj) + ); + +array [1..n_locations] of 0..n_locations : twin_location = [i - 1 + (i mod 2) * 2 | i in 1..n_locations]; +% TODO нумерация с нуля + +array [0..n_operations] of 0..n_locations : operations_destination; % Локация в которой окажется объект после завершения операции. + +% Определение m_obj_loc. + % Местоположение объекта или пункт назначения (если объект движется) перед началом определённого интервала. + array [0..n_moving_obj, 0..(n_intervals + 1)] of var 0..n_locations : m_obj_loc; + + constraint forall (t in 0..(n_intervals + 1)) (m_obj_loc[0, t] = 0); % Фиктивный объект. + + % Главный объект (субъект) операции. + array [0..n_operations] of 0..n_moving_obj : main_obj_of_operation; + + % Является ли операция швартовкой/отшвартовкой. + array [0..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] + ); + + % Направление движения/местоположение объекта может измениться только если перед этим началась операция перемещения, и он не вспомогательный при операции швартовки. + 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[current_moving_operation[obj, t - 1]]) + \/ + (not is_mooring_op[current_moving_operation[obj, t - 1]]) + ) + ) -> (m_obj_loc[obj, t] = operations_destination[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[current_moving_operation[obj, t - 1]]) + /\ + ( is_mooring_op[current_moving_operation[obj, t - 1]]) + ) + ) -> (m_obj_loc[obj, t] = m_obj_loc[obj, t - 1]) + ); + +% Начальное состояние. + array [0..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 [0..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]) + ); + +% Определение op_status, op_start. + constraint forall (i in 1..n_operations, j in {0, n_intervals + 1}) (op_status[i, j] == 0); % Краевые значения. + + constraint forall (op in 1..n_operations, j in {0, n_intervals + 1}) (op_start[op, j] = false); + constraint forall (i in 1..n_operations, j in 1..(n_intervals + 1)) (op_start[i, j] = (op_status[i, j] /\ not op_status[i, j - 1])); + +% Связь ресурсов с операцией и основным объектом. + % Операции, которые могут задействовать данный объект как ресурс. + array [0..n_moving_obj] of set of 1..n_operations : operations_that_used_obj_as_resource; + + % Является ли данная операция операцией перемещения. + array [0..n_operations] of bool : is_moving_operation; + + % Операция, в которой участвует данный объект как ресурс. + array [0..n_moving_obj, 0..(n_intervals + 1)] of var 0..n_operations : participation_as_resource; + + constraint forall (t in 0..(n_intervals + 1)) (participation_as_resource[0, t] = 0); % Фиктивный объект. + + % Граничные значения. + constraint forall (obj in 1..n_moving_obj) (participation_as_resource[obj, 0] = 0); + constraint forall (obj in 1..n_moving_obj) (participation_as_resource[obj, n_intervals + 1] = 0); + + % Только те операции, которые затрагивают данный объект. + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( + (participation_as_resource[obj, t] != 0) + -> participation_as_resource[obj, t] in operations_that_used_obj_as_resource[obj] + ); + + % Связь с текущими операциями перемещения. + % Если объект задействован в операции перемещения, которая использует его как ресурс, + % то participation_as_resource должен указывать на эту операцию. + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( + (current_moving_operation[obj, t] in operations_that_used_obj_as_resource[obj]) + -> + (participation_as_resource[obj, t] = current_moving_operation[obj, t]) + ); + % Если объект участвует как ресурс в операции перемещения, то это согласованно с current_moving_operation. + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( + ((participation_as_resource[obj, t] != 0) /\ + (is_moving_operation[participation_as_resource[obj, t]]) + ) -> (participation_as_resource[obj, t] = current_moving_operation[obj, t]) + ); + + % { Объект участвует где-то в качестве ресурса - соответствующая операция обязана быть активной. } + 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)) ( + ((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]) + ); + + int : n_resources_types; % Количество различных типов ресурсов. + array [1..n_resources_types] of set of 1..n_moving_obj : objects_of_type; % Все объекты конкретного типа. + + int : n_resources_counters; % Количество счётчиков ресурсов. + % Счётчик ресурсов. + array [1..n_resources_counters , 1..n_intervals] of var int : resources_counter; + array [1..n_resources_counters] of 1..n_resources_types : counter_type; % Типы ресурсов, за которыми следят счётчики. + array [1..n_resources_counters] of 1..n_operations : operation_of_counter; % Операция, которой принадлежит данный счётчик. + array [1..n_resources_counters] of int : required_counter_values; % Необходимые значения на счётчиках ресурсов для выполнения операции. + array [0..n_operations] of set of 1..n_resources_counters : counters_of_operation; % Счётчики, которые относятся к данной операции. + + % Участие всех необходимых ресурсов в операции. + constraint forall (t in 1..n_intervals, op in 1..n_operations, counter in counters_of_operation[op]) ( + op_status[op, t] -> (resources_counter[counter, t] = required_counter_values[counter]) + ); + + % Определение 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, t] = operation_of_counter[counter] + ) + ); + +% Участие объекта в операциях грузообработки. + array [0..n_moving_obj, 1..n_intervals] of var bool : is_involved_in_cargo_op; + + constraint forall (t in 1..n_intervals) (is_involved_in_cargo_op[0, t] = false); % Фиктивный объект. + + % Операции погрузки, которые используют этот объект в качестве главного или в качестве бункеровщика. + array [0..n_moving_obj] of set of 0..n_operations : related_cargo_op; + + % TODO узнать про where + % Определение is_involved_in_cargo_op. + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( + is_involved_in_cargo_op[obj, t] = ( + % (exists (op in 1..n_operations where (not is_moving_operation[op]) /\ (main_obj_of_operation[op] = obj)) ( + (exists (op in related_cargo_op[obj]) (op_status[op, t])) + \/ + ((participation_as_resource[obj, t] != 0) /\ (not is_moving_operation[participation_as_resource[obj, t]])) + ) + ); + % Операции перемещения исключают операции грузообработки и наоборот. + constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( + is_involved_in_cargo_op[obj, t] -> (current_moving_operation[obj, t] = 0) + ); + +% Наличие всех объектов на месте во время начала операции перемещения + готовность к началу. + % Требуемое положение конкретных типов объектов в момент начала операций. + array [1..n_resources_counters] of 1..n_locations : operations_resources_start_loc; + + % Наличие на месте всех ресурсов. + constraint forall ( + op in 1..n_operations, + t in 1..n_intervals, + counter in counters_of_operation[op], + 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]) + ); + + % Требуемое положение главного объекта в момент начала операций. + array [0..n_operations] of 0..n_locations : main_obj_start_loc; + % Требуемое положение бункеровщика в момент начала операции. + array [0..n_operations] of 0..n_locations : bunker_start_loc; + + % Бункеровщик, участвующий в операции погрузки (0, если такогого нет или это не погрузка). + array [0..n_operations] of 0..n_moving_obj : bunker_of_cargo_op; + + % Наличие главных объектов на месте. + 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]) + ); + + % Наличие бункеровщиков на месте. + constraint forall (op in 1..n_operations, + t in 1..n_intervals, + obj = bunker_of_cargo_op[op] where obj != 0) ( + op_start[op, t] -> (m_obj_loc[obj, t] == bunker_start_loc[op]) + ); + +% Непрерывность перемещения и швартовки. + array [0..n_operations] of int : operations_duration; + array [0..n_operations] of bool : is_continuous_operation; + + 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])) + /\ + (not op_status[i, j + len]) + ) + )) /\ + (forall (j in (n_intervals - len + 2)..(n_intervals + 1)) (op_start[i, j] == false)) + ); + +% Конфликтующие операции. + array [0..n_operations] of set of 1..n_operations : conflicting_operations; + + constraint forall (op in 1..n_operations, t in 0..(n_intervals + 1), conf_op in conflicting_operations[op]) ( + op_status[op, t] -> not op_status[conf_op, t] + ); + +% Окна непогоды. + array [0..n_operations, 0..n_intervals] of bool : bad_weather; + + constraint forall (op in 1..n_operations, t in 1..n_intervals) ( + bad_weather[op, t] -> (op_status[op, t] = false) + ); + +% Грузообработка. + int : n_cargo_types; + int : n_obj_with_storage; + array [0..n_obj_with_storage, 0..(n_intervals + 1), 1..n_cargo_types] of var int : storage_used_volume; % Первые n_moving_obj соответствуют наполненности соответствующих движущихся объектов. + + constraint forall (t in 0..(n_intervals + 1), cargo in 1..n_cargo_types) (storage_used_volume[0, t, cargo] = 0); % Фиктивный объект. + + % Ограничения на вместимость. + array [0..n_obj_with_storage] of int : max_storage_vol; + % Максимальный объём. + constraint forall (storage in 1..n_obj_with_storage, t in 0..(n_intervals + 1)) ( + sum (cargo in 1..n_cargo_types) (storage_used_volume[storage, t, cargo]) <= max_storage_vol[storage] + ); + % Неотрицательность объёма. + constraint forall (storage in 1..n_obj_with_storage, t in 0..(n_intervals + 1), cargo in 1..n_cargo_types) ( + 0 <= storage_used_volume[storage, t, cargo] + ); + + % Ограничения на граничные значения. + array [0..n_obj_with_storage, 0..n_cargo_types] of int : initial_storage_vol; + array [0..n_obj_with_storage, 0..n_cargo_types] of int : final_storage_vol; + + constraint forall (storage in 1..n_obj_with_storage, cargo in 1..n_cargo_types) ( % Initial values. + storage_used_volume[storage, 0, cargo] = initial_storage_vol[storage, cargo] + ); + + constraint forall (storage in 1..n_obj_with_storage, cargo in 1..n_cargo_types % Final values. + where final_storage_vol[storage, cargo] >= 0) ( + storage_used_volume[storage, n_intervals + 1, cargo] = final_storage_vol[storage, cargo] + ); + + % Изменение грузов в хранилищах. + array [0..n_obj_with_storage, 0..(n_intervals + 1), 1..n_cargo_types] of int : cargo_flows; + + int : n_loading_op; + + array [0..n_operations] of int : loading_op_delta_of_main_obj; + array [0..n_operations] of int : loading_op_abs_delta; + array [0..n_operations] of {1, -1} : loading_op_direction; + + array [0..n_operations] of 1..n_obj_with_storage : operations_main_stor; + array [0..n_operations] of 1..n_obj_with_storage : operations_secondary_stor; + array [0..n_operations] of 1..n_cargo_types : operations_cargo_t; + + array [1..n_loading_op] of int : loading_op_delta; + array [1..n_loading_op] of {1, -1} : loading_op_local_direction; + array [1..n_loading_op] of 1..n_operations : loading_op_n; % Номера среди общего списка операций. + + array [1..n_obj_with_storage, 1..n_cargo_types] of set of 1..n_loading_op : involved_operations; + + % Интенсивность операций погрузки. + array [0..n_operations, 0..(n_intervals + 1)] of var int : cargo_op_intensity; + + constraint forall (t in 0..(n_intervals + 1)) (cargo_op_intensity[0, t] = 0); % Фиктивная операция. + + constraint forall (op in 1..n_operations, t in 0..(n_intervals + 1)) (cargo_op_intensity[op, t] >= 0); + constraint forall (op in 1..n_operations, t in 0..(n_intervals + 1)) (cargo_op_intensity[op, t] <= loading_op_abs_delta[op]); + + % Связь с операциями грузообработки. + constraint forall (op in 1..n_operations, t in 0..(n_intervals + 1) where not is_moving_operation[op]) ( + (cargo_op_intensity[op, t] > 0) -> op_status[op, t] + ); + constraint forall (op in 1..n_operations, t in 0..(n_intervals + 1) where is_moving_operation[op]) ( + cargo_op_intensity[op, t] = 0 + ); + constraint forall (op in 1..n_operations, t in 0..(n_intervals + 1) where not is_moving_operation[op]) ( + op_status[op, t] -> (cargo_op_intensity[op, t] > 0) + ); +/* + constraint forall (storage in 1..n_obj_with_storage, cargo in 1..n_cargo_types, t in 1..(n_intervals + 1)) ( + storage_used_volume[storage, t, cargo] = ( + storage_used_volume[storage, t - 1, cargo] + + cargo_flows[storage, t, cargo] + + sum (inv_op in involved_operations[storage, cargo]) ( + loading_op_delta[inv_op] * + op_status[loading_op_n[inv_op], t] + ) + ) + ); +*/ + constraint forall (storage in 1..n_obj_with_storage, cargo in 1..n_cargo_types, t in 1..(n_intervals + 1)) ( + storage_used_volume[storage, t, cargo] = ( + storage_used_volume[storage, t - 1, cargo] + + cargo_flows[storage, t, cargo] + + sum (inv_op in involved_operations[storage, cargo]) ( + cargo_op_intensity[loading_op_n[inv_op], t] * + loading_op_local_direction[inv_op] + ) + ) + ); + + +% Фиксированные операции. + int : n_fixed_op; + array [1..n_fixed_op] of 1..n_operations : fixed_op; + array [1..n_fixed_op] of set of 1..n_moving_obj : fixed_op_resources; + array [1..n_fixed_op] of 1..n_intervals : fixed_op_start; + array [1..n_fixed_op] of 1..n_intervals : fixed_op_end; % Включительно. + + array [0..n_operations, 0..n_intervals] of bool : is_fixed; + + constraint forall (no in 1..n_fixed_op, op = fixed_op[no]) ( + forall (t in fixed_op_start[no]..fixed_op_end[no]) ( + (op_status[op, t]) /\ + forall (obj in fixed_op_resources[no]) ( + participation_as_resource[obj, t] = op + ) + ) + ); + +% Оптимизация - сдвиг в начало. + % Возможно ли начать операцию в данный интервал (если предположить, что операция длится 1 интервал). + array [0..n_operations, 1..n_intervals] of var bool : is_op_possible; + + constraint forall (t in 1..n_intervals) (is_op_possible[0, t] = false); % Фиктивный объект. + + % Счётчик ресурсов, которые могут быть потенциально задействованы в операции. + array [1..n_resources_counters , 1..n_intervals] of var int : possible_resources_counter; + + % Определение possible_resources_counter. + constraint forall (counter in 1..n_resources_counters, t in 1..n_intervals) ( + possible_resources_counter[counter, t] = sum (obj in objects_of_type[counter_type[counter]]) ( + (participation_as_resource[obj, t] = 0) /\ + (current_moving_operation[obj, t] = 0) /\ + (m_obj_loc[obj, t] = operations_resources_start_loc[counter]) + ) + ); + + % Достаточно ли свободных ресурсов для операции. + array [0..n_operations, 1..n_intervals] of var bool : is_enough_free_resources; + + constraint forall (t in 1..n_intervals) (is_enough_free_resources[0, t] = false); % Фиктивный объект. + + constraint forall (op in 1..n_operations, t in 1..n_intervals) ( + is_enough_free_resources[op, t] = forall (counter in counters_of_operation[op]) ( + possible_resources_counter[counter, t] >= required_counter_values[counter] + ) + ); + + % Определение is_op_possible. + constraint forall (op in 1..n_operations, t in 1..n_intervals) ( + is_op_possible[op, t] = ( + (bad_weather[op, t] = false) /\ % Погода не мешает. + (m_obj_loc[main_obj_of_operation[op], t] = main_obj_start_loc[op]) + /\ % Главный объект на месте. + (current_moving_operation[main_obj_of_operation[op], t] = 0) + /\ % Главный объект не участвует в операции перемещеня. + (is_enough_free_resources[op, t] = true) /\ % Достаточно свободных ресурсов на нужном месте. + (forall (conf_op in conflicting_operations[op]) (op_status[op, t] = false)) + /\ % Не выполняется ни одной конфликтующей операции. + (is_moving_operation[op] -> not is_involved_in_cargo_op[main_obj_of_operation[op], t]) + /\ % Если это операция перемещения, то главный объект + % не участвует в операциях погрузки. + ((is_mooring_op[op] /\ (operations_destination[op] mod 2 = 0)) -> ( + current_moored_obj[operations_destination[op], t] = 0) + ) /\ % Если это операция пришвартовки, то в этот интервал + % причал должен быть свободным. + ((not is_moving_operation[op]) -> ( + let {1..n_obj_with_storage : m_stor = operations_main_stor[op]; + 1..n_obj_with_storage : s_stor = operations_secondary_stor[op]; + 1..n_cargo_types : cargo = operations_cargo_t[op]; + int : delta = loading_op_delta_of_main_obj[op]; + } in + (storage_used_volume[m_stor, t, cargo] + delta >= 0) /\ + ((sum (c in 1..n_cargo_types) (storage_used_volume[m_stor, t, cargo])) + delta <= max_storage_vol[m_stor]) /\ + (storage_used_volume[s_stor, t, cargo] - delta >= 0) /\ + ((sum (c in 1..n_cargo_types) (storage_used_volume[s_stor, t, cargo])) - delta <= max_storage_vol[s_stor]) + )) /\ % Если это операция грузообработки, то она не выведет + % объём берегового хранилища и хранилища судна за + % границы дозволенного. + (((not is_moving_operation[op]) /\ (main_obj_start_loc[op] mod 2 = 1)) -> + ((current_moored_obj[twin_location[main_obj_start_loc[op]], t] = 0) /\ + (current_moored_obj[twin_location[main_obj_start_loc[op]], t] = main_obj_of_operation[op])) + ) /\ % Если это операция грузообработки без пришвартовки, + % то причал должен быть свободен в этот интервал, либо + % главный объект должен быть уже условно пришвартован. + (((bunker_of_cargo_op[op] != 0) /\ (op_status[op, t])) -> + ((m_obj_loc[bunker_of_cargo_op[op], t] = bunker_start_loc[op]) /\ + (current_moving_operation[bunker_of_cargo_op[op], t] = 0)) + ) % Бункеровщик (если есть) находится в нужной локации + % и не участвует в операциях перемещения. + ) + ); +/* + % Сам критерий оптимизации - если если операцию можно было начать на 1 интервал раньше, то её нужно начать раньше. + constraint forall (op in 1..n_operations, t in 2..n_intervals) ( + (op_start[op, t] /\ (not is_fixed[op, t])) -> not is_op_possible[op, t - 1] + ); +*/ +% Критерий оптимизации + array [1..(n_intervals + 1)] of var bool : is_not_terminated; + % В конце всё остановится. + constraint (is_not_terminated[n_intervals + 1] == false); + + % Действия ещё не остановились, если в текущий интервал что-нибудь происходит или они не остановятся в следующий интервал. + constraint forall (t in 1..n_intervals) ( + is_not_terminated[t] == ( + (exists (op in 1..n_operations) (op_status[op, t])) + \/ + is_not_terminated[t + 1] + ) + ); + + solve minimize sum(is_not_terminated); + +output [show(sum(is_not_terminated)), "\n", + "op_status = ", show(op_status), "\n\n", + "m_obj_loc = ", show(m_obj_loc), "\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", + "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", + + "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", + "cargo_op_intensity = ", show(cargo_op_intensity), "\n\n", + +/* + "is_op_possible {", show(n_intervals), "} = ", show(is_op_possible), "\n\n", + "debug_1 {", show(n_intervals), "} = ", show(debug_1), "\n\n", + "is_enough_free_resources {", show(n_intervals), "} = ", show(is_enough_free_resources), "\n\n", + "operation_of_counter {", show(n_resources_counters), "} = ", show(operation_of_counter), "\n\n", + "possible_resources_counter {", show(n_intervals), "} = ", show(possible_resources_counter), "\n\n", +*/ + ""]; diff --git a/src/inport/ConversionUtil.java b/src/inport/ConversionUtil.java index 215e01c887369ba3d8e8e50fce64f695b44f0147..f53db0a158bb9ca0d1dd565593140774cb4cb1d2 100644 --- a/src/inport/ConversionUtil.java +++ b/src/inport/ConversionUtil.java @@ -795,15 +795,19 @@ public class ConversionUtil { private void cargoOperations() throws IOException { ArrayList>> involvedOperations = new ArrayList<>(); ArrayList loadingOpDelta = new ArrayList<>(); + ArrayList loading_op_local_direction = new ArrayList<>(); ArrayList loadingOpN = new ArrayList<>(); ArrayList loading_op_delta_of_main_obj = new ArrayList<>(); + ArrayList loading_op_abs_delta = new ArrayList<>(); + ArrayList loading_op_direction = new ArrayList<>(); + + ArrayList operations_main_stor = new ArrayList<>(); ArrayList operations_secondary_stor = new ArrayList<>(); ArrayList operations_cargo_t = new ArrayList<>(); ArrayList bunker_of_cargo_op = new ArrayList<>(); - ArrayList is_bunker_required = new ArrayList<>(); for (int i = 0; i < nObjWithStorage; i++) { involvedOperations.add(new ArrayList<>()); @@ -826,20 +830,28 @@ public class ConversionUtil { int cargoN = cargoNById.get(op.getCargo().getId()); loadingOpDelta.add(-(int)op.getIntensity()); + loading_op_local_direction.add(-(int)op.getIntensity() > 0 ? 1 : -1); loadingOpN.add(i); involvedOperations.get(storageN).get(cargoN).add(loadingOpDelta.size()); loadingOpDelta.add((int)op.getIntensity()); + loading_op_local_direction.add( (int)op.getIntensity() > 0 ? 1 : -1); loadingOpN.add(i); involvedOperations.get(shipN).get(cargoN).add(loadingOpDelta.size()); loading_op_delta_of_main_obj.add((int)op.getIntensity()); + loading_op_abs_delta.add(Math.abs((int)op.getIntensity())); + loading_op_direction.add((int)op.getIntensity() > 0 ? 1 : -1); + operations_main_stor.add(shipN + 1); operations_secondary_stor.add(storageN + 1); operations_cargo_t.add(cargoN + 1); bunker_of_cargo_op.add(op.getBunker().isPresent() ? mObjToN(op.getBunker().get()) + 1 : 0); } else { loading_op_delta_of_main_obj.add(0); + loading_op_abs_delta.add(0); + loading_op_direction.add(1); + operations_main_stor.add(1); operations_secondary_stor.add(1); operations_cargo_t.add(1); @@ -853,9 +865,13 @@ public class ConversionUtil { write2DArrayOfSetAs3DArray(writer, "involved_operations", involvedOperations); } writeArray(writer, "loading_op_delta", loadingOpDelta); + writeArray(writer, "loading_op_local_direction", loading_op_local_direction); writeArray(writer, "loading_op_n", loadingOpN, (Integer i) -> i + 1); writeArray(writer, "loading_op_delta_of_main_obj", loading_op_delta_of_main_obj, Optional.of(0)); + writeArray(writer, "loading_op_abs_delta", loading_op_abs_delta, Optional.of(0)); + writeArray(writer, "loading_op_direction", loading_op_direction, Optional.of(1)); + writeArray(writer, "operations_main_stor", operations_main_stor, Optional.of(1)); writeArray(writer, "operations_secondary_stor", operations_secondary_stor, Optional.of(1)); writeArray(writer, "operations_cargo_t", operations_cargo_t, Optional.of(1));