Commit 67d4ca3f authored by Vladislav Kiselev's avatar Vladislav Kiselev

Добавлены ограничения с вариативной интенсивностью.

parent a73c7d1e
using CP;
int n_intervals = ...;
int n_operations = ...;
int n_locations = ...;
int n_moving_obj = ...;
dvar boolean op_status[0..n_operations][0..(n_intervals + 1)];
dvar boolean op_start[0..n_operations][0..(n_intervals + 1)];
int moving_op_of_obj[0..n_moving_obj][0..n_operations] = ...;
// Текущая операция операция перемещения, в которой задействован данный объект.
dvar int current_moving_operation[0..n_moving_obj][0..(n_intervals + 1)] in 0..n_operations;
// Является ли данная операция операцией перемещения.
int is_moving_operation[0..n_operations] = ...;
// Главный объект (субъект) операции.
int main_obj_of_operation[0..n_operations] = ...;
// Объект, пришвартованный к данной локации.
dvar int current_moored_obj[0..n_locations, 0..(n_intervals + 1)] in 0..n_moving_obj;
// Операции с условной швартовкой.
int op_with_nominally_mooring_max_size = ...;
int op_with_nominally_mooring_sizes[0..n_locations, 0..n_moving_obj] = ...;
int op_with_nominally_mooring[0..n_locations, 0..n_moving_obj, 1..op_with_nominally_mooring_max_size] = ...;
// Местоположение объекта или пункт назначения (если объект движется) перед началом определённого интервала.
dvar int m_obj_loc[0..n_moving_obj, 0..(n_intervals + 1)] in 0..n_locations;
int twin_location[1..n_locations];
int main_location[1..n_locations];
execute initializeArray {
for(var i = 1; i <= n_locations; i++) {
twin_location[i] = i - 1 + (i % 2) * 2;
main_location[i] = i - ((i + 1) % 2);
}
}
int operations_destination[0..n_operations] = ...; // Локация в которой окажется объект после завершения операции.
// Является ли операция швартовкой/отшвартовкой.
int is_mooring_op[0..n_operations] = ...;
int initial_m_obj_loc[0..n_moving_obj] = ...;
int final_m_obj_loc[0..n_moving_obj] = ...;
// Операции, которые могут задействовать данный объект как ресурс.
{int} operations_that_used_obj_as_resource [0..n_moving_obj] = ...;
// Операция, в которой участвует данный объект как ресурс.
dvar int participation_as_resource[0..n_moving_obj, 0..(n_intervals + 1)] in 0..n_operations;
int n_resources_types = ...; // Количество различных типов ресурсов.
{int} objects_of_type[1..n_resources_types] = ...; // Все объекты конкретного типа.
int n_resources_counters = ...; // Количество счётчиков ресурсов.
// Счётчик ресурсов.
dvar int resources_counter[1..n_resources_counters , 1..n_intervals];
int counter_type[1..n_resources_counters] = ...; // Типы ресурсов, за которыми следят счётчики.
int operation_of_counter[1..n_resources_counters] = ...; // Операция, которой принадлежит данный счётчик.
int required_counter_values[1..n_resources_counters] = ...; // Необходимые значения на счётчиках ресурсов для выполнения операции.
{int} counters_of_operation[0..n_operations] = ...; // Счётчики, которые относятся к данной операции.
dvar boolean is_involved_in_cargo_op[0..n_moving_obj, 0..n_intervals];
// Операции погрузки, которые используют этот объект в качестве главного или в качестве бункеровщика.
{int} related_cargo_op[0..n_moving_obj] = ...;
// Операции отшвартовки, которые используют объект в качестве главного.
{int} related_unmooring_op[0..n_moving_obj] = ...;
// Требуемое положение конкретных типов объектов в момент начала операций.
int operations_resources_start_loc[1..n_resources_counters] = ...;
// Требуемое положение главного объекта в момент начала операций.
int main_obj_start_loc[0..n_operations] = ...;
// Требуемое положение бункеровщика в момент начала операции.
int bunker_start_loc[0..n_operations] = ...;
// Бункеровщик, участвующий в операции погрузки (0, если такогого нет или это не погрузка).
int bunker_of_cargo_op[0..n_operations] = ...;
int operations_duration[0..n_operations] = ...;
int is_continuous_operation[0..n_operations] = ...;
{int} conflicting_operations[0..n_operations] = ...;
int bad_weather[0..n_operations, 0..n_intervals] = ...;
int n_cargo_types = ...;
int n_all_storage_sections = ...;
dvar int storage_used_volume[0..n_all_storage_sections, 0..(n_intervals + 1)];
int max_storage_vol[0..n_all_storage_sections] = ...;
int initial_storage_vol[0..n_all_storage_sections] = ...;
int final_storage_vol[0..n_all_storage_sections] = ...;
int cargo_flows[0..n_all_storage_sections, 0..(n_intervals + 1)] = ...;
int n_loading_op = ...;
int loading_op_delta_of_main_obj[0..n_operations] = ...;
int loading_op_abs_delta[0..n_operations] = ...;
int loading_op_direction[0..n_operations] = ...;
int operations_main_stor[0..n_operations] = ...;
int operations_secondary_stor[0..n_operations] = ...;
int operations_cargo_t[0..n_operations] = ...;
int loading_op_delta[1..n_loading_op] = ...;
int loading_op_local_direction[1..n_loading_op] = ...;
int loading_op_n[1..n_loading_op] = ...; // Номера среди общего списка операций.
{int} involved_operations[1..n_all_storage_sections] = ...;
{int} sections_of_moving_obj[1..n_moving_obj] = ...;
int is_sections_of_moving_obj_empty[1..n_moving_obj] = ...;
// Интенсивность операций погрузки.
dvar int cargo_op_intensity[0..n_operations, 0..(n_intervals + 1)];
int n_fixed_op = ...;
int fixed_op[1..n_fixed_op] = ...;
{int} fixed_op_resources[1..n_fixed_op] = ...;
int fixed_op_start[1..n_fixed_op] = ...;
int fixed_op_end[1..n_fixed_op] = ...; // Включительно.
int fixed_op_intensity[1..n_fixed_op] = ...;
int is_fixed[0..n_operations, 0..n_intervals] = ...;
int is_obj_involved_in_fixed_op[0..n_moving_obj, 0..(n_intervals + 1)] = ...;
int min_positive_cargo_val[1..n_all_storage_sections, 1..n_locations] = ...; // Объём максимальной положительной операции, которая может быть произведена с этой секцией в этом хранилище. Если в локации таковой нет, то это значение объёма хранилища + 1.
int max_negative_cargo_val[1..n_all_storage_sections, 1..n_locations] = ...;
int can_obj_leave_loc_only_alone[1..n_moving_obj, 1..n_locations] = ...;
int is_fixed_op_planned_in_future[1..n_moving_obj, 1..n_locations, 1..n_intervals] = ...;
// Возможно ли начать операцию в данный интервал (если предположить, что операция длится 1 интервал).
dvar boolean is_op_possible[0..n_operations, 1..n_intervals];
// Счётчик ресурсов, которые могут быть потенциально задействованы в операции.
dvar int possible_resources_counter[1..n_resources_counters , 1..n_intervals];
dvar boolean is_enough_free_resources[0..n_operations, 1..n_intervals];
dvar boolean can_obj_theoretically_use_cargo_op[0..n_moving_obj, 0..(n_intervals + 1)];
// Остановился ли объект окончательно, начиная с данного интервала.
dvar boolean is_obj_totally_terminated[0..n_moving_obj, 0..(n_intervals + 1)];
dvar int prev_m_obj_loc[0..n_moving_obj, 0..(n_intervals + 1)] in 1..n_locations;
dvar boolean is_obj_involved_in_useful_operation[0..n_moving_obj, 0..(n_intervals + 1)];
// Успел ли объект поучаствовать в полезной операции к концу данного интервала.
dvar boolean is_attended_useful_op_in_cur_loc[0..n_moving_obj, 0..(n_intervals + 1)];
dvar boolean is_cargo_op_not_exceeds_storage_limits[1..n_operations, 1..n_intervals];
dvar boolean is_not_terminated[1..(n_intervals + 1)];
minimize sum (i in 1..(n_intervals + 1)) is_not_terminated[i];
subject to {
forall (t in 0..(n_intervals + 1)) (op_status[0, t] == 0); // Фиктивная операция.
forall (t in 0..(n_intervals + 1)) ( op_start[0, t] == 0); // Фиктивная операция.
// Определение current_moving_operation.
forall (t in 0..(n_intervals + 1)) (current_moving_operation[0, t] == 0); // Фиктивный объект.
// Крайние значения.
forall (obj in 1..n_moving_obj, t in {0, n_intervals + 1}) (
current_moving_operation[obj, t] == 0
);
// Текущая операция лежит в множестве тех, которые затрагивают данный объект.
forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
(current_moving_operation[obj, t] != 0) => (moving_op_of_obj[obj, current_moving_operation[obj, t]] != 0)
);
// Если операция, затрагивающая данный объект в качестве главного, выполняется - то именно она текущая операция перемещения для этого объекта.
forall (op in 1..n_operations, t in 1..n_intervals : (is_moving_operation[op] == 1)) (
(op_status[op, t] == 1) => (current_moving_operation[main_obj_of_operation[op], t] == op)
);
// Связь current_moving_operation c op_status.
forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
(current_moving_operation[obj, t] != 0) => (op_status[current_moving_operation[obj, t], t] == 1)
);
// Определение current_moored_obj.
forall (t in 0..(n_intervals + 1)) (current_moored_obj[0, t] == 0); // Фиктивная локация.
// Фиксирование неиспользуемых значений.
forall (loc in 1..n_locations, t in 0..(n_intervals + 1) : loc mod 2 == 1) (
current_moored_obj[loc, t] == 0
);
// Крайние значения.
forall (loc in 1..n_locations, t in {0, n_intervals + 1}) (
current_moored_obj[loc, t] == 0
);
// current_moored_obj соответствуе какому-либо реально пришвартованному объекту.
forall (loc in 1..n_locations, t in 1..n_intervals : loc mod 2 == 0) (
(current_moored_obj[loc, t] != 0) => ((m_obj_loc[current_moored_obj[loc, t], t] == loc) ||
(or (id in 1..op_with_nominally_mooring_max_size) // new!!!
op_status[op_with_nominally_mooring[loc, current_moored_obj[loc, t], id], t] == true
))
);
// Если объект пришвартован или швартуется, то current_moored_obj об это знает.
forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
(m_obj_loc[obj, t] mod 2 == 0) => (current_moored_obj[m_obj_loc[obj, t], t] == obj)
);
// Если выполняется операция, где судно условно пришвартовано, то current_moored_obj знает об этом.
forall (loc in 1..n_locations,
obj in 1..n_moving_obj,
op_id in 1..op_with_nominally_mooring_sizes[loc, obj],
t in 1..n_intervals) (
(op_status[op_with_nominally_mooring[loc, obj, op_id], t] == 1) => (current_moored_obj[loc, t] == obj)
);
// Определение m_obj_loc.
forall (t in 0..(n_intervals + 1)) (m_obj_loc[0, t] == 0); // Фиктивный объект.
// За фиктивный нулевой интервал объект не успевает ничего сделать с начальным положением.
forall (obj in 1..n_moving_obj) (
m_obj_loc[obj, 1] == m_obj_loc[obj, 0]
);
// Направление движения/местоположение объекта может измениться только если перед этим началась операция перемещения, и он не вспомогательный при операции швартовки.
forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) (
((current_moving_operation[obj, t - 1] != current_moving_operation[obj, t - 2]) &&
(current_moving_operation[obj, t - 1] != 0) &&
((obj == main_obj_of_operation[current_moving_operation[obj, t - 1]])
||
(is_mooring_op[current_moving_operation[obj, t - 1]] == 0)
)
) => (m_obj_loc[obj, t] == operations_destination[current_moving_operation[obj, t - 1]])
);
forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) (
((current_moving_operation[obj, t - 1] == current_moving_operation[obj, t - 2]) ||
(current_moving_operation[obj, t - 1] == 0) ||
((obj != main_obj_of_operation[current_moving_operation[obj, t - 1]])
&&
( is_mooring_op[current_moving_operation[obj, t - 1]] == 1)
)
) => (m_obj_loc[obj, t] == m_obj_loc[obj, t - 1])
);
// Начальное состояние.
forall (i in 1..n_moving_obj) (m_obj_loc[i, 0] == initial_m_obj_loc[i]);
// Конечное состояние.
forall (i in 1..n_moving_obj) (
(final_m_obj_loc[i] != 0) =>
(m_obj_loc[i, n_intervals + 1] == final_m_obj_loc[i])
);
// Определение op_status, op_start.
forall (i in 1..n_operations, j in {0, n_intervals + 1}) (op_status[i, j] == 0); // Краевые значения.
forall (op in 1..n_operations, j in {0, n_intervals + 1}) (op_start[op, j] == 0);
forall (i in 1..n_operations, j in 1..(n_intervals + 1)) (op_start[i, j] == ((op_status[i, j] == 1) && (op_status[i, j - 1] == 0)));
// Связь ресурсов с операцией и основным объектом.
forall (t in 0..(n_intervals + 1)) (participation_as_resource[0, t] == 0); // Фиктивный объект.
// Граничные значения.
forall (obj in 1..n_moving_obj) (participation_as_resource[obj, 0] == 0);
forall (obj in 1..n_moving_obj) (participation_as_resource[obj, n_intervals + 1] == 0);
// Только те операции, которые затрагивают данный объект.
forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
(participation_as_resource[obj, t] != 0)
=> participation_as_resource[obj, t] in operations_that_used_obj_as_resource[obj]
);
// Связь с текущими операциями перемещения.
// Если объект задействован в операции перемещения, которая использует его как ресурс,
// то participation_as_resource должен указывать на эту операцию.
forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
(current_moving_operation[obj, t] in operations_that_used_obj_as_resource[obj])
=>
(participation_as_resource[obj, t] == current_moving_operation[obj, t])
);
// Если объект участвует как ресурс в операции перемещения, то это согласованно с current_moving_operation.
forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
((participation_as_resource[obj, t] != 0) &&
(is_moving_operation[participation_as_resource[obj, t]] == 1)
) => (participation_as_resource[obj, t] == current_moving_operation[obj, t])
);
// { Объект участвует где-то в качестве ресурса - соответствующая операция обязана быть активной. }
forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
(participation_as_resource[obj, t] != 0) => (op_status[participation_as_resource[obj, t], t] == 1)
);
// От начала операции и до конца её ресурсы не могут измениться (в том числе и для погрузки).
forall (obj in 1..n_moving_obj, t in 1..(n_intervals - 1)) (
((participation_as_resource[obj, t] != 0) &&
(op_status[participation_as_resource[obj, t], t + 1] == 1)
) => (participation_as_resource[obj, t + 1] == participation_as_resource[obj, t])
);
// Участие всех необходимых ресурсов в операции.
forall (t in 1..n_intervals, op in 1..n_operations, counter in counters_of_operation[op]) (
(op_status[op, t] == 1) => (resources_counter[counter, t] == required_counter_values[counter])
);
// Определение resources_counter.
forall (counter in 1..n_resources_counters, t in 1..n_intervals) (
resources_counter[counter, t] == sum (obj in objects_of_type[counter_type[counter]]) (
participation_as_resource[obj, t] == operation_of_counter[counter]
)
);
// Участие объекта в операциях грузообработки.
forall (t in 1..n_intervals) (is_involved_in_cargo_op[0, t] == 0); // Фиктивный объект.
forall (obj in 1..n_moving_obj) (is_involved_in_cargo_op[obj, 0] == 0);
// Определение is_involved_in_cargo_op.
forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
is_involved_in_cargo_op[obj, t] == (
(or (op in related_cargo_op[obj]) (op_status[op, t] == true))
||
((participation_as_resource[obj, t] != 0) && (is_moving_operation[participation_as_resource[obj, t]] == 0))
)
);
// Операции перемещения исключают операции грузообработки и наоборот.
forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
(is_involved_in_cargo_op[obj, t] == 1) => (current_moving_operation[obj, t] == 0)
);
// Наличие всех объектов на месте во время начала операции перемещения + готовность к началу.
// Наличие на месте всех ресурсов.
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] == 1)
) => (m_obj_loc[obj, t] == operations_resources_start_loc[counter])
);
// Наличие главных объектов на месте.
forall (op in 1..n_operations, t in 1..n_intervals) (
(op_start[op, t] == 1) => (m_obj_loc[main_obj_of_operation[op], t] == main_obj_start_loc[op])
);
// Наличие бункеровщиков на месте.
forall (op in 1..n_operations,
t in 1..n_intervals
: bunker_of_cargo_op[op] != 0) (
(op_start[op, t] == 1) => (m_obj_loc[bunker_of_cargo_op[op], t] == bunker_start_loc[op])
);
// Непрерывность перемещения и швартовки.
forall (i in 1..n_operations : is_continuous_operation[i] == 1)
forall (j in 1..(n_intervals - operations_duration[i] + 1))
forall (k in 1..(operations_duration[i] - 1))
(op_start[i, j] == 1) => (
(op_status[i, j + k] == 1)
&&
(op_status[i, j + operations_duration[i]] == 0)
)
;
forall (i in 1..n_operations : is_continuous_operation[i] == 1)
forall (j in (n_intervals - operations_duration[i] + 2)..(n_intervals + 1)) (op_start[i, j] == 0)
;
// Конфликтующие операции.
forall (op in 1..n_operations, t in 0..(n_intervals + 1), conf_op in conflicting_operations[op]) (
(op_status[op, t] == 1) => (op_status[conf_op, t] == 0)
);
// Окна непогоды.
forall (op in 1..n_operations, t in 1..n_intervals) (
(bad_weather[op, t] == 1) => (op_status[op, t] == 0)
);
// Грузообработка.
forall (t in 0..(n_intervals + 1)) (storage_used_volume[0, t] == 0); // Фиктивный объект.
// Ограничения на вместимость.
// Максимальный объём.
forall (storage in 1..n_all_storage_sections, t in 0..(n_intervals + 1)) (
(storage_used_volume[storage, t]) <= max_storage_vol[storage]
);
// Неотрицательность объёма.
forall (storage in 1..n_all_storage_sections, t in 0..(n_intervals + 1)) (
0 <= storage_used_volume[storage, t]
);
// Ограничения на граничные значения.
forall (storage in 1..n_all_storage_sections) ( // Initial values.
storage_used_volume[storage, 0] == initial_storage_vol[storage]
);
forall (storage in 1..n_all_storage_sections // Final values.
: final_storage_vol[storage] >= 0) (
storage_used_volume[storage, n_intervals + 1] == final_storage_vol[storage]
);
// Изменение грузов в хранилищах.
forall (t in 0..(n_intervals + 1)) (cargo_op_intensity[0, t] == 0); // Фиктивная операция.
forall (op in 1..n_operations, t in 0..(n_intervals + 1)) (cargo_op_intensity[op, t] >= 0);
forall (op in 1..n_operations, t in 0..(n_intervals + 1)) (cargo_op_intensity[op, t] <= loading_op_abs_delta[op]);
// Связь с операциями грузообработки.
forall (op in 1..n_operations, t in 0..(n_intervals + 1) : (is_moving_operation[op] == 0)) (
(cargo_op_intensity[op, t] > 0) => (op_status[op, t] == 1)
);
forall (op in 1..n_operations, t in 0..(n_intervals + 1) : (is_moving_operation[op] == 0)) (
cargo_op_intensity[op, t] == 0
);
forall (op in 1..n_operations, t in 0..(n_intervals + 1) : (is_moving_operation[op] == 0)) (
(op_status[op, t] == 1) => (cargo_op_intensity[op, t] > 0)
);
forall (storage in 1..n_all_storage_sections, t in 1..(n_intervals + 1)) (
storage_used_volume[storage, t] == (
storage_used_volume[storage, t - 1] +
cargo_flows[storage, t] +
sum (inv_op in involved_operations[storage]) (
cargo_op_intensity[loading_op_n[inv_op], t] *
loading_op_local_direction[inv_op]
)
)
);
// Фиксированные операции.
forall (no in 1..n_fixed_op)
forall (t in fixed_op_start[no]..fixed_op_end[no])
((op_status[fixed_op[no], t] == 1) &&
(cargo_op_intensity[fixed_op[no], t] == fixed_op_intensity[no]))
;
forall (no in 1..n_fixed_op)
forall (t in fixed_op_start[no]..fixed_op_end[no])
forall (obj in fixed_op_resources[no]) (
participation_as_resource[obj, t] == fixed_op[no]
)
;
// Оптимизация - сдвиг в начало.
forall (t in 1..n_intervals) (is_op_possible[0, t] == false); // Фиктивный объект.
// Определение possible_resources_counter.
forall (counter in 1..n_resources_counters, t in 1..n_intervals) (
possible_resources_counter[counter, t] == sum (obj in objects_of_type[counter_type[counter]]) (
(participation_as_resource[obj, t] == 0) &&
(current_moving_operation[obj, t] == 0) &&
(m_obj_loc[obj, t] == operations_resources_start_loc[counter])
)
);
// Достаточно ли свободных ресурсов для операции.
forall (t in 1..n_intervals) (is_enough_free_resources[0, t] == false); // Фиктивный объект.
forall (op in 1..n_operations, t in 1..n_intervals) (
is_enough_free_resources[op, t] == and (counter in counters_of_operation[op]) (
possible_resources_counter[counter, t] >= required_counter_values[counter]
)
);
forall (op in 1..n_operations, t in 1..n_intervals) (
is_cargo_op_not_exceeds_storage_limits[op, t] ==
((is_moving_operation[op] == 0) => (
(storage_used_volume[operations_main_stor[op], t] + loading_op_direction[op] >= 0) &&
(storage_used_volume[operations_main_stor[op], t] + loading_op_direction[op] <= max_storage_vol[operations_main_stor[op]]) &&
(storage_used_volume[operations_secondary_stor[op], t] - loading_op_direction[op] >= 0) &&
(storage_used_volume[operations_secondary_stor[op], t] - loading_op_direction[op] <= max_storage_vol[operations_secondary_stor[op]])
))
);
// Определение is_op_possible.
forall (op in 1..n_operations, t in 1..n_intervals) (
is_op_possible[op, t] == (
(bad_weather[op, t] == 0) && // Погода не мешает.
(m_obj_loc[main_obj_of_operation[op], t] == main_obj_start_loc[op])
&& // Главный объект на месте.
(current_moving_operation[main_obj_of_operation[op], t] == 0)
&& // Главный объект не участвует в операции перемещеня.
(is_enough_free_resources[op, t] == true) && // Достаточно свободных ресурсов на нужном месте.
(and (conf_op in conflicting_operations[op]) (op_status[conf_op, t] == false))
&& // Не выполняется ни одной конфликтующей операции.
((is_moving_operation[op] == 1) => is_involved_in_cargo_op[main_obj_of_operation[op], t] == false)
&& // Если это операция перемещения, то главный объект
// не участвует в операциях погрузки.
(((is_mooring_op[op] == 1) && (operations_destination[op] mod 2 == 0)) => (
current_moored_obj[operations_destination[op], t] == 0)
) && // Если это операция пришвартовки, то в этот интервал
// причал должен быть свободным.
(is_cargo_op_not_exceeds_storage_limits[op, t] == 1) && // Если это операция грузообработки, то она не выведет
// объём берегового хранилища и хранилища судна за
// границы дозволенного.
(((is_moving_operation[op] == 0) && (main_obj_start_loc[op] mod 2 == 1)) =>
((current_moored_obj[twin_location[main_obj_start_loc[op]], t] == 0) ||
(current_moored_obj[twin_location[main_obj_start_loc[op]], t] == main_obj_of_operation[op]))
) && // Если это операция грузообработки без пришвартовки,
// то причал должен быть свободен в этот интервал, либо
// главный объект должен быть уже условно пришвартован.
(((bunker_of_cargo_op[op] != 0) && (op_status[op, t] == 0)) =>
((m_obj_loc[bunker_of_cargo_op[op], t] == bunker_start_loc[op]) &&
(current_moving_operation[bunker_of_cargo_op[op], t] == 0))
) // Бункеровщик (если есть) находится в нужной локации
// и не участвует в операциях перемещения.
)
);
// Сам критерий оптимизации - если если операцию можно было начать на 1 интервал раньше, то её нужно начать раньше.
forall (op in 1..n_operations, t in 2..n_intervals) (
((op_start[op, t] == 1) && (is_fixed[op, t] == 0)) => (is_op_possible[op, t - 1] == 0)
);
// Оптимизация - есть две соседние операции погрузки - первая операция должна быть максимально загруженной.
forall (op in 1..n_operations, t in 2..n_intervals) (
((cargo_op_intensity[op, t - 1] != 0) && (cargo_op_intensity[op, t] != 0)) => (
(cargo_op_intensity[op, t - 1] == loading_op_abs_delta[op]) || // Операция достигла предела интенсивности.
(is_cargo_op_not_exceeds_storage_limits[op, t - 1] == 0) // Или операция нарушит границы хранилищ
|| // при увеличении интенсивности.
(is_fixed[op, t] == 1) // Или операция фиксирована.
)
);
// Оптимизация - судно возвращается откуда перед этим пришло -> оно сделало или делает что-то "полезное".
forall (t in 0..(n_intervals + 1)) (prev_m_obj_loc[0, t] == 1);
forall (t in 0..(n_intervals + 1)) (is_obj_involved_in_useful_operation[0, t] == 0);
// Определение prev_m_obj_loc
forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) (
(m_obj_loc[obj, t - 1] != m_obj_loc[obj, t]) => (prev_m_obj_loc[obj, t] == m_obj_loc[obj, t - 1])
);
forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) (
(m_obj_loc[obj, t - 1] == m_obj_loc[obj, t]) => (prev_m_obj_loc[obj, t] == prev_m_obj_loc[obj, t - 1])
);
forall (obj in 1..n_moving_obj) (prev_m_obj_loc[obj, 0] == m_obj_loc[obj, 0]);
// Определение is_obj_involved_in_useful_operation
forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) (
is_obj_involved_in_useful_operation[obj, t] == (
(participation_as_resource[obj, t] != 0)
|| (or (op in related_cargo_op[obj]) (op_status[op, t] == 1))
|| (is_obj_involved_in_fixed_op[obj, t] == 1)
|| (or (op in related_unmooring_op[obj]) (op_status[op, t] == 1))
)
);
forall (obj in 1..n_moving_obj) (is_obj_involved_in_useful_operation[obj, 0] == 0);
// Определение is_attended_useful_op_in_cur_loc
forall (t in 0..(n_intervals + 1)) (is_attended_useful_op_in_cur_loc[0, t] == 0);
forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) (
is_attended_useful_op_in_cur_loc[obj, t] == (
((is_attended_useful_op_in_cur_loc[obj, t - 1] == 1) && (m_obj_loc[obj, t - 1] == m_obj_loc[obj, t])) // Предыдущее значение в текущей локации.
||
(is_obj_involved_in_useful_operation[obj, t] == 1)
||
(is_obj_involved_in_useful_operation[obj, t - 1] == 1) // Учитывает случай когда операция перемещения, из-за которой объект попал в локацию была нужна.
)
);
// Сама оптимизация - если объект
forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) (
((m_obj_loc[obj, t - 1] != m_obj_loc[obj, t]) && (prev_m_obj_loc[obj, t - 1] == m_obj_loc[obj, t])
) => (is_attended_useful_op_in_cur_loc[obj, t - 1] == 1)
);
// Оптимизация - если объект не может совершить в данной локации операции без выхода за границы хранилища, а так же если он
// может уйти только своим ходом, то он либо уходит немедленно, либо остаётся на месте навсегда.
// Определение can_obj_theoretically_use_cargo_op.
forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) (
can_obj_theoretically_use_cargo_op[obj, t] == (
(is_sections_of_moving_obj_empty[obj] == 1)
||
or (section in sections_of_moving_obj[obj]) (
(storage_used_volume[section, t - 1] + min_positive_cargo_val[section, main_location[m_obj_loc[obj, t]]] <= max_storage_vol[section])
|| (storage_used_volume[section, t - 1] + max_negative_cargo_val[section, main_location[m_obj_loc[obj, t]]] >= 0)
)
)
);
forall (t in 0..(n_intervals + 1)) (can_obj_theoretically_use_cargo_op[0, t] == false);
forall (obj in 1..n_moving_obj) (can_obj_theoretically_use_cargo_op[obj, 0] == false);
forall (obj in 1..n_moving_obj) (is_obj_totally_terminated[obj, n_intervals + 1] == true);
forall (t in 0..(n_intervals + 1)) (is_obj_totally_terminated[0, t] == true);
forall (obj in 1..n_moving_obj, t in 0..n_intervals) (
is_obj_totally_terminated[obj, t] == (
(current_moving_operation[obj, t] == 0)
&& (is_involved_in_cargo_op[obj, t] == 0)
&& (is_obj_totally_terminated[obj, t + 1] == 1)
)
);
// Само ограничение.
forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
( (can_obj_leave_loc_only_alone[obj, m_obj_loc[obj, t]] == 1)
&& (can_obj_theoretically_use_cargo_op[obj, t] == 0)
&& (is_fixed_op_planned_in_future[obj, m_obj_loc[obj, t], t] == 0)
) =>
((is_obj_totally_terminated[obj, t] == 1) || (current_moving_operation[obj, t] != 0))
);
// Критерий оптимизации
// В конце всё остановится.
(is_not_terminated[n_intervals + 1] == 0);
// Действия ещё не остановились, если в текущий интервал что-нибудь происходит или они не остановятся в следующий интервал.
forall (t in 1..n_intervals) (
is_not_terminated[t] == (
(or (op in 1..n_operations) (op_status[op, t] == true))
||
(is_not_terminated[t + 1] == 1)
)
);
}
execute {
writeln("op_status = ", op_status, ";");
writeln("m_obj_loc = ", m_obj_loc, ";");
writeln("op_start = ", op_start, ";");
writeln("is_not_terminated = ", is_not_terminated, ";");
writeln("storage_used_volume = ", storage_used_volume, ";");
writeln("current_moving_operation = ", current_moving_operation, ";");
writeln("resources_counter = ", resources_counter, ";");
writeln("operation_of_counter = ", operation_of_counter, ";");
writeln("participation_as_resource = ", participation_as_resource, ";");
writeln("is_involved_in_cargo_op = ", is_involved_in_cargo_op, ";");
writeln("cargo_op_intensity = ", cargo_op_intensity, ";");
writeln("is_op_possible = ", is_op_possible, ";");
}
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