Commit df752fb2 authored by Vladislav Kiselev's avatar Vladislav Kiselev

Операции грузообрабртки теперь могут быть не целыми.

parent dda622ab
...@@ -336,11 +336,15 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац ...@@ -336,11 +336,15 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац
int : n_loading_op; int : n_loading_op;
array [0..n_operations] of int : loading_op_delta_of_main_obj; 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_main_stor;
array [0..n_operations] of 1..n_obj_with_storage : operations_secondary_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 [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 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_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 [1..n_obj_with_storage, 1..n_cargo_types] of set of 1..n_loading_op : involved_operations;
......
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",
*/
""];
...@@ -795,15 +795,19 @@ public class ConversionUtil { ...@@ -795,15 +795,19 @@ public class ConversionUtil {
private void cargoOperations() throws IOException { private void cargoOperations() throws IOException {
ArrayList<ArrayList<ArrayList<Integer>>> involvedOperations = new ArrayList<>(); ArrayList<ArrayList<ArrayList<Integer>>> involvedOperations = new ArrayList<>();
ArrayList<Integer> loadingOpDelta = new ArrayList<>(); ArrayList<Integer> loadingOpDelta = new ArrayList<>();
ArrayList<Integer> loading_op_local_direction = new ArrayList<>();
ArrayList<Integer> loadingOpN = new ArrayList<>(); ArrayList<Integer> loadingOpN = new ArrayList<>();
ArrayList<Integer> loading_op_delta_of_main_obj = new ArrayList<>(); ArrayList<Integer> loading_op_delta_of_main_obj = new ArrayList<>();
ArrayList<Integer> loading_op_abs_delta = new ArrayList<>();
ArrayList<Integer> loading_op_direction = new ArrayList<>();
ArrayList<Integer> operations_main_stor = new ArrayList<>(); ArrayList<Integer> operations_main_stor = new ArrayList<>();
ArrayList<Integer> operations_secondary_stor = new ArrayList<>(); ArrayList<Integer> operations_secondary_stor = new ArrayList<>();
ArrayList<Integer> operations_cargo_t = new ArrayList<>(); ArrayList<Integer> operations_cargo_t = new ArrayList<>();
ArrayList<Integer> bunker_of_cargo_op = new ArrayList<>(); ArrayList<Integer> bunker_of_cargo_op = new ArrayList<>();
ArrayList<Boolean> is_bunker_required = new ArrayList<>();
for (int i = 0; i < nObjWithStorage; i++) { for (int i = 0; i < nObjWithStorage; i++) {
involvedOperations.add(new ArrayList<>()); involvedOperations.add(new ArrayList<>());
...@@ -826,20 +830,28 @@ public class ConversionUtil { ...@@ -826,20 +830,28 @@ public class ConversionUtil {
int cargoN = cargoNById.get(op.getCargo().getId()); int cargoN = cargoNById.get(op.getCargo().getId());
loadingOpDelta.add(-(int)op.getIntensity()); loadingOpDelta.add(-(int)op.getIntensity());
loading_op_local_direction.add(-(int)op.getIntensity() > 0 ? 1 : -1);
loadingOpN.add(i); loadingOpN.add(i);
involvedOperations.get(storageN).get(cargoN).add(loadingOpDelta.size()); involvedOperations.get(storageN).get(cargoN).add(loadingOpDelta.size());
loadingOpDelta.add((int)op.getIntensity()); loadingOpDelta.add((int)op.getIntensity());
loading_op_local_direction.add( (int)op.getIntensity() > 0 ? 1 : -1);
loadingOpN.add(i); loadingOpN.add(i);
involvedOperations.get(shipN).get(cargoN).add(loadingOpDelta.size()); involvedOperations.get(shipN).get(cargoN).add(loadingOpDelta.size());
loading_op_delta_of_main_obj.add((int)op.getIntensity()); 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_main_stor.add(shipN + 1);
operations_secondary_stor.add(storageN + 1); operations_secondary_stor.add(storageN + 1);
operations_cargo_t.add(cargoN + 1); operations_cargo_t.add(cargoN + 1);
bunker_of_cargo_op.add(op.getBunker().isPresent() ? mObjToN(op.getBunker().get()) + 1 : 0); bunker_of_cargo_op.add(op.getBunker().isPresent() ? mObjToN(op.getBunker().get()) + 1 : 0);
} else { } else {
loading_op_delta_of_main_obj.add(0); 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_main_stor.add(1);
operations_secondary_stor.add(1); operations_secondary_stor.add(1);
operations_cargo_t.add(1); operations_cargo_t.add(1);
...@@ -853,9 +865,13 @@ public class ConversionUtil { ...@@ -853,9 +865,13 @@ public class ConversionUtil {
write2DArrayOfSetAs3DArray(writer, "involved_operations", involvedOperations); write2DArrayOfSetAs3DArray(writer, "involved_operations", involvedOperations);
} }
writeArray(writer, "loading_op_delta", loadingOpDelta); 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_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_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_main_stor", operations_main_stor, Optional.of(1));
writeArray(writer, "operations_secondary_stor", operations_secondary_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)); writeArray(writer, "operations_cargo_t", operations_cargo_t, Optional.of(1));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment