Commit 2766a7f9 authored by Vladislav Kiselev's avatar Vladislav Kiselev

Добавлена возможность бункеровки, упрощено сведение.

parent c22255ea
......@@ -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];
% Определение current_moored_obj.
% Объект, пришвартованный к данной локации.
array [0..n_locations, 0..(n_intervals + 1)] of var 0..n_moving_obj : current_moored_obj;
% Операции грузообработки, проводимые без пришвартовки на этой локации.
array [1..n_locations] of set of 1..n_operations : related_unmoored_cargo_op;
constraint forall (t in 0..(n_intervals + 1)) (current_moored_obj[0, t] = 0); % Фиктивная локация.
% Определение 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])
)
% Фиксирование неиспользуемых значений.
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;
% В начале никто не движется.
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 (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, t in 1..(n_intervals + 1)) (
(current_moving_operation[obj, t - 1] = 0)
-> is_m_obj_in_movement_before_start[obj, t] = false
% Если объект пришвартован или швартуется, то 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] = (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;
array [1..n_moving_obj] of set of 1..n_operations : related_cargo_op_using_obj_as_main;
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] =
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]
))
(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])
);
/* 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])
)
% Требуемое положение главного объекта в момент начала операций.
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 [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",
......
......@@ -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);
}
}
......@@ -22,7 +22,14 @@ public class ConversionUtil {
static private void write2DArrayOfInt(FileWriter writer,
String name,
ArrayList<ArrayList<Integer>> operations) throws IOException {
locWrite2DArray(writer, name, operations, Object::toString);
locWrite2DArray(writer, name, operations, Object::toString, false);
}
static private void write2DArrayOfInt(FileWriter writer,
String name,
ArrayList<ArrayList<Integer>> 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 <T extends Collection<Integer>> void write2DArrayOfSetAs3DArray(FileWriter writer,
String name,
ArrayList<ArrayList<ArrayList<Integer>>> operations) throws IOException {
ArrayList<ArrayList<T>> operations) throws IOException {
write2DArrayOfSetAs3DArray(writer, name, operations, false);
}
static private <T extends Collection<Integer>> void write2DArrayOfSetAs3DArray(FileWriter writer,
String name,
ArrayList<ArrayList<T>> operations,
boolean isNumberedFromZero) throws IOException {
int maxSize = 0;
ArrayList<ArrayList<Integer>> sizes = new ArrayList<>();
int dim1 = operations.size();
int dim2 = 0;
for (ArrayList<ArrayList<Integer>> a1 : operations) {
for (ArrayList<T> a1 : operations) {
dim2 = a1.size();
ArrayList<Integer> locSizes = new ArrayList<>();
for (ArrayList<Integer> 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<ArrayList<Integer>> a1 : operations) {
for (ArrayList<Integer> a2 : a1) {
for (int i = 0; i < maxSize; i++) {
for (ArrayList<T> a1 : operations) {
for (T a2 : a1) {
for (Integer val : a2) {
if (isFirst) {
isFirst = false;
} else {
writer.write(", ");
}
writer.write(Integer.toString(i < a2.size() ? a2.get(i) : 1));
writer.write(Integer.toString(val));
}
for (int i = a2.size(); i < maxSize; i++) {
if (isFirst) {
isFirst = false;
} else {
writer.write(", ");
}
writer.write(Integer.toString(1));
}
}
}
......@@ -143,27 +172,36 @@ public class ConversionUtil {
String name,
ArrayList<ArrayList<T>> operations,
Function<T, String> toMZNFormat) throws IOException {
writer.write(name + " = \n");
locWrite2DArray(writer, name, operations, toMZNFormat, false);
}
static int boolToInt(boolean b) {
return b ? 1 : 0;
}
static private <T> void locWrite2DArray(FileWriter writer,
String name,
ArrayList<ArrayList<T>> operations,
Function<T, String> 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<T> a : operations) {
for (T val : a) {
if (isFirst0) {
isFirst0 = false;
writer.write(" [| ");
} else {
writer.write(" | ");
}
boolean isFirst1 = true;
for (T val : a) {
if (isFirst1) {
isFirst1 = false;
} else {
writer.write(", ");
}
writer.write(toMZNFormat.apply(val));
}
writer.write("\n");
}
writer.write(" |];\n");
writer.write("]);\n");
}
static private <T, E> void writeArray(FileWriter writer,
......@@ -362,6 +400,10 @@ public class ConversionUtil {
private ArrayList<Set<Integer>> objectsOfType;
public ArrayList<MovingObject> 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<ArrayList<Boolean>> 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<Boolean> 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<ArrayList<Integer>> initialStorageVol = new ArrayList<>();
ArrayList<ArrayList<Integer>> 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<Integer> operations_secondary_stor = new ArrayList<>();
ArrayList<Integer> operations_cargo_t = new ArrayList<>();
ArrayList<Integer> bunker_of_cargo_op = new ArrayList<>();
ArrayList<Boolean> 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<ArrayList<Boolean>> locMovingOpOfObj = new ArrayList<>();
for (ArrayList<Integer> operations : movingOpOfObj) {
ArrayList<Boolean> 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, "operations_destination", operationsDestination, (Integer val) -> val + 1,
Optional.of(-1));
writer.write("\n");
}
private void unmooredCargoOp() throws IOException {
ArrayList<Set<Integer>> relatedUnmooredCargoOp = new ArrayList<>();
for (int i = 0; i < locationNumberById.size(); i++) {
relatedUnmooredCargoOp.add(new TreeSet<>());
private void cargoOpUsingObj() throws IOException {
ArrayList<Set<Integer>> 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<Set<Integer>> relatedCargoOpUsingObjAsMain = new ArrayList<>();
for (int i = 0; i < movingObjects.size(); i++) {
relatedCargoOpUsingObjAsMain.add(new TreeSet<>());
private void addOpWithNominallyMooring() throws IOException {
ArrayList<ArrayList<Set<Integer>>> 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<MovingObject> calcMovingObjects(TaskCase taskCase) {
ArrayList<MovingObject> movingObjects = new ArrayList<>();
movingObjects.addAll(taskCase.getShips());
movingObjects.addAll(taskCase.getBunkers());
movingObjects.addAll(taskCase.getTows());
movingObjects.addAll(taskCase.getEquipments());
return movingObjects;
}
/* Каждую операцию лишает типизации по главному действующему лицу. */
public static ArrayList<OperationTemplate> renumberOperations(TaskCase task) {
TreeMap<Integer, ArrayList<MovingObject>> 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<MovingObject> 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<ArrayList<Boolean>> getIsFixedArray() {
......@@ -1158,9 +1268,9 @@ public class ConversionUtil {
}
ArrayList<ArrayList<Boolean>> 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<Boolean> 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<ArrayList<Boolean>> locMovingOpOfObj = new ArrayList<>();
locMovingOpOfObj.add(new ArrayList<>());
for (int i = 0; i <= operationTemplates.size(); i++) {
locMovingOpOfObj.get(0).add(false);
}
for (ArrayList<Integer> operations : movingOpOfObj) {
ArrayList<Boolean> 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<Integer> mainObjStartLoc = new ArrayList<>();
ArrayList<Boolean> 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,8 +1395,27 @@ 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<Integer> mainObjStartLoc = new ArrayList<>();
ArrayList<Integer> 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));
}
/* С типизацией. */
......@@ -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<Operation> 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")) {
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 \"op_status\" in input");
throw new ParserException("No \"" + keyArray + "\" in input");
}
}
}
if (result != -1) {
Task task = new Task(taskCase, "");
operations = new ArrayList<>();
ArrayList<ArrayList<String>> opStatus = arrays.get("op_status");
ArrayList<OperationTemplate> templates = new ArrayList<>(task.getTemplates());
if (task.isTypified()) {
templates = Task.renumberOperations(task);
ArrayList<OperationTemplate> templates = new ArrayList<>(taskCase.getTemplates());
if (taskCase.isTypified()) {
templates = Task.renumberOperations(taskCase);
}
Map<Integer, OperationTemplate> operationById = new TreeMap<>();
for (OperationTemplate operation : task.getTemplates()) {
for (OperationTemplate operation : taskCase.getTemplates()) {
operationById.put(operation.getId(), operation);
}
Map<Integer, MovingObject> objByNo = new TreeMap<>();
ArrayList<ArrayList<Boolean>> isFixed;
{
Task t = new Task(task, "");
ArrayList<MovingObject> 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);
for (MovingObject obj : task.getMovingObjects()) {
objByNo.put(task.getMObjNumberById().get(obj.getId()), obj);
}
isFixed = t.getIsFixedArray();
}
isFixed = task.getIsFixedArray();
Set<String> 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<MovingObject> resources = new ArrayList<>();
// TODO ускорить.
ArrayList<ArrayList<String>> 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);
}
......
......@@ -6,6 +6,7 @@ package inport;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
/**
......@@ -16,6 +17,8 @@ public class LoadingTemplate extends OperationTemplate {
private TransportShip loader;
private OptionalInt loaderType = OptionalInt.empty();
private Optional<Bunker> bunker = Optional.empty();
private OptionalInt bunkerType = OptionalInt.empty();
private Storage storage;
private List<LoadingEquipment> resources;
private List<Integer> 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<Bunker> getBunker() {
return bunker;
}
public void setBunker(Optional<Bunker> 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<Integer> resourcesTypes, boolean withMooring, double intensity, int id) {
public LoadingTemplate(TransportShip loader,
Berth berth,
Storage storage,
Cargo cargo,
Optional<Bunker> bunker,
List<Integer> 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");
}
}
......@@ -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<MovingObject> movingObjects = new ArrayList<>();
movingObjects.addAll(task.getShips());
movingObjects.addAll(task.getTows());
movingObjects.addAll(task.getEquipments());
ArrayList<MovingObject> movingObjects = Task.calcMovingObjects(task);
Map<Integer, MovingObject> objByNo = new TreeMap<>();
for (MovingObject obj : movingObjects) {
......
......@@ -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> bunker = Optional.empty();
private List<MovingObject> resources;
public Optional<Bunker> getBunker() {
return bunker;
}
public void setBunker(Optional<Bunker> 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) {
......
......@@ -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<Integer, Cargo> cargoes) {
......
......@@ -82,15 +82,24 @@ public class StorageState {
return "";
}
public StorageState(String s, Map<Integer, Storage> mp, Map<Integer, MovingObject> vp, Map<Integer, Cargo> cp) {
public StorageState(String s,
Map<Integer, Storage> mp,
Map<Integer, MovingObject> vp,
Map<Integer, Bunker> bunkers,
Map<Integer, Cargo> 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());
}
......
......@@ -35,6 +35,9 @@ public class TaskCase {
// Обслуживаемые суда
private List<TransportShip> ships;
// Типы бункеровщиков.
private Map<Integer, String> bunkerTypes;
// Типы обслуживаемых судов
private Map<Integer, String> vesselTypes;
......@@ -67,6 +70,13 @@ public class TaskCase {
// План - решение
private List<Operation> solution;
public Map<Integer, String> getBunkerTypes() {
return bunkerTypes;
}
public void setBunkerTypes(Map<Integer, String> 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<Integer, Berth> m_berth, Map<Integer, MovingObject> m_vessel)
private MovingObjectState fromString(String s,
Map<Integer, Berth> m_berth,
Map<Integer, MovingObject> m_vessel,
Map<Integer, Bunker> 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<Integer, Berth> m_berth = new HashMap<>();
Map<Integer, Storage> m_storage = new HashMap<>();
Map<Integer, MovingObject> m_vessel = new HashMap<>();
Map<Integer, Bunker> m_bunker = new HashMap<>();
Map<Integer, LoadingEquipment> m_equipment = new HashMap<>();
Map<Integer, OperationTemplate> 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<Integer, Integer, Integer> 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<Integer, String> e : vesselTypes.entrySet()) {
writer.write(e.getKey() + "; " + e.getValue() + "\n");
}
writer.write("\n" + Tag.Bunker_Types.text + "\n");
for (Map.Entry<Integer, String> e : bunkerTypes.entrySet()) {
writer.write(e.getKey() + "; " + e.getValue() + "\n");
}
}
writer.write("\nBunkers"+"\n");
for (Bunker c : bunkers)
writer.write(c.toString()+"\n");
......
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 [])
......@@ -69,7 +69,7 @@ Final Storage State
Task Properties
30.0; 0
22.0; 0
Solution
......
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