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 интервал).
// За фиктивный нулевой интервал объект не успевает ничего сделать с начальным положением.
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]);
(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])