diff --git a/src/constraints/conversion_2.mzn b/src/constraints/conversion_2.mzn index 90bb8829aea51c9bb4175fa04a686f6a2e29049d..2ef635f48d661136442bdfec3e87a74e558d014b 100644 --- a/src/constraints/conversion_2.mzn +++ b/src/constraints/conversion_2.mzn @@ -5,14 +5,19 @@ int : n_operations; int : n_locations; int : n_moving_obj; -array [1..n_operations, 0..(n_intervals + 1)] of var bool : op_status; -array [1..n_operations, 0..(n_intervals + 1)] of var bool : op_start; +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; -array [1..n_moving_obj, 1..n_operations] of bool : moving_op_of_obj; +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 [1..n_moving_obj, 0..(n_intervals + 1)] of var 0..n_operations : 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}) ( @@ -32,59 +37,62 @@ array [1..n_moving_obj, 1..n_operations] of bool : moving_op_of_obj; (current_moving_operation[obj, t] != 0) -> (op_status[current_moving_operation[obj, t], t]) ); -% Ограничение на количество пришвартованных кораблей. - % Счётчик объектов в локации (только в чётных - в состоянии пришвартованности). - array [1..n_locations, 0..(n_intervals + 1)] of var int : obj_in_loc_counter; - - array [1..n_locations] of 1..n_locations : twin_location = [i - 1 + (i mod 2) * 2 | i in 1..n_locations]; - - % Операции грузообработки, проводимые без пришвартовки на этой локации. - array [1..n_locations] of set of 1..n_operations : related_unmoored_cargo_op; - - % Определение obj_in_loc_counter. - constraint forall (loc in 1..n_locations, t in 0..n_intervals where (loc mod 2) = 0) ( - obj_in_loc_counter[loc, t] = (sum (obj in 1..n_moving_obj) (m_obj_loc[obj, t + 1] = loc)) % Швартовка и нахождение у причала. - + (sum (op in related_unmoored_cargo_op[twin_location[loc]]) (op_status[op, t])) % Погрузка без швартовки. - % + (sum (op in 1..n_operations where ((not is_moving_operation[op]) /\ (main_obj_start_loc[op] = twin_location[loc]))) % Погрузка без швартовки. - % (op_status[op, t]) - % ) % TODO узнать, почему медленнее варианта выше. - + (sum (op in 1..n_operations where (is_mooring_op[op] /\ (main_obj_start_loc[op] = loc))) % Отшвартовка. - (op_status[op, 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) where (loc mod 2) = 0) ( - obj_in_loc_counter[loc, t] <= 1 + % Крайние значения. + constraint forall (loc in 1..n_locations, t in {0, n_intervals + 1}) ( + current_moored_obj[loc, t] = 0 ); -% Определение is_m_obj_in_movement_before_start. - % Находится ли объект в движении перед началом интервала. - array [1..n_moving_obj, 0..(n_intervals + 1)] of var bool : is_m_obj_in_movement_before_start; + % Операции с условной швартовкой. + 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])) + ) + ); - % В начале никто не движется. - constraint forall (obj in 1..n_moving_obj) (not is_m_obj_in_movement_before_start[obj, 0]); - % Перед первым интервалом все тоже стоят на месте. - constraint forall (obj in 1..n_moving_obj) (not is_m_obj_in_movement_before_start[obj, 1]); + % Если объект пришвартован или швартуется, то 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) + ); - % Если в предыдущем интервале объект не движется - то в начале этого он не движется, иначе он движется если предыдущая операция не закончилась. - constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( - (current_moving_operation[obj, t - 1] = 0) - -> is_m_obj_in_movement_before_start[obj, t] = false - ); - constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( - (current_moving_operation[obj, t - 1] != 0) - -> is_m_obj_in_movement_before_start[obj, t] = (current_moving_operation[obj, t - 1] == current_moving_operation[obj, t]) - ); + % Если выполняется операция, где судно условно пришвартовано, то 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_operations] of 1..n_locations : operations_destination; % Локация в которой окажется объект после завершения операции. +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 [1..n_moving_obj, 0..(n_intervals + 1)] of var 1..n_locations : 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 1..n_moving_obj : main_obj_of_operation; + array [0..n_operations] of 0..n_moving_obj : main_obj_of_operation; % Является ли операция швартовкой/отшвартовкой. array [0..n_operations] of bool : is_mooring_op; @@ -115,11 +123,11 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ); % Начальное состояние. - array [1..n_moving_obj] of 0..n_locations : initial_m_obj_loc; + 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 [1..n_moving_obj] of 0..n_locations : final_m_obj_loc; + 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]) @@ -133,13 +141,15 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац % Связь ресурсов с операцией и основным объектом. % Операции, которые могут задействовать данный объект как ресурс. - array [1..n_moving_obj] of set of 1..n_operations : operations_that_used_obj_as_resource; + 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 [1..n_moving_obj, 0..(n_intervals + 1)] of var 0..n_operations : participation_as_resource; + 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); @@ -187,7 +197,7 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац 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 [1..n_operations] of set of 1..n_resources_counters : counters_of_operation; % Счётчики, которые относятся к данной операции. + 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]) ( @@ -202,20 +212,22 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ); % Участие объекта в операциях грузообработки. - array [1..n_moving_obj, 1..n_intervals] of var bool : is_involved_in_cargo_op; + 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 [1..n_moving_obj] of set of 1..n_operations : related_cargo_op_using_obj_as_main; + % Операции погрузки, которые используют этот объект в качестве главного или в качестве бункеровщика. + 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_using_obj_as_main[obj]) ( - op_status[op, t] - )) - \/ - ((participation_as_resource[obj, t] != 0) /\ (not is_moving_operation[participation_as_resource[obj, t]])) + 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) ( @@ -226,35 +238,41 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац % Требуемое положение конкретных типов объектов в момент начала операций. array [1..n_resources_counters] of 1..n_locations : operations_resources_start_loc; - % Требуемое положение главного объекта в момент начала операций. - array [1..n_operations] of 1..n_locations : main_obj_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]) /\ - (not is_m_obj_in_movement_before_start[obj, t]) /\ - ((not is_moving_operation[op]) -> (current_moving_operation[obj, t] = 0)) - ) + ) -> (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]) ); - /* TODO узнать, как ((not is_moving_operation[op]) -> (current_moving_operation[obj, t] = 0)) влияет на производительность - - по идее это не нужно, но на v2-60 без неё гораздо лучше чем с ней. - */ - - % Наличие главных объектов (субъектов) на месте. - 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]) /\ - (not is_m_obj_in_movement_before_start[obj, t]) - ) + + % Наличие бункеровщиков на месте. + 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 [1..n_operations] of int : operations_duration; - array [1..n_operations] of bool : is_continuous_operation; + 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)) ( @@ -268,14 +286,14 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ); % Конфликтующие операции. - array [1..n_operations] of set of 1..n_operations : conflicting_operations; + 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 [1..n_operations, 1..n_intervals] of bool : bad_weather; + 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) @@ -284,10 +302,12 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац % Грузообработка. int : n_cargo_types; int : n_obj_with_storage; - array [1..n_obj_with_storage, 0..(n_intervals + 1), 1..n_cargo_types] of var int : storage_used_volume; % Первые n_moving_obj соответствуют наполненности соответствующих движущихся объектов. + 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 [1..n_obj_with_storage] of int : max_storage_vol; + 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] @@ -298,8 +318,8 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ); % Ограничения на граничные значения. - array [1..n_obj_with_storage, 1..n_cargo_types] of int : initial_storage_vol; - array [1..n_obj_with_storage, 1..n_cargo_types] of int : final_storage_vol; + 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] @@ -311,14 +331,14 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ); % Изменение грузов в хранилищах. - array [1..n_obj_with_storage, 0..(n_intervals + 1), 1..n_cargo_types] of int : cargo_flows; + array [0..n_obj_with_storage, 0..(n_intervals + 1), 1..n_cargo_types] of int : cargo_flows; int : n_loading_op; - array [1..n_operations] of int : loading_op_delta_of_main_obj; - array [1..n_operations] of 1..n_obj_with_storage : operations_main_stor; - array [1..n_operations] of 1..n_obj_with_storage : operations_secondary_stor; - array [1..n_operations] of 1..n_cargo_types : operations_cargo_t; + array [0..n_operations] of int : loading_op_delta_of_main_obj; + 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..n_operations : loading_op_n; % Номера среди общего списка операций. @@ -343,7 +363,7 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац 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 [1..n_operations, 1..n_intervals] of bool : is_fixed; + 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]) ( @@ -356,7 +376,9 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац % Оптимизация - сдвиг в начало. % Возможно ли начать операцию в данный интервал (если предположить, что операция длится 1 интервал). - array [1..n_operations, 1..n_intervals] of var bool : is_op_possible; + 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; @@ -371,7 +393,9 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ); % Достаточно ли свободных ресурсов для операции. - array [1..n_operations, 1..n_intervals] of var bool : is_enough_free_resources; + 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]) ( @@ -379,12 +403,6 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ) ); - array [1..n_operations, 1..n_intervals] of var bool : debug_1; - constraint forall (op in 1..n_operations, t in 1..n_intervals) ( - debug_1[op, t] = - (m_obj_loc[main_obj_of_operation[op], t] = main_obj_start_loc[op]) % Главный объект на месте. - ); - % Определение is_op_possible. constraint forall (op in 1..n_operations, t in 1..n_intervals) ( is_op_possible[op, t] = ( @@ -400,7 +418,7 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац /\ % Если это операция перемещения, то главный объект % не участвует в операциях погрузки. ((is_mooring_op[op] /\ (operations_destination[op] mod 2 = 0)) -> ( - obj_in_loc_counter[operations_destination[op], t] = 0) + current_moored_obj[operations_destination[op], t] = 0) ) /\ % Если это операция пришвартовки, то в этот интервал % причал должен быть свободным. ((not is_moving_operation[op]) -> ( @@ -417,9 +435,16 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац % объём берегового хранилища и хранилища судна за % границы дозволенного. (((not is_moving_operation[op]) /\ (main_obj_start_loc[op] mod 2 = 1)) -> - (obj_in_loc_counter[twin_location[main_obj_start_loc[op]], t] = 0) - ) % Если это операция грузообработки без пришвартовки, - % то причал должен быть свободен в этот интервал. + ((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)) + ) % Бункеровщик (если есть) находится в нужной локации + % и не участвует в операциях перемещения. ) ); @@ -450,13 +475,16 @@ output [show(sum(is_not_terminated)), "\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", - "is_m_obj_in_movement_before_start = ", show(is_m_obj_in_movement_before_start), "\n\n", - "obj_in_loc_counter = ", show(obj_in_loc_counter), "\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", + /* "is_op_possible {", show(n_intervals), "} = ", show(is_op_possible), "\n\n", "debug_1 {", show(n_intervals), "} = ", show(debug_1), "\n\n", diff --git a/src/inport/Bunker.java b/src/inport/Bunker.java index 3be110471fec467ac14e52363b8f4bbe5ffa6fc0..d139204808a964337780f692b514aa883950c6f2 100644 --- a/src/inport/Bunker.java +++ b/src/inport/Bunker.java @@ -8,26 +8,17 @@ package inport; * * @author topazh_ag */ -public class Bunker extends MovingObject { +public class Bunker extends TransportShip { - public Bunker(int id, String name) { - super(id, name); + public Bunker(int id, String name, double cargoMax) { + super(id, name, cargoMax); } public Bunker() { super( ); } - - @Override - public String toString() { - return getId() + ";" + getName(); - } - public Bunker(String s) { super(s); } - - - } diff --git a/src/inport/ConversionUtil.java b/src/inport/ConversionUtil.java index 8f5bd5efb9b98fa73374bbb3b20ead1670fdbc65..215e01c887369ba3d8e8e50fce64f695b44f0147 100644 --- a/src/inport/ConversionUtil.java +++ b/src/inport/ConversionUtil.java @@ -19,10 +19,17 @@ public class ConversionUtil { } } + static private void write2DArrayOfInt(FileWriter writer, + String name, + ArrayList> operations) throws IOException { + locWrite2DArray(writer, name, operations, Object::toString, false); + } + static private void write2DArrayOfInt(FileWriter writer, String name, - ArrayList> operations) throws IOException { - locWrite2DArray(writer, name, operations, Object::toString); + ArrayList> operations, + boolean isNumberedFromZero) throws IOException { + locWrite2DArray(writer, name, operations, Object::toString, isNumberedFromZero); } static private void write2DArrayOfSet(FileWriter writer, @@ -47,39 +54,61 @@ public class ConversionUtil { ); } - static private void write2DArrayOfSetAs3DArray(FileWriter writer, + static private > void write2DArrayOfSetAs3DArray(FileWriter writer, + String name, + ArrayList> operations) throws IOException { + write2DArrayOfSetAs3DArray(writer, name, operations, false); + } + + static private > void write2DArrayOfSetAs3DArray(FileWriter writer, String name, - ArrayList>> operations) throws IOException { + ArrayList> operations, + boolean isNumberedFromZero) throws IOException { int maxSize = 0; ArrayList> sizes = new ArrayList<>(); int dim1 = operations.size(); int dim2 = 0; - for (ArrayList> a1 : operations) { + for (ArrayList a1 : operations) { dim2 = a1.size(); ArrayList locSizes = new ArrayList<>(); - for (ArrayList a2 : a1) { + for (T a2 : a1) { maxSize = Math.max(maxSize, a2.size()); locSizes.add(a2.size()); } sizes.add(locSizes); } writer.write(name + "_max_size = " + maxSize + ";\n"); - write2DArrayOfInt(writer, name + "_sizes", sizes); + write2DArrayOfInt(writer, name + "_sizes", sizes, true); + + { + String firstEl = Integer.toString(isNumberedFromZero ? 0 : 1); + int modifier = isNumberedFromZero ? -1 : 0; + writer.write(name + " = array3d(" + firstEl + ".." + (dim1 + modifier) + + ", " + firstEl + ".." + (dim2 + modifier) + + ", 1.." + name + "_max_size, ["); + } - writer.write(name + " = array3d(1.." + dim1 + ", 1.." + dim2 + ", 1.." + name + "_max_size, ["); boolean isFirst = true; - for (ArrayList> a1 : operations) { - for (ArrayList a2 : a1) { - for (int i = 0; i < maxSize; i++) { + for (ArrayList a1 : operations) { + for (T a2 : a1) { + for (Integer val : a2) { + if (isFirst) { + isFirst = false; + } else { + writer.write(", "); + } + writer.write(Integer.toString(val)); + } + for (int i = a2.size(); i < maxSize; i++) { if (isFirst) { isFirst = false; } else { writer.write(", "); } - writer.write(Integer.toString(i < a2.size() ? a2.get(i) : 1)); + writer.write(Integer.toString(1)); } } } @@ -139,31 +168,40 @@ public class ConversionUtil { writer.write("]);\n"); } + static private void locWrite2DArray(FileWriter writer, + String name, + ArrayList> operations, + Function toMZNFormat) throws IOException { + locWrite2DArray(writer, name, operations, toMZNFormat, false); + } + + static int boolToInt(boolean b) { + return b ? 1 : 0; + } + static private void locWrite2DArray(FileWriter writer, String name, ArrayList> operations, - Function toMZNFormat) throws IOException { - writer.write(name + " = \n"); + Function toMZNFormat, + boolean isNumberedFromZero) throws IOException { + + writer.write(name + " = array2d(" + (isNumberedFromZero ? 0 : 1) + ".." + (operations.size() - boolToInt(isNumberedFromZero)) + + ", " + (isNumberedFromZero ? 0 : 1) + ".." + (operations.get(0).size() - boolToInt(isNumberedFromZero)) + + ", ["); + boolean isFirst0 = true; + for (ArrayList a : operations) { - if (isFirst0) { - isFirst0 = false; - writer.write(" [| "); - } else { - writer.write(" | "); - } - boolean isFirst1 = true; for (T val : a) { - if (isFirst1) { - isFirst1 = false; + if (isFirst0) { + isFirst0 = false; } else { writer.write(", "); } writer.write(toMZNFormat.apply(val)); } - writer.write("\n"); } - writer.write(" |];\n"); + writer.write("]);\n"); } static private void writeArray(FileWriter writer, @@ -362,6 +400,10 @@ public class ConversionUtil { private ArrayList> objectsOfType; + public ArrayList getMovingObjects() { + return movingObjects; + } + Task(TaskCase task, String fileName) { this.fileName = fileName; this.task = task; @@ -375,19 +417,11 @@ public class ConversionUtil { locationNumberById.put(new Pair<>(berth.getId(), true), locationNumberById.size()); } - movingObjects = new ArrayList<>(); + movingObjects = calcMovingObjects(task); mObjNumberById = new TreeMap<>(); - for (MovingObject obj : task.getShips()) { - mObjNumberById.put(obj.getId(), movingObjects.size()); - movingObjects.add(obj); - } - for (MovingObject obj : task.getTows()) { - mObjNumberById.put(obj.getId(), movingObjects.size()); - movingObjects.add(obj); - } - for (MovingObject obj : task.getEquipments()) { - mObjNumberById.put(obj.getId(), movingObjects.size()); - movingObjects.add(obj); + + for (int i = 0; i < movingObjects.size(); i++) { + mObjNumberById.put(movingObjects.get(i).getId(), i); } operationTemplates = new ArrayList<>(task.getTemplates()); @@ -417,6 +451,10 @@ public class ConversionUtil { typeToN.put(type, next); next++; } + for (Integer type : task.getBunkerTypes().keySet()) { + typeToN.put(type, next); + next++; + } for (Integer type : task.getEquipmentsTypes().keySet()) { typeToN.put(type, next); next++; @@ -508,7 +546,7 @@ public class ConversionUtil { for (MovingObjectState state : task.getVesselInitialState()) { initialStates.set(mObjToN(state.getVessel()), getLocNById(state.getLocation().getId(), false)); } - writeArray(writer, "initial_m_obj_loc", initialStates, (Integer p) -> p + 1); + writeArray(writer, "initial_m_obj_loc", initialStates, (Integer p) -> p + 1, Optional.of(-1)); writer.write("\n"); } @@ -538,23 +576,27 @@ public class ConversionUtil { /* Окна погоды. Новый формат. */ private void weatherWindowsNewFormat() throws IOException { ArrayList> badWeather = new ArrayList<>(); + badWeather.add(new ArrayList<>()); + for (int j = 0; j <= n_intervals; j++) { + badWeather.get(0).add(false); + } for (int i = 0; i < operationTemplates.size(); i++) { ArrayList curLine = new ArrayList<>(); - for (int j = 0; j < n_intervals; j++) { + for (int j = 0; j <= n_intervals; j++) { curLine.add(false); } operationTemplates.get(i).getTimeWindows().forEach( (Double start, Double duration) -> { for (int j = (int)Math.floor(start); j < (int)Math.ceil(start + duration); j++) { - curLine.set(j, true); + curLine.set(j + 1, true); } } ); badWeather.add(curLine); } - locWrite2DArray(writer, "bad_weather", badWeather, Objects::toString); + locWrite2DArray(writer, "bad_weather", badWeather, Objects::toString, true); } /* Непрерывность перемещения и швартовки. */ @@ -576,8 +618,8 @@ public class ConversionUtil { isMovingObj.add(false); } } - writeArray(writer, "operations_duration", operationsDuration); - writeArray(writer, "is_continuous_operation", isMovingObj); + writeArray(writer, "operations_duration", operationsDuration, Optional.of(1)); + writeArray(writer, "is_continuous_operation", isMovingObj, Optional.of(false)); } /* Конечные положения объектов. */ @@ -586,7 +628,7 @@ public class ConversionUtil { for (MovingObjectState state : task.getVesselEndState()) { finalStates.set(mObjToN(state.getVessel()), getLocNById(state.getLocation().getId(), false)); } - writeArray(writer, "final_m_obj_loc", finalStates, (Integer p) -> p + 1); + writeArray(writer, "final_m_obj_loc", finalStates, (Integer p) -> p + 1, Optional.of(-1)); } /* Наличие всех ресурсов на месте, в том числе и самого корабля. */ @@ -658,7 +700,7 @@ public class ConversionUtil { for (Storage storage : storages) { maxStorageVol.add((int)Math.ceil(storage.getVolume())); } - writeArray(writer, "max_storage_vol", maxStorageVol); + writeArray(writer, "max_storage_vol", maxStorageVol, Optional.of(0)); writer.write("\n"); } @@ -668,9 +710,9 @@ public class ConversionUtil { ArrayList> initialStorageVol = new ArrayList<>(); ArrayList> finalStorageVol = new ArrayList<>(); - for (int i = 0; i < nObjWithStorage; i++) { - initialStorageVol.add(integerArray(cargoes.size(), 0)); - finalStorageVol .add(integerArray(cargoes.size(), -1)); + for (int i = 0; i <= nObjWithStorage; i++) { + initialStorageVol.add(integerArray(cargoes.size() + 1, 0)); + finalStorageVol .add(integerArray(cargoes.size() + 1, -1)); } for (StorageState st : task.getStorageInitialState()) { int cargoN = cargoNById.get(st.getCargo().getId()); @@ -679,10 +721,10 @@ public class ConversionUtil { if (st.getStorage() instanceof Storage) { Storage storage = (Storage) st.getStorage(); int stN = storNById.get(storage.getId()); - initialStorageVol.get(movingObjects.size() + stN).set(cargoN, val); + initialStorageVol.get(movingObjects.size() + stN + 1).set(cargoN + 1, val); } else if (st.getStorage() instanceof TransportShip) { TransportShip ship = (TransportShip) st.getStorage(); - initialStorageVol.get(mObjToN(ship)).set(cargoN, val); + initialStorageVol.get(mObjToN(ship) + 1).set(cargoN + 1, val); } } for (StorageState st : task.getStorageEndState()) { @@ -692,14 +734,14 @@ public class ConversionUtil { if (st.getStorage() instanceof Storage) { Storage storage = (Storage) st.getStorage(); int stN = storNById.get(storage.getId()); - finalStorageVol.get(movingObjects.size() + stN).set(cargoN, val); + finalStorageVol.get(movingObjects.size() + stN + 1).set(cargoN + 1, val); } else if (st.getStorage() instanceof TransportShip) { TransportShip ship = (TransportShip) st.getStorage(); - finalStorageVol.get(mObjToN(ship)).set(cargoN, val); + finalStorageVol.get(mObjToN(ship) + 1).set(cargoN + 1, val); } } - write2DArrayOfInt(writer, "initial_storage_vol", initialStorageVol); - write2DArrayOfInt(writer, "final_storage_vol", finalStorageVol); + write2DArrayOfInt(writer, "initial_storage_vol", initialStorageVol, true); + write2DArrayOfInt(writer, "final_storage_vol", finalStorageVol, true); } /* Потоки грузов. */ @@ -721,8 +763,19 @@ public class ConversionUtil { cargoFlows.get(storageN + movingObjects.size()).get(i).set(cargoN, (int)flow.getCurrentValue(i - 0.1)); } } - writer.write("cargo_flows = array3d(1..n_obj_with_storage, 0..(n_intervals + 1), 1..n_cargo_types, ["); + writer.write("cargo_flows = array3d(0..n_obj_with_storage, 0..(n_intervals + 1), 1..n_cargo_types, ["); boolean isFirst = true; + + for (int j = 0; j < n_intervals + 2; j++) { + for (int k = 0; k < cargoes.size(); k++) { + if (isFirst) { + isFirst = false; + } else { + writer.write(", "); + } + writer.write("0"); + } + } for (int i = 0; i < nObjWithStorage; i++) { for (int j = 0; j < n_intervals + 2; j++) { for (int k = 0; k < cargoes.size(); k++) { @@ -749,6 +802,9 @@ public class ConversionUtil { 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<>()); for (int j = 0; j < cargoes.size(); j++) { @@ -759,13 +815,19 @@ public class ConversionUtil { for (int i = 0; i < operationTemplates.size(); i++) { if (operationTemplates.get(i) instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate) operationTemplates.get(i); - int storageN = storNById.get(op.getStorage().getId()); + + int storageN; + if (op.getBunker().isPresent()) { + storageN = mObjToN(op.getBunker().get()); + } else { + storageN = storNById.get(op.getStorage().getId()) + movingObjects.size(); + } int shipN = mObjToN(op.getLoader()); int cargoN = cargoNById.get(op.getCargo().getId()); loadingOpDelta.add(-(int)op.getIntensity()); loadingOpN.add(i); - involvedOperations.get(storageN + movingObjects.size()).get(cargoN).add(loadingOpDelta.size()); + involvedOperations.get(storageN).get(cargoN).add(loadingOpDelta.size()); loadingOpDelta.add((int)op.getIntensity()); loadingOpN.add(i); @@ -773,13 +835,15 @@ public class ConversionUtil { loading_op_delta_of_main_obj.add((int)op.getIntensity()); operations_main_stor.add(shipN + 1); - operations_secondary_stor.add(storageN + movingObjects.size() + 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); operations_main_stor.add(1); operations_secondary_stor.add(1); operations_cargo_t.add(1); + bunker_of_cargo_op.add(0); } } writer.write("n_loading_op = " + loadingOpDelta.size() + ";\n"); @@ -791,10 +855,11 @@ public class ConversionUtil { writeArray(writer, "loading_op_delta", loadingOpDelta); writeArray(writer, "loading_op_n", loadingOpN, (Integer i) -> i + 1); - writeArray(writer, "loading_op_delta_of_main_obj", loading_op_delta_of_main_obj); - writeArray(writer, "operations_main_stor", operations_main_stor); - writeArray(writer, "operations_secondary_stor", operations_secondary_stor); - writeArray(writer, "operations_cargo_t", operations_cargo_t); + writeArray(writer, "loading_op_delta_of_main_obj", loading_op_delta_of_main_obj, Optional.of(0)); + 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)); + writeArray(writer, "bunker_of_cargo_op", bunker_of_cargo_op, Optional.of(0)); writer.write("\n"); } @@ -925,57 +990,48 @@ public class ConversionUtil { } private void movingObjectLocationDefinition(boolean isV1) throws IOException { - if (! isV1) { - writeArray(writer, "is_mooring_op", isMooringOp, Optional.of(false)); - writeArray(writer, "main_obj_of_operation", mainObjOfOperation, (Integer val) -> val + 1, Optional.of(1)); - - ArrayList> locMovingOpOfObj = new ArrayList<>(); - for (ArrayList operations : movingOpOfObj) { - ArrayList lOperations = new ArrayList<>(); - for (int i = 0; i < operationTemplates.size(); i++) { - lOperations.add(false); - } - for (Integer op : operations) { - lOperations.set(op - 1, true); - } - locMovingOpOfObj.add(lOperations); - } - locWrite2DArray(writer, "moving_op_of_obj", locMovingOpOfObj, Objects::toString); - } else { - writeArrayOfSetAs2DArray(writer, "moving_op_of_obj", movingOpOfObj, true, false); - } - writeArray(writer, "operations_destination", operationsDestination, (Integer val) -> val + 1); + writeArray(writer, "is_mooring_op", isMooringOp, Optional.of(false)); + writeArray(writer, "operations_destination", operationsDestination, (Integer val) -> val + 1, + Optional.of(-1)); writer.write("\n"); } - private void unmooredCargoOp() throws IOException { - ArrayList> relatedUnmooredCargoOp = new ArrayList<>(); - for (int i = 0; i < locationNumberById.size(); i++) { - relatedUnmooredCargoOp.add(new TreeSet<>()); + private void cargoOpUsingObj() throws IOException { + ArrayList> relatedCargoOp = new ArrayList<>(); + for (int i = 0; i < movingObjects.size(); i++) { + relatedCargoOp.add(new TreeSet<>()); } for (int i = 0; i < operationTemplates.size(); i++) { if (operationTemplates.get(i) instanceof LoadingTemplate) { LoadingTemplate op = (LoadingTemplate) operationTemplates.get(i); - if (! op.getWithMooring()) { - relatedUnmooredCargoOp.get(getLocNById(op.getStartLocation().getId(), false)).add(i + 1); + relatedCargoOp.get(mObjToN(op.getLoader())).add(i + 1); + if (op.getBunker().isPresent()) { + relatedCargoOp.get(mObjToN(op.getBunker().get())).add(i + 1); } } } - writeArray(writer, "related_unmoored_cargo_op", relatedUnmooredCargoOp, ConversionUtil::setToString); + writeArray(writer, "related_cargo_op", relatedCargoOp, ConversionUtil::setToString, + Optional.of(new TreeSet<>())); } - private void cargoOpUsingObjAsMain() throws IOException { - ArrayList> relatedCargoOpUsingObjAsMain = new ArrayList<>(); - for (int i = 0; i < movingObjects.size(); i++) { - relatedCargoOpUsingObjAsMain.add(new TreeSet<>()); + private void addOpWithNominallyMooring() throws IOException { + ArrayList>> opWithNominallyMooring = new ArrayList<>(); + for (int loc = 0; loc <= locationNumberById.size(); loc++) { + opWithNominallyMooring.add(new ArrayList<>()); + for (int obj = 0; obj <= movingObjects.size(); obj++) { + opWithNominallyMooring.get(loc).add(new TreeSet<>()); + } } for (int i = 0; i < operationTemplates.size(); i++) { - if (operationTemplates.get(i) instanceof LoadingTemplate) { - LoadingTemplate op = (LoadingTemplate) operationTemplates.get(i); - relatedCargoOpUsingObjAsMain.get(getMObjNumberById().get(op.getLoader().getId())).add(i + 1); + OperationTemplate t = operationTemplates.get(i); + if ((t instanceof MooringTemplate) || + ((t instanceof LoadingTemplate) && (! ((LoadingTemplate)t).getWithMooring()))) { + opWithNominallyMooring.get(getLocNById(t.getStartLocation().getId(), true) + 1) + .get(mObjToN(getExecutor(t)) + 1) + .add(i + 1); } } - writeArray(writer, "related_cargo_op_using_obj_as_main", relatedCargoOpUsingObjAsMain, ConversionUtil::setToString); + write2DArrayOfSetAs3DArray(writer, "op_with_nominally_mooring", opWithNominallyMooring, true); } void portToMiniZinc_0() throws IOException { @@ -1054,22 +1110,29 @@ public class ConversionUtil { } } + public static ArrayList calcMovingObjects(TaskCase taskCase) { + ArrayList movingObjects = new ArrayList<>(); + movingObjects.addAll(taskCase.getShips()); + movingObjects.addAll(taskCase.getBunkers()); + movingObjects.addAll(taskCase.getTows()); + movingObjects.addAll(taskCase.getEquipments()); + return movingObjects; + } + /* Каждую операцию лишает типизации по главному действующему лицу. */ public static ArrayList renumberOperations(TaskCase task) { TreeMap> shipsByType = new TreeMap<>(); for (Integer type : task.getVesselTypes().keySet()) { shipsByType.put(type, new ArrayList<>()); } + for (Integer type : task.getBunkerTypes().keySet()) { + shipsByType.put(type, new ArrayList<>()); + } for (Integer type : task.getEquipmentsTypes().keySet()) { shipsByType.put(type, new ArrayList<>()); } - ArrayList movingObjects = new ArrayList<>(); - movingObjects.addAll(task.getTows()); - movingObjects.addAll(task.getShips()); - movingObjects.addAll(task.getEquipments()); - - for (MovingObject obj : movingObjects) { + for (MovingObject obj : calcMovingObjects(task)) { if (obj.getType().isPresent()) { shipsByType.get(obj.getType().getAsInt()).add(obj); } @@ -1082,8 +1145,34 @@ public class ConversionUtil { if (t.getLoaderType().isPresent()) { for (MovingObject obj : shipsByType.get(t.getLoaderType().getAsInt())) { assert(obj instanceof TransportShip); - result.add(new LoadingTemplate((TransportShip)obj, t.getStartLocation(), t.getStorage(), - t.getCargo(), t.getResourcesTypes(), t.getWithMooring(), t.getIntensity(), t.getId())); + if (t.getBunkerType().isPresent()) { + for (MovingObject bunker : shipsByType.get(t.getBunkerType().getAsInt())) { + assert(obj instanceof Bunker); + result.add(new LoadingTemplate( + (TransportShip)obj, + t.getStartLocation(), + t.getStorage(), + t.getCargo(), + Optional.of((Bunker)bunker), + t.getResourcesTypes(), + t.getWithMooring(), + t.getIntensity(), + t.getId() + )); + } + } else { + result.add(new LoadingTemplate( + (TransportShip)obj, + t.getStartLocation(), + t.getStorage(), + t.getCargo(), + Optional.empty(), + t.getResourcesTypes(), + t.getWithMooring(), + t.getIntensity(), + t.getId() + )); + } } } } @@ -1129,6 +1218,26 @@ public class ConversionUtil { conflictingOperationsG.get(i).add(j + 1); } } + { // Взаимоисключение операций погрузки без швартовки на одном причале с разными субъектами. + // + операций бункеровки без швартовки на одном причалое + // TODO переделать + if ((operationTemplates.get(i) instanceof LoadingTemplate) && + (operationTemplates.get(j) instanceof LoadingTemplate)) { + LoadingTemplate op1 = (LoadingTemplate) operationTemplates.get(i); + LoadingTemplate op2 = (LoadingTemplate) operationTemplates.get(j); + + if ((! op1.getWithMooring()) && (! op2.getWithMooring()) && + (op1.getStartLocation() == op2.getStartLocation()) && + (op1.getLoader() != op2.getLoader())) { + conflictingOperationsG.get(i).add(j + 1); + } + if ((! op1.getWithMooring()) && (! op2.getWithMooring()) && + (op1.getStartLocation() == op2.getStartLocation()) && + (op1.getBunker().isPresent()) && (op2.getBunker().isPresent())) { + conflictingOperationsG.get(i).add(j + 1); + } + } + } { // Взаимоисключение операций перемещения и грузообработки с общим деятелем. // TODO вынести в отдельный constraint OperationTemplate t1 = operationTemplates.get(i); @@ -1147,7 +1256,8 @@ public class ConversionUtil { } } } - writeArray(writer, "conflicting_operations", conflictingOperationsG, ConversionUtil::setToString); + writeArray(writer, "conflicting_operations", conflictingOperationsG, ConversionUtil::setToString, + Optional.of(new TreeSet<>())); } public ArrayList> getIsFixedArray() { @@ -1158,9 +1268,9 @@ public class ConversionUtil { } ArrayList> isFixed = new ArrayList<>(); - for (int i = 0; i < operationTemplates.size(); i++) { + for (int i = 0; i <= operationTemplates.size(); i++) { isFixed.add(new ArrayList<>()); - for (int j = 0; j < n_intervals; j++) { + for (int j = 0; j <= n_intervals; j++) { isFixed.get(i).add(false); } } @@ -1169,7 +1279,7 @@ public class ConversionUtil { int operation = opNoByOpIdAndExecutorNo.get(new Pair<>(op.getTemplate().getId(), op.getExecutor().getId())); for (int i = (int)Math.floor(op.getStart()); i < (int)Math.ceil(op.getDuration() + op.getStart()); i++) { - isFixed.get(operation).set(i, true); + isFixed.get(operation + 1).set(i + 1, true); } } } @@ -1206,7 +1316,36 @@ public class ConversionUtil { writeArray(writer, "fixed_op_resources", fixedOpResources, ConversionUtil::setToString); writeArray(writer, "fixed_op_start", fixedOpStart); writeArray(writer, "fixed_op_end", fixedOpEnd); - locWrite2DArray(writer, "is_fixed", getIsFixedArray(), Objects::toString); + locWrite2DArray(writer, "is_fixed", getIsFixedArray(), Objects::toString, true); + } + + void defDataForCurMovingOp() throws IOException { + ArrayList isMovingOp = new ArrayList<>(); + for (OperationTemplate op : operationTemplates) { + isMovingOp.add((op instanceof MovingTemplate) || (op instanceof MooringTemplate)); + } + writeArray(writer, "is_moving_operation", isMovingOp, Optional.of(false)); + writer.write("\n"); + + writeArray(writer, "main_obj_of_operation", mainObjOfOperation, (Integer val) -> val + 1, Optional.of(-1)); + + ArrayList> locMovingOpOfObj = new ArrayList<>(); + locMovingOpOfObj.add(new ArrayList<>()); + for (int i = 0; i <= operationTemplates.size(); i++) { + locMovingOpOfObj.get(0).add(false); + } + for (ArrayList operations : movingOpOfObj) { + ArrayList lOperations = new ArrayList<>(); + lOperations.add(false); + for (int i = 0; i < operationTemplates.size(); i++) { + lOperations.add(false); + } + for (Integer op : operations) { + lOperations.set(op, true); + } + locMovingOpOfObj.add(lOperations); + } + locWrite2DArray(writer, "moving_op_of_obj", locMovingOpOfObj, Objects::toString, true); } private void typifiedResourcesDefinition() throws IOException { @@ -1223,26 +1362,8 @@ public class ConversionUtil { } } } - writeArray(writer, "operations_that_used_obj_as_resource", res, ConversionUtil::setToString); - writer.write("\n"); - } - { // main_obj_start_loc, is_moving_operation - ArrayList mainObjStartLoc = new ArrayList<>(); - ArrayList isMovingOp = new ArrayList<>(); - - for (OperationTemplate op : operationTemplates) { - boolean isMoored = false; - if ((op instanceof LoadingTemplate) && (((LoadingTemplate) op).getWithMooring())) { - isMoored = true; - } - if ((op instanceof MooringTemplate) && (!((MooringTemplate)op).isDirect())) { - isMoored = true; - } - mainObjStartLoc.add(locationNumberById.get(new Pair<>(op.getStartLocation().getId(), isMoored))); - isMovingOp.add((op instanceof MovingTemplate) || (op instanceof MooringTemplate)); - } - writeArray(writer, "main_obj_start_loc", mainObjStartLoc, (Integer val) -> val + 1); - writeArray(writer, "is_moving_operation", isMovingOp, Optional.of(false)); + writeArray(writer, "operations_that_used_obj_as_resource", res, ConversionUtil::setToString, + Optional.of(new TreeSet<>())); writer.write("\n"); } { // counters, operations_resources_start_loc @@ -1274,10 +1395,29 @@ public class ConversionUtil { writeArray(writer, "operation_of_counter", operationOfCounter, (Integer val) -> val + 1); writeArray(writer, "required_counter_values", requiredCounterValues); writeArray(writer, "operations_resources_start_loc", operationsResourcesStartLoc, (Integer val) -> val + 1); - writeArray(writer, "counters_of_operation", countersOfOperation, ConversionUtil::setToString); + writeArray(writer, "counters_of_operation", countersOfOperation, ConversionUtil::setToString, + Optional.of(new TreeSet<>())); } } + void requiredLocationsOnOpStart() throws IOException { + ArrayList mainObjStartLoc = new ArrayList<>(); + ArrayList bunkerStartLoc = new ArrayList<>(); + for (OperationTemplate op : operationTemplates) { + boolean isMoored = false; + if ((op instanceof LoadingTemplate) && (((LoadingTemplate) op).getWithMooring())) { + isMoored = true; + } + if ((op instanceof MooringTemplate) && (!((MooringTemplate)op).isDirect())) { + isMoored = true; + } + mainObjStartLoc.add(getLocNById(op.getStartLocation().getId(), isMoored)); + bunkerStartLoc.add(getLocNById(op.getStartLocation().getId(), false)); + } + writeArray(writer, "main_obj_start_loc", mainObjStartLoc, (Integer val) -> val + 1, Optional.of(-1)); + writeArray(writer, "bunker_start_loc", bunkerStartLoc, (Integer val) -> val + 1, Optional.of(-1)); + } + /* С типизацией. */ void portToMiniZinc_2() throws IOException { if (!task.isTypified()) { @@ -1296,15 +1436,19 @@ public class ConversionUtil { movingObjectLocationDefinition(false); initialLocations(); finalLocations(); + + defDataForCurMovingOp(); + weatherWindowsNewFormat(); conflictingOperationsOnStorageAndOnTypeOnMainObject(); + requiredLocationsOnOpStart(); + operationsContinuity(); typifiedResourcesDefinition(); - unmooredCargoOp(); - - cargoOpUsingObjAsMain(); + cargoOpUsingObj(); + addOpWithNominallyMooring(); writer.write("n_obj_with_storage = " + nObjWithStorage + ";\n"); writer.write("n_cargo_types = " + cargoes.size() + ";\n"); @@ -1346,7 +1490,7 @@ public class ConversionUtil { } } - public static void resolveMiniZincResults(TaskCase task, String fileName) { + public static void resolveMiniZincResults(TaskCase taskCase, String fileName) { ArrayList operations = null; Integer result = null; @@ -1386,7 +1530,7 @@ public class ConversionUtil { while ((pos < line.length()) && (line.charAt(pos) != '[') && (line.charAt(pos) != '{')) { pos++; } - int arrayFirstDim = ((int) task.getPlanningInterval()) + 2; + int arrayFirstDim = ((int) taskCase.getPlanningInterval()) + 2; if (line.charAt(pos) == '{') { pos++; @@ -1429,78 +1573,87 @@ public class ConversionUtil { if (result == null) { throw new ParserException("No result in input"); } - if (!arrays.containsKey("op_status")) { - if (result == -1) { - operations = new ArrayList<>(); - } else { - throw new ParserException("No \"op_status\" in input"); + + for (String keyArray : Arrays.asList("op_status", "participation_as_resource")) { + if (! arrays.containsKey(keyArray)) { + if (result == -1) { + operations = new ArrayList<>(); + } else { + throw new ParserException("No \"" + keyArray + "\" in input"); + } } } + if (result != -1) { + Task task = new Task(taskCase, ""); + operations = new ArrayList<>(); ArrayList> opStatus = arrays.get("op_status"); - ArrayList templates = new ArrayList<>(task.getTemplates()); - if (task.isTypified()) { - templates = Task.renumberOperations(task); + ArrayList templates = new ArrayList<>(taskCase.getTemplates()); + if (taskCase.isTypified()) { + templates = Task.renumberOperations(taskCase); } Map operationById = new TreeMap<>(); - for (OperationTemplate operation : task.getTemplates()) { + for (OperationTemplate operation : taskCase.getTemplates()) { operationById.put(operation.getId(), operation); } Map objByNo = new TreeMap<>(); ArrayList> isFixed; - { - Task t = new Task(task, ""); - ArrayList movingObjects = new ArrayList<>(); - movingObjects.addAll(task.getShips()); - movingObjects.addAll(task.getTows()); - movingObjects.addAll(task.getEquipments()); - - for (MovingObject obj : movingObjects) { - objByNo.put(t.getMObjNumberById().get(obj.getId()), obj); - } - isFixed = t.getIsFixedArray(); + for (MovingObject obj : task.getMovingObjects()) { + objByNo.put(task.getMObjNumberById().get(obj.getId()), obj); } + isFixed = task.getIsFixedArray(); + Set oldSolution = new TreeSet<>(); - for (Operation op : task.getSolution()) { + for (Operation op : taskCase.getSolution()) { if (op.getFixation()) { oldSolution.add(op.toString()); } } - for (int opNo = 0; opNo < opStatus.size(); opNo++) { + for (int opNo = 1; opNo < opStatus.size(); opNo++) { int duration = 0; int t = 0; boolean lastFixation = false; while (t < opStatus.get(opNo).size()) { - if ((opStatus.get(opNo).get(t).equals("true") && (lastFixation != isFixed.get(opNo).get(t - 1))) + if ((opStatus.get(opNo).get(t).equals("true") && (lastFixation != isFixed.get(opNo).get(t)) && (duration != 0)) || (opStatus.get(opNo).get(t).equals("false") && (duration != 0))) { // Добавляем новую операцию. Operation op = new Operation(); op.setStart(t - duration - 1); op.setDuration(duration); - op.setTemplate(operationById.get(templates.get(opNo).getId())); + op.setTemplate(operationById.get(templates.get(opNo - 1).getId())); - if (task.isTypified()) { - op.setExecutor(ConversionUtil.getExecutor(templates.get(opNo))); + if (taskCase.isTypified()) { + op.setExecutor(ConversionUtil.getExecutor(templates.get(opNo - 1))); ArrayList resources = new ArrayList<>(); // TODO ускорить. ArrayList> opOfResource = arrays.get("participation_as_resource"); - for (int obj = 0; obj < opOfResource.size(); obj++) { - if (opOfResource.get(obj).get(t - 1).equals(Integer.toString(opNo + 1))) { - resources.add(objByNo.get(obj)); + for (int obj = 1; obj < opOfResource.size(); obj++) { + if (opOfResource.get(obj).get(t - 1).equals(Integer.toString(opNo))) { + resources.add(objByNo.get(obj - 1)); } } op.setResources(resources); } + { + OperationTemplate template = templates.get(opNo - 1); + if (template instanceof LoadingTemplate) { + LoadingTemplate operation = (LoadingTemplate)template; + if (operation.getBunker().isPresent()) { + // TODO Доделать. + } + } + } + op.setFixation(true); if (! oldSolution.contains(op.toString())) { op.setFixation(false); @@ -1509,22 +1662,24 @@ public class ConversionUtil { operations.add(op); duration = 0; } - if (opStatus.get(opNo).get(t).equals("true") && (lastFixation != isFixed.get(opNo).get(t - 1))) { // Остаёмся на месте. - lastFixation = isFixed.get(opNo).get(t - 1); + if (opStatus.get(opNo).get(t).equals("true") && (lastFixation != isFixed.get(opNo).get(t))) { // Остаёмся на месте. + lastFixation = isFixed.get(opNo).get(t); continue; } if (opStatus.get(opNo).get(t).equals("true")) { duration++; + } else { + duration = 0; } - if ((0 <= t - 1) && (t - 1 < isFixed.get(opNo).size())) { - lastFixation = isFixed.get(opNo).get(t - 1); + if ((0 <= t) && (t < isFixed.get(opNo).size())) { + lastFixation = isFixed.get(opNo).get(t); } t++; } } } - task.setSolution(operations); - task.setSolution_result(result); + taskCase.setSolution(operations); + taskCase.setSolution_result(result); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/src/inport/LoadingTemplate.java b/src/inport/LoadingTemplate.java index 1196afd4a7704fb7ef93e45dbd3062a2894fd4f0..ec1bdbc7909872b8beca8c6ce5eb385d3de613d4 100644 --- a/src/inport/LoadingTemplate.java +++ b/src/inport/LoadingTemplate.java @@ -6,6 +6,7 @@ package inport; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.OptionalInt; /** @@ -15,7 +16,9 @@ import java.util.OptionalInt; public class LoadingTemplate extends OperationTemplate { private TransportShip loader; - private OptionalInt loaderType = OptionalInt.empty(); + private OptionalInt loaderType = OptionalInt.empty(); + private Optional bunker = Optional.empty(); + private OptionalInt bunkerType = OptionalInt.empty(); private Storage storage; private List resources; private List resourcesTypes; @@ -23,6 +26,20 @@ public class LoadingTemplate extends OperationTemplate { private boolean withMooring; private Cargo cargo; + public OptionalInt getBunkerType() { + return bunkerType; + } + public void setBunkerType(OptionalInt bunkerType) { + this.bunkerType = bunkerType; + } + + public Optional getBunker() { + return bunker; + } + public void setBunker(Optional bunker) { + this.bunker = bunker; + } + public OptionalInt getLoaderType() { return loaderType; } @@ -95,11 +112,19 @@ public class LoadingTemplate extends OperationTemplate { return cargo; } - public LoadingTemplate(TransportShip loader, Berth berth, Storage storage, Cargo cargo, - List resourcesTypes, boolean withMooring, double intensity, int id) { + public LoadingTemplate(TransportShip loader, + Berth berth, + Storage storage, + Cargo cargo, + Optional bunker, + List resourcesTypes, + boolean withMooring, + double intensity, + int id) { super(id, berth); this.loader = loader; this.storage = storage; + this.bunker = bunker; this.resources = new ArrayList<>(); this.resourcesTypes = new ArrayList<>(resourcesTypes); this.withMooring = withMooring; @@ -130,20 +155,20 @@ public class LoadingTemplate extends OperationTemplate { res += t; first = false; } - int startId; - if (loaderType.isPresent()) { - startId = loaderType.getAsInt(); - } else { - startId = loader.getId(); - } - int source = startId; - if (intensity>0) - source = storage.getId(); - int target = startId; - if (intensity<=0) - target = storage.getId(); + int source = (loaderType.isPresent() ? loaderType.getAsInt() : loader.getId()); + int target; + if (bunkerType.isPresent()) { + target = bunkerType.getAsInt(); + } else target = bunker.map(MovingObject::getId).orElseGet(() -> storage.getId()); + + if (intensity > 0) { + int temp = source; + source = target; + target = temp; + } return getId() + "; " + "loa; " + twtoString() + "; " + source + "; " + cargo.getId() + "; " + target + "; " - + getStartLocation().getId() + "; [" + res +"]; " + Math.abs(intensity) + "; " + (withMooring ? "M" : "U"); - } + + getStartLocation().getId() + "; [" + res +"]; " + Math.abs(intensity) + "; " + + (withMooring ? "M" : "U"); + } } diff --git a/src/inport/Main.java b/src/inport/Main.java index 46a6c26727cfb0a92d9f893f1c3a366aa4025045..bb59bf24e737dcca69bb93c4ab827499f037a6cf 100644 --- a/src/inport/Main.java +++ b/src/inport/Main.java @@ -100,7 +100,6 @@ public class Main { System.out.println(e.getMessage()); break; } - String error = solveTask_2(task); if (!error.isEmpty()) { @@ -148,10 +147,7 @@ public class Main { } Task t = new Task(task, ""); { - ArrayList movingObjects = new ArrayList<>(); - movingObjects.addAll(task.getShips()); - movingObjects.addAll(task.getTows()); - movingObjects.addAll(task.getEquipments()); + ArrayList movingObjects = Task.calcMovingObjects(task); Map objByNo = new TreeMap<>(); for (MovingObject obj : movingObjects) { diff --git a/src/inport/Operation.java b/src/inport/Operation.java index 32cf9a633cde9b31683599dcb6da1ec7cfec492c..c04c7f4ec4ae8dd426080fc856b4d4b0f3dd3727 100644 --- a/src/inport/Operation.java +++ b/src/inport/Operation.java @@ -5,6 +5,7 @@ package inport; import java.util.List; +import java.util.Optional; /** * @@ -17,8 +18,16 @@ public class Operation { private double start; private double duration; private MovingObject executor; + private Optional bunker = Optional.empty(); private List resources; + public Optional getBunker() { + return bunker; + } + public void setBunker(Optional bunker) { + this.bunker = bunker; + } + public boolean getFixation() { return fixation; } @@ -110,7 +119,8 @@ public class Operation { StringBuilder sb = new StringBuilder(); sb.append(template.getId()).append("; "); sb.append(fixation ? "F" : "R").append("; ").append(start).append("; ").append(duration); - sb.append(" (").append(executor.getId()).append(" ["); + sb.append(" (").append(executor.getId()).append(" "); + sb.append(bunker.map(b -> b.getId() + " ").orElse("")).append("["); boolean isFirst = true; for (MovingObject obj : resources) { if (isFirst) { diff --git a/src/inport/Storage.java b/src/inport/Storage.java index 134139e51cb993d2bc6f4f30a54107beb91bd31a..20b3e280f7d29dd239e998e118e05414ed9d29b4 100644 --- a/src/inport/Storage.java +++ b/src/inport/Storage.java @@ -101,7 +101,7 @@ public class Storage { @Override public String toString() { - return id + "; " + name + "; " + cargo.getId() + "; " +volume; + return id + "; " + name + "; " + cargo.getId() + "; " + volume; } public Storage(String s, Map cargoes) { diff --git a/src/inport/StorageState.java b/src/inport/StorageState.java index 6a9d57c78e28f86f788ced88fcda28f938d6f165..f05b8cb2e619be13430cc30d59280802de489277 100644 --- a/src/inport/StorageState.java +++ b/src/inport/StorageState.java @@ -82,15 +82,24 @@ public class StorageState { return ""; } - public StorageState(String s, Map mp, Map vp, Map cp) { + public StorageState(String s, + Map mp, + Map vp, + Map bunkers, + Map cp) { String[] tokens = s.split(";"); int key = Integer.parseInt(tokens[0].trim()); cargo = cp.get(key); key = Integer.parseInt(tokens[1].trim()); - if (mp.containsKey(key)) + if (mp.containsKey(key)) { storage = mp.get(key); - if (vp.containsKey(key)) + } + if (vp.containsKey(key)) { storage = vp.get(key); + } + if (bunkers.containsKey(key)) { + storage = bunkers.get(key); + } cargoState = Double.parseDouble(tokens[2].trim()); } diff --git a/src/inport/TaskCase.java b/src/inport/TaskCase.java index b2a0a53af19b4d9ead3cd531b5f6081aa4e321a5..06c6cf4a37781e832a79f46946c1743dbd3a77ef 100644 --- a/src/inport/TaskCase.java +++ b/src/inport/TaskCase.java @@ -35,6 +35,9 @@ public class TaskCase { // Обслуживаемые суда private List ships; + // Типы бункеровщиков. + private Map bunkerTypes; + // Типы обслуживаемых судов private Map vesselTypes; @@ -67,6 +70,13 @@ public class TaskCase { // План - решение private List solution; + public Map getBunkerTypes() { + return bunkerTypes; + } + public void setBunkerTypes(Map bunkerTypes) { + this.bunkerTypes = bunkerTypes; + } + /** * Get the value of solution * @@ -385,6 +395,7 @@ public class TaskCase { equipments = new ArrayList<>(); ships = new ArrayList<>(); + bunkerTypes = new TreeMap<>(); vesselTypes = new TreeMap<>(); equipmentTypes = new TreeMap<>(); @@ -401,12 +412,15 @@ public class TaskCase { solution = new ArrayList<>(); } - private MovingObjectState fromString(String s, Map m_berth, Map m_vessel) + private MovingObjectState fromString(String s, + Map m_berth, + Map m_vessel, + Map m_bunker) { String[] tkns1 = s.split(";"); MovingObjectState st = new MovingObjectState(); int key = Integer.parseInt(tkns1[0].trim()); - MovingObject vs = m_vessel.get(key); + MovingObject vs = m_vessel.containsKey(key) ? m_vessel.get(key) : m_bunker.get(key); st.setVessel(vs); key = Integer.parseInt(tkns1[1].trim()); st.setLocation(m_berth.get(key)); @@ -422,6 +436,7 @@ public class TaskCase { Loading_Equipment_Types("Loading Equipment Types"), Vessel_Types ("Vessel Types"), Bunkers ("Bunkers"), + Bunker_Types ("Bunker Types"), Tows ("Tows"), Loading_Equipments ("Loading Equipments"), Transport_Ships ("Transport Ships"), @@ -453,6 +468,7 @@ public class TaskCase { { cargoes.clear(); berths.clear(); storages.clear(); bunkers.clear(); tows.clear(); equipments.clear(); ships.clear(); templates.clear(); cargoFlows.clear(); vesselInitialState.clear(); storageInitialState.clear(); vesselEndState.clear(); storageEndState.clear(); + bunkerTypes.clear(); solution.clear(); // Open the file @@ -467,6 +483,7 @@ public class TaskCase { Map m_berth = new HashMap<>(); Map m_storage = new HashMap<>(); Map m_vessel = new HashMap<>(); + Map m_bunker = new HashMap<>(); Map m_equipment = new HashMap<>(); Map m_template = new HashMap<>(); //Read File Line By Line @@ -494,7 +511,8 @@ public class TaskCase { break; case Berths: Berth b = new Berth(strLine); berths.add(b); m_berth.put(b.getId(), b); break; - case Storages: Storage s = new Storage(strLine, m_cargo); storages.add(s); m_storage.put(s.getId(), s); + case Storages: + Storage s = new Storage(strLine, m_cargo); storages.add(s); m_storage.put(s.getId(), s); break; case Vessel_Types: tokens = strLine.split(";"); @@ -505,6 +523,13 @@ public class TaskCase { equipmentTypes.put(Integer.parseInt(tokens[0].trim()), tokens[1].trim()); break; case Bunkers: + Bunker bunker = new Bunker(strLine); + bunkers.add(bunker); + m_bunker.put(bunker.getId(), bunker); + break; + case Bunker_Types : + tokens = strLine.split(";"); + bunkerTypes.put(Integer.parseInt(tokens[0].trim()), tokens[1].trim()); break; case Tows: Tow t = new Tow(strLine); tows.add(t); m_vessel.put(t.getId(), t); break; @@ -577,7 +602,8 @@ public class TaskCase { LoadingTemplate mt = new LoadingTemplate(); mt.setId(Integer.parseInt(tokens[0].trim())); mt.setTimeWindow(tokens[2].trim()); - int direct = 1; + + int direction = 1; BiFunction addLoaderOrStorage = (Integer key, Integer loaderDirection) -> { int dir = 1; @@ -588,17 +614,27 @@ public class TaskCase { if (m_vessel.containsKey(key)) { mt.setLoader((TransportShip)m_vessel.get(key)); dir = loaderDirection; - } + } else if (m_storage.containsKey(key)) { - mt.setStorage((Storage)m_storage.get(key)); + mt.setStorage(m_storage.get(key)); + dir = -loaderDirection; + } else + if (m_bunker.containsKey(key)) { + mt.setBunker(Optional.of(m_bunker.get(key))); + dir = -loaderDirection; + } else + if (bunkerTypes.containsKey(key)) { + mt.setBunkerType(OptionalInt.of(key)); dir = -loaderDirection; } return dir; }; - // Источник. Пока пара - это только хранилище-судно. С бункеровкой будем разбираться потом - int key = Integer.parseInt(tokens[3].trim()); - direct = addLoaderOrStorage.apply(key, -1); + int key; + + // Источник. + key = Integer.parseInt(tokens[3].trim()); + direction = addLoaderOrStorage.apply(key, -1); // Груз. key = Integer.parseInt(tokens[4].trim());; for (Cargo cargo : cargoes) { @@ -606,9 +642,9 @@ public class TaskCase { mt.setCargo(cargo); } } - // Приемник. Пока пара - это только хранилище-судно. С бункеровкой будем разбираться потом + // Приемник. key = Integer.parseInt(tokens[5].trim()); - direct = addLoaderOrStorage.apply(key, 1); + direction = addLoaderOrStorage.apply(key, 1); key = Integer.parseInt(tokens[6].trim()); mt.setStartLocation(m_berth.get(key)); String[] rs = tokens[7].trim().replace("[", "").replace("]", "").split(","); @@ -621,7 +657,7 @@ public class TaskCase { mt.getResources().add(m_equipment.get(key)); } } - mt.setIntensity(direct*Double.parseDouble(tokens[8].trim())); + mt.setIntensity(direction*Double.parseDouble(tokens[8].trim())); mt.setWithMooring(tokens[9].trim().equals("M")); templates.add(mt); @@ -632,13 +668,13 @@ public class TaskCase { break; case Cargo_Flows: cargoFlows.add(new CargoFlow(strLine, m_storage, m_cargo)); break; - case Initial_Vessel_State: vesselInitialState.add(fromString(strLine, m_berth, m_vessel)); + case Initial_Vessel_State: vesselInitialState.add(fromString(strLine, m_berth, m_vessel, m_bunker)); break; - case Initial_Storage_State: storageInitialState.add(new StorageState(strLine, m_storage, m_vessel, m_cargo)); + case Initial_Storage_State: storageInitialState.add(new StorageState(strLine, m_storage, m_vessel, m_bunker, m_cargo)); break; - case Final_Vessel_State: vesselEndState.add(fromString(strLine, m_berth, m_vessel)); + case Final_Vessel_State: vesselEndState.add(fromString(strLine, m_berth, m_vessel, m_bunker)); break; - case Final_Storage_State: storageEndState.add(new StorageState(strLine, m_storage, m_vessel, m_cargo)); + case Final_Storage_State: storageEndState.add(new StorageState(strLine, m_storage, m_vessel, m_bunker, m_cargo)); break; case Task_Properties: { @@ -719,7 +755,13 @@ public class TaskCase { for (Map.Entry e : vesselTypes.entrySet()) { writer.write(e.getKey() + "; " + e.getValue() + "\n"); } + + writer.write("\n" + Tag.Bunker_Types.text + "\n"); + for (Map.Entry e : bunkerTypes.entrySet()) { + writer.write(e.getKey() + "; " + e.getValue() + "\n"); + } } + writer.write("\nBunkers"+"\n"); for (Bunker c : bunkers) writer.write(c.toString()+"\n"); diff --git a/tests/with_typing/Bunkers.tipp b/tests/with_typing/Bunkers.tipp new file mode 100644 index 0000000000000000000000000000000000000000..6df16f1cfff13f8f46ba62eecddf5c903218ce6c --- /dev/null +++ b/tests/with_typing/Bunkers.tipp @@ -0,0 +1,94 @@ +Typified +1 + +Cargoes +10001; Нечто; 0.0 +10002; Топливо; 0.0 + +Berths +1; Raid +2; Pier 1 +3; Pier 2 + +Storages +4; Storage 1; 10001; 10000.0 + +Vessel Types +1001; Тип судна 1 + +Bunker Types +2001; Тип бункировщика 1 + +Bunkers +201; Bunker 1; 2000.0; 2001 +202; Bunker 2; 2000.0; 2001 + +Tows + +Loading Equipment Types + +Loading Equipments + +Transport Ships +101; Ship 1; 2000.0; 1001 +102; Ship 2; 2000.0; 1001 + +Templates +7; mov; []; 1001; 1; 2; []; 1.0 +8; mov; []; 1001; 2; 1; []; 1.0 +9; mov; []; 1001; 1; 3; []; 1.0 +10; mov; []; 1001; 3; 1; []; 1.0 +11; mov; []; 1001; 2; 3; []; 1.0 +12; mov; []; 1001; 3; 2; []; 1.0 +13; mov; []; 2001; 3; 2; []; 1.0 +14; mov; []; 2001; 3; 2; []; 1.0 +19; loa; []; 4; 10001; 1001; 2; []; 100.0; U +20; loa; []; 2001; 10002; 1001; 2; []; 10.0; U + +Cargo Flows + +Initial Vessel State +101; 1 +102; 1 +201; 2 +202; 2 + +Initial Storage State +10001; 101; 0.0 +10002; 101; 0.0 +10001; 102; 0.0 +10002; 102; 0.0 +10002; 201; 20.0 +10002; 202; 20.0 +10001; 4; 10000.0 + +Final Vessel State +101; 1 +102; 1 + +Final Storage State +10001; 101; 300.0 +10002; 101; 20.0 +10001; 102; 300.0 +10002; 102; 20.0 + + +Task Properties +30.0; 0 + + +Solution +8.0 +7; R; 0.0; 1.0 (101 []) +9; R; 0.0; 1.0 (102 []) +19; R; 1.0; 3.0 (101 []) +20; R; 1.0; 1.0 (101 []) +10; R; 2.0; 1.0 (102 []) +7; R; 3.0; 1.0 (102 []) +20; R; 3.0; 1.0 (101 []) +11; R; 4.0; 1.0 (101 []) +19; R; 4.0; 3.0 (102 []) +20; R; 4.0; 1.0 (102 []) +20; R; 5.0; 1.0 (102 []) +8; R; 7.0; 1.0 (102 []) +10; R; 7.0; 1.0 (101 []) diff --git a/tests/with_typing/v2.tipp b/tests/with_typing/v2.tipp index 8e0c354a80ec1a3c3d8da454d8a2d6d0a9643830..10f7ca43eb3092a834a373fbbf2d4b69fe077575 100644 --- a/tests/with_typing/v2.tipp +++ b/tests/with_typing/v2.tipp @@ -69,7 +69,7 @@ Final Storage State Task Properties -30.0; 0 +22.0; 0 Solution diff --git "a/\320\237\320\273\320\260\320\275\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265 \320\277\320\276\321\200\321\202\320\276\320\262\321\213\321\205 \320\276\320\277\320\265\321\200\320\260\321\206\320\270\320\271.docx" "b/\320\237\320\273\320\260\320\275\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265 \320\277\320\276\321\200\321\202\320\276\320\262\321\213\321\205 \320\276\320\277\320\265\321\200\320\260\321\206\320\270\320\271.docx" index 23d4ad6746c292f13c5853d2c7338507a367facd..13dac3982343770318491436e05bb0b0ee136095 100644 Binary files "a/\320\237\320\273\320\260\320\275\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265 \320\277\320\276\321\200\321\202\320\276\320\262\321\213\321\205 \320\276\320\277\320\265\321\200\320\260\321\206\320\270\320\271.docx" and "b/\320\237\320\273\320\260\320\275\320\270\321\200\320\276\320\262\320\260\320\275\320\270\320\265 \320\277\320\276\321\200\321\202\320\276\320\262\321\213\321\205 \320\276\320\277\320\265\321\200\320\260\321\206\320\270\320\271.docx" differ