Commit c8542a5d authored by Vladislav Kiselev's avatar Vladislav Kiselev

Типизация.

parent 7098b577
...@@ -11,7 +11,7 @@ array [1..n_operations, 0..(n_intervals + 1)] of var bool : op_fin; ...@@ -11,7 +11,7 @@ array [1..n_operations, 0..(n_intervals + 1)] of var bool : op_fin;
int : moving_op_of_obj_max_size; int : moving_op_of_obj_max_size;
array [1..n_moving_obj] of 0..moving_op_of_obj_max_size : moving_op_of_obj_sizes; array [1..n_moving_obj] of 0..moving_op_of_obj_max_size : moving_op_of_obj_sizes;
array [1..n_moving_obj, 1..moving_op_of_obj_max_size] of 1..n_operations : moving_op_of_obj; % Операции перемещения затрагивающие данный объект. array [1..n_moving_obj, 0..moving_op_of_obj_max_size] of 1..n_operations : moving_op_of_obj; % Операции перемещения затрагивающие данный объект.
% Определение current_moving_operation. % Определение current_moving_operation.
% Текущая операция операция перемещения, в которой задействован данный объект. % Текущая операция операция перемещения, в которой задействован данный объект.
...@@ -21,16 +21,34 @@ array [1..n_moving_obj, 1..moving_op_of_obj_max_size] of 1..n_operations : movin ...@@ -21,16 +21,34 @@ array [1..n_moving_obj, 1..moving_op_of_obj_max_size] of 1..n_operations : movin
constraint forall (obj in 1..n_moving_obj, t in 0..(n_intervals + 1)) ( constraint forall (obj in 1..n_moving_obj, t in 0..(n_intervals + 1)) (
current_moving_operation[obj, t] <= moving_op_of_obj_sizes[obj] current_moving_operation[obj, t] <= moving_op_of_obj_sizes[obj]
); );
% Если операция, затрагивающая данный объект в качестве главного, выполняется - то именно она текущая операция перемещения для этого объекта.
constraint forall (op in 1..n_operations, t in 0..(n_intervals + 1), obj = main_obj_of_operation[op]
where is_moving_operation[op]) (
op_status[op, t] -> ((current_moving_operation[obj, t] != 0) /\
(moving_op_of_obj[obj, current_moving_operation[obj, t]] = op))
);
% Если операция, затрагивающая данный объект в качестве ресурса
% TODO упростить в conversion_1
% Связь current_moving_operation c op_status.
constraint forall (obj in 1..n_moving_obj,
t in 0..(n_intervals + 1)) (
(current_moving_operation[obj, t] != 0)
-> (op_status[moving_op_of_obj[obj, current_moving_operation[obj, t]], t])
);
% Ограничение на количество пришвартованных кораблей.
% Счётчик объектов в локации (только в чётных - в состоянии пришвартованности).
array [1..n_locations, 0..(n_intervals + 1)] of var int : obj_in_loc_counter;
% Если операция, затрагивающая данный объект, выполняется - то именно она текущая операция перемещения для этого объекта. % Определение obj_in_loc_counter.
constraint forall (obj in 1..n_moving_obj, op_no in 1..moving_op_of_obj_sizes[obj], t in 0..(n_intervals + 1)) ( constraint forall (loc in 1..n_locations, t in 0..(n_intervals + 1)) (
(op_status[moving_op_of_obj[obj, op_no], t]) -> (current_moving_operation[obj, t] = op_no) obj_in_loc_counter[loc, t] = sum (obj in 1..n_moving_obj) (m_obj_loc[obj, t] = loc)
); );
% Если объект движется, то выполняется какая-то операция перемещения, касаящаяся этого объекта. % Само ограничение.
constraint forall (obj in 1..n_moving_obj, t in 0..(n_intervals + 1)) ( constraint forall (loc in 1..n_locations, t in 0..(n_intervals + 1) where (loc mod 2) = 0) (
(current_moving_operation[obj, t] > 0) -> obj_in_loc_counter[loc, t] <= 1
(exists (op_no in 1..moving_op_of_obj_sizes[obj]) (op_status[moving_op_of_obj[obj, op_no], t]))
); );
% Определение is_m_obj_in_movement_before_start. % Определение is_m_obj_in_movement_before_start.
...@@ -44,11 +62,12 @@ array [1..n_moving_obj, 1..moving_op_of_obj_max_size] of 1..n_operations : movin ...@@ -44,11 +62,12 @@ array [1..n_moving_obj, 1..moving_op_of_obj_max_size] of 1..n_operations : movin
% Если в предыдущем интервале объект не движется - то в начале этого он не движется, иначе он движется если предыдущая операция не закончилась. % Если в предыдущем интервале объект не движется - то в начале этого он не движется, иначе он движется если предыдущая операция не закончилась.
constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) ( constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) (
if (current_moving_operation[obj, t - 1] = 0) then (current_moving_operation[obj, t - 1] = 0)
is_m_obj_in_movement_before_start[obj, t] = false -> is_m_obj_in_movement_before_start[obj, t] = false
else );
is_m_obj_in_movement_before_start[obj, t] = (current_moving_operation[obj, t - 1] == current_moving_operation[obj, t]) constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals + 1)) (
endif (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])
); );
array [1..n_operations] of 1..n_locations : operations_destination; % Локация в которой окажется объект после завершения операции. array [1..n_operations] of 1..n_locations : operations_destination; % Локация в которой окажется объект после завершения операции.
...@@ -56,27 +75,49 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ...@@ -56,27 +75,49 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац
% Определение m_obj_loc. % Определение m_obj_loc.
% Местоположение объекта или пункт назначения (если объект движется) перед началом определённого интервала. % Местоположение объекта или пункт назначения (если объект движется) перед началом определённого интервала.
array [1..n_moving_obj, 0..(n_intervals + 1)] of var 1..n_locations : m_obj_loc; array [1..n_moving_obj, 0..(n_intervals + 1)] of var 1..n_locations : m_obj_loc;
% Главный объект (субъект) операции.
array [1..n_operations] of 1..n_moving_obj : main_obj_of_operation;
% Является ли операция швартовкой/отшвартовкой.
array [1..n_operations] of bool : is_mooring_op;
% За фиктивный нулевой интервал объект не успевает ничего сделать с начальным положением. % За фиктивный нулевой интервал объект не успевает ничего сделать с начальным положением.
constraint forall (obj in 1..n_moving_obj) ( constraint forall (obj in 1..n_moving_obj) (
m_obj_loc[obj, 1] = m_obj_loc[obj, 0] m_obj_loc[obj, 1] = m_obj_loc[obj, 0]
); );
% TODO исправить в conversion_1.mzn
% Направление движения/местоположение объекта может измениться только если перед этим началась операция перемещения. % Направление движения/местоположение объекта может измениться только если перед этим началась операция перемещения.
constraint forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) ( constraint forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) (
if ((current_moving_operation[obj, t - 1] != current_moving_operation[obj, t - 2]) /\ ((current_moving_operation[obj, t - 1] != current_moving_operation[obj, t - 2]) /\
(current_moving_operation[obj, t - 1] != 0)) then (current_moving_operation[obj, t - 1] != 0) /\
m_obj_loc[obj, t] = operations_destination[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]] ((obj = main_obj_of_operation[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]])
else \/
m_obj_loc[obj, t] = m_obj_loc[obj, t - 1] (not is_mooring_op[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]])
endif )
) -> (m_obj_loc[obj, t] = operations_destination[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]])
);
constraint forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) (
((current_moving_operation[obj, t - 1] != current_moving_operation[obj, t - 2]) /\
(current_moving_operation[obj, t - 1] != 0) /\
((obj != main_obj_of_operation[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]])
/\
(is_mooring_op[moving_op_of_obj[obj, current_moving_operation[obj, t - 1]]])
)
) -> (m_obj_loc[obj, t] = m_obj_loc[obj, t - 1])
);
constraint forall (obj in 1..n_moving_obj, t in 2..(n_intervals + 1)) (
((current_moving_operation[obj, t - 1] = current_moving_operation[obj, t - 2]) \/
(current_moving_operation[obj, t - 1] = 0)
) -> (m_obj_loc[obj, t] = m_obj_loc[obj, t - 1])
); );
% Начальное состояние. % Начальное состояние.
array [1..n_moving_obj] of var 0..n_locations : initial_m_obj_loc; array [1..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]); constraint forall (i in 1..n_moving_obj) (m_obj_loc[i, 0] = initial_m_obj_loc[i]);
% Конечное состояние. % Конечное состояние.
array [1..n_moving_obj] of var 0..n_locations : final_m_obj_loc; array [1..n_moving_obj] of 0..n_locations : final_m_obj_loc;
constraint forall (i in 1..n_moving_obj) ( constraint forall (i in 1..n_moving_obj) (
(final_m_obj_loc[i] != 0) -> (final_m_obj_loc[i] != 0) ->
(m_obj_loc[i, n_intervals + 1] = final_m_obj_loc[i]) (m_obj_loc[i, n_intervals + 1] = final_m_obj_loc[i])
...@@ -94,9 +135,6 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ...@@ -94,9 +135,6 @@ 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 [1..n_moving_obj] of set of 1..n_operations : operations_that_used_obj_as_resource;
% Главный объект (субъект) операции.
array [1..n_operations] of 1..n_moving_obj : main_obj_of_operation;
% Является ли данная операция операцией перемещения. % Является ли данная операция операцией перемещения.
array [1..n_operations] of bool : is_moving_operation; array [1..n_operations] of bool : is_moving_operation;
...@@ -109,7 +147,8 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ...@@ -109,7 +147,8 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац
% Только те операции, которые затрагивают данный объект. % Только те операции, которые затрагивают данный объект.
constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
participation_as_resource[obj, t] in operations_that_used_obj_as_resource[obj] (participation_as_resource[obj, t] != 0)
-> participation_as_resource[obj, t] in operations_that_used_obj_as_resource[obj]
); );
% Связь с текущими операциями перемещения. % Связь с текущими операциями перемещения.
...@@ -123,29 +162,37 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ...@@ -123,29 +162,37 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац
(participation_as_resource[obj, t] = moving_op_of_obj[obj, current_moving_operation[obj, t]]) (participation_as_resource[obj, t] = moving_op_of_obj[obj, current_moving_operation[obj, t]])
) )
); );
% { Если объект участвует как ресурс в операции перемещения, то это согласованно с current_moving_operation,
% иначе (как ресурс в погрузке) - он должен стоять на месте. } % { Если объект участвует как ресурс в операции перемещения (не швартовки), то это согласованно с current_moving_operation,
% иначе (как ресурс в погрузке или швартове) - он должен стоять на месте. }
constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) ( constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
(participation_as_resource[obj, t] != 0) -> ( (participation_as_resource[obj, t] != 0) -> (
if (is_moving_operation[participation_as_resource[obj, t]]) then ( (is_moving_operation[participation_as_resource[obj, t]] /\
(not is_mooring_op[participation_as_resource[obj, t]])
) -> (
(current_moving_operation[obj, t] != 0)
/\
(participation_as_resource[obj, t] = moving_op_of_obj[obj, current_moving_operation[obj, t]]) (participation_as_resource[obj, t] = moving_op_of_obj[obj, current_moving_operation[obj, t]])
else )
current_moving_operation[obj, t] = 0 )
end /\
(not (is_moving_operation[participation_as_resource[obj, t]] /\
(not is_mooring_op[participation_as_resource[obj, t]])
) -> current_moving_operation[obj, t] = 0)
) )
); );
% { Объект участвует где-то в качестве ресурса - соответствующая операция обязана быть активной. } % { Объект участвует где-то в качестве ресурса - соответствующая операция обязана быть активной. }
constraint forall (obj in n_moving_obj, t in 1..n_intervals) ( constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
(participation_as_resource[obj, t] != 0) -> op_status[participation_as_resource[obj, t], t] (participation_as_resource[obj, t] != 0) -> op_status[participation_as_resource[obj, t], t]
); );
% От начала операции и до конца её ресурсы не могут измениться (в том числе и для погрузки). % От начала операции и до конца её ресурсы не могут измениться (в том числе и для погрузки).
constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals - 1)) ( constraint forall (obj in 1..n_moving_obj, t in 1..(n_intervals - 1)) (
if participation_as_resource[obj, t] != 0 then (participation_as_resource[obj, t] != 0) ->
op_status[participation_as_resource[obj, t], t + 1] -> ( (op_status[participation_as_resource[obj, t], t + 1]
participation_as_resource[obj, t + 1] = participation_as_resource[obj, t] -> participation_as_resource[obj, t + 1] = participation_as_resource[obj, t]
) )
else true
end
); );
int : n_resources_types; % Количество различных типов ресурсов. int : n_resources_types; % Количество различных типов ресурсов.
...@@ -167,7 +214,7 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ...@@ -167,7 +214,7 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац
% Определение resources_counter. % Определение resources_counter.
constraint forall (counter in 1..n_resources_counters, t in 1..n_intervals) ( constraint forall (counter in 1..n_resources_counters, t in 1..n_intervals) (
resources_counter[counter, t] = sum (obj in objects_of_type[counter_type[counter]]) ( resources_counter[counter, t] = sum (obj in objects_of_type[counter_type[counter]]) (
participation_as_resource[obj] = operation_of_counter[counter] participation_as_resource[obj, t] = operation_of_counter[counter]
) )
); );
...@@ -183,24 +230,27 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ...@@ -183,24 +230,27 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац
op in 1..n_operations, op in 1..n_operations,
t in 1..n_intervals, t in 1..n_intervals,
counter in counters_of_operation[op], counter in counters_of_operation[op],
obj in objects_of_type[counter_type[counter]] obj in objects_of_type[counter_type[counter]]) (
where (participation_as_resource[obj, t] = op)) ( ((participation_as_resource[obj, t] = op) /\ (op_start[op, t])
op_start[op, t] -> ((m_obj_loc[obj, t] == operations_resources_start_loc[counter]) /\ ) -> ((m_obj_loc[obj, t] == operations_resources_start_loc[counter]) /\
(not is_m_obj_in_movement_before_start[obj, t])) (not is_m_obj_in_movement_before_start[obj, t]) /\
((not is_moving_operation[op]) -> (current_moving_operation[obj, t] = 0))
)
); );
% Наличие и готовность главных объектов (субъектов). % Наличие и готовность главных объектов (субъектов).
constraint forall (op in 1..n_operations, t in 1..n_intervals) ( 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[main_obj_of_operation[op], t] == main_obj_start_loc[op]) /\ op_start[op, t] -> ((m_obj_loc[obj, t] == main_obj_start_loc[op]) /\
(not is_m_obj_in_movement_before_start[main_obj_of_operation[op], t])) (not is_m_obj_in_movement_before_start[obj, t]) /\
((not is_moving_operation[op]) -> (current_moving_operation[obj, t] = 0))
)
); );
% Непрерывность перемещения и швартовки. % Непрерывность перемещения и швартовки.
array [1..n_operations] of int : operations_duration; array [1..n_operations] of int : operations_duration;
array [1..n_operations] of bool : is_continuous_operation; array [1..n_operations] of bool : is_continuous_operation;
constraint forall (i in 1..n_operations where is_continuous_operation[i]) ( constraint forall (i in 1..n_operations, len = operations_duration[i] where is_continuous_operation[i]) (
let {var int : len = operations_duration[i]} in
(forall (j in 1..(n_intervals - len + 1)) ( (forall (j in 1..(n_intervals - len + 1)) (
(op_start[i, j] == 1) -> ( (op_start[i, j] == 1) -> (
(forall (k in 1..(len - 1)) (op_status[i, j + k])) (forall (k in 1..(len - 1)) (op_status[i, j + k]))
...@@ -300,12 +350,20 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ...@@ -300,12 +350,20 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац
solve minimize sum(is_not_terminated); solve minimize sum(is_not_terminated);
output [show(sum(is_not_terminated)), "\n", output [show(sum(is_not_terminated)), "\n",
show(op_status), "\n\n", "op_status = ", show(op_status), "\n\n",
"m_obj_loc = ", show(m_obj_loc), "\n\n", "m_obj_loc = ", show(m_obj_loc), "\n\n",
"op_fin = ", show(op_fin), "\n\n", "op_fin = ", show(op_fin), "\n\n",
"op_start = ", show(op_start), "\n\n", "op_start = ", show(op_start), "\n\n",
"is_not_terminated = ", show(is_not_terminated), "\n\n", "is_not_terminated = ", show(is_not_terminated), "\n\n",
"storage_used_volume = ", show(storage_used_volume), "\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", "is_m_obj_in_movement_before_start = ", show(is_m_obj_in_movement_before_start), "\n\n",
"current_moving_operation = ", show(current_moving_operation), "\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",
"real_current_moving_operation = ", show(current_moving_operation), "\n\n",
"moving_op_of_obj {", show(moving_op_of_obj_max_size + 1), "}= ", show(moving_op_of_obj), "\n\n",
""];
...@@ -5,7 +5,6 @@ import javafx.util.Pair; ...@@ -5,7 +5,6 @@ import javafx.util.Pair;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
public class ConversionUtil { public class ConversionUtil {
...@@ -90,13 +89,14 @@ public class ConversionUtil { ...@@ -90,13 +89,14 @@ public class ConversionUtil {
static private void writeArrayOfSetAs2DArray(FileWriter writer, static private void writeArrayOfSetAs2DArray(FileWriter writer,
String name, String name,
ArrayList<ArrayList<Integer>> operations) throws IOException { ArrayList<ArrayList<Integer>> operations) throws IOException {
writeArrayOfSetAs2DArray(writer, name, operations, true); writeArrayOfSetAs2DArray(writer, name, operations, true, false);
} }
static private void writeArrayOfSetAs2DArray(FileWriter writer, static private void writeArrayOfSetAs2DArray(FileWriter writer,
String name, String name,
ArrayList<ArrayList<Integer>> operations, ArrayList<ArrayList<Integer>> operations,
boolean addAdditionalInfo) throws IOException { boolean addAdditionalInfo,
boolean addDummyZeroElement) throws IOException {
int maxSize = 0; int maxSize = 0;
ArrayList<Integer> sizes = new ArrayList<>(); ArrayList<Integer> sizes = new ArrayList<>();
for (ArrayList<Integer> s : operations) { for (ArrayList<Integer> s : operations) {
...@@ -107,10 +107,18 @@ public class ConversionUtil { ...@@ -107,10 +107,18 @@ public class ConversionUtil {
writer.write(name + "_max_size = " + maxSize + ";\n"); writer.write(name + "_max_size = " + maxSize + ";\n");
writeArray(writer, name + "_sizes", sizes); writeArray(writer, name + "_sizes", sizes);
} }
writer.write(name + " = array2d(1.." + operations.size() + ", 1.." + maxSize + ", ["); writer.write(name + " = array2d(1.." + operations.size() + ", " + (addDummyZeroElement ? "0" : "1") + ".." + maxSize + ", [");
boolean isFirst = true; boolean isFirst = true;
for (ArrayList<Integer> s : operations) { for (ArrayList<Integer> s : operations) {
if (addDummyZeroElement) {
if (isFirst) {
isFirst = false;
} else {
writer.write(", ");
}
writer.write("1");
}
for (Integer val : s) { for (Integer val : s) {
if (isFirst) { if (isFirst) {
isFirst = false; isFirst = false;
...@@ -197,7 +205,23 @@ public class ConversionUtil { ...@@ -197,7 +205,23 @@ public class ConversionUtil {
return res; return res;
} }
static private MovingObject getExecutor(OperationTemplate t) { static private ArrayList<ArrayList<Integer>> arrayOfIntegerArrays(int size) {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
for (int i = 0; i < size; i++) {
res.add(new ArrayList<>());
}
return res;
}
static private ArrayList<Set<Integer>> arrayOfIntegerSet(int size) {
ArrayList<Set<Integer>> res = new ArrayList<>();
for (int i = 0; i < size; i++) {
res.add(new TreeSet<>());
}
return res;
}
static MovingObject getExecutor(OperationTemplate t) {
if (t instanceof LoadingTemplate) { if (t instanceof LoadingTemplate) {
return ((LoadingTemplate) t).getLoader(); return ((LoadingTemplate) t).getLoader();
} }
...@@ -210,7 +234,7 @@ public class ConversionUtil { ...@@ -210,7 +234,7 @@ public class ConversionUtil {
return null; return null;
} }
static private List<MovingObject> getResources(OperationTemplate t) { static List<MovingObject> getResources(OperationTemplate t) {
List<MovingObject> res = new ArrayList<>(); List<MovingObject> res = new ArrayList<>();
if (t instanceof LoadingTemplate) { if (t instanceof LoadingTemplate) {
res.addAll(((LoadingTemplate) t).getResources()); res.addAll(((LoadingTemplate) t).getResources());
...@@ -266,7 +290,7 @@ public class ConversionUtil { ...@@ -266,7 +290,7 @@ public class ConversionUtil {
return true; return true;
} }
private static class Task { static class Task {
private FileWriter writer = null; private FileWriter writer = null;
private final String fileName; private final String fileName;
private final TaskCase task; private final TaskCase task;
...@@ -280,9 +304,17 @@ public class ConversionUtil { ...@@ -280,9 +304,17 @@ public class ConversionUtil {
} }
private final ArrayList<MovingObject> movingObjects; private final ArrayList<MovingObject> movingObjects;
private final Function<MovingObject, Integer> mObjToN;
private final ArrayList<OperationTemplate> operationTemplates; public Map<Integer, Integer> getMObjNumberById() {
return mObjNumberById;
}
private final Map<Integer, Integer> mObjNumberById;
private int mObjToN(MovingObject obj) {
return mObjNumberById.get(obj.getId());
}
private ArrayList<OperationTemplate> operationTemplates;
private final ArrayList<Storage> storages; private final ArrayList<Storage> storages;
private final ArrayList<Cargo> cargoes; private final ArrayList<Cargo> cargoes;
...@@ -292,6 +324,19 @@ public class ConversionUtil { ...@@ -292,6 +324,19 @@ public class ConversionUtil {
private final Map<Integer, Integer> storNById; private final Map<Integer, Integer> storNById;
private final Map<Integer, Integer> cargoNById; private final Map<Integer, Integer> cargoNById;
private final Map<Integer, Integer> typeToN;
private ArrayList<ArrayList<Integer>> movingOpOfObj;
private ArrayList<Integer> operationsDestination;
private ArrayList<Integer> mainObjOfOperation;
private ArrayList<Boolean> isMooringOp;
public ArrayList<ArrayList<Integer>> getMovingOpOfObj() {
return movingOpOfObj;
}
private ArrayList<Set<Integer>> objectsOfType;
Task(TaskCase task, String fileName) { Task(TaskCase task, String fileName) {
this.fileName = fileName; this.fileName = fileName;
this.task = task; this.task = task;
...@@ -306,7 +351,7 @@ public class ConversionUtil { ...@@ -306,7 +351,7 @@ public class ConversionUtil {
} }
movingObjects = new ArrayList<>(); movingObjects = new ArrayList<>();
Map<Integer, Integer> mObjNumberById = new TreeMap<>(); mObjNumberById = new TreeMap<>();
for (MovingObject obj : task.getShips()) { for (MovingObject obj : task.getShips()) {
mObjNumberById.put(obj.getId(), movingObjects.size()); mObjNumberById.put(obj.getId(), movingObjects.size());
movingObjects.add(obj); movingObjects.add(obj);
...@@ -320,8 +365,10 @@ public class ConversionUtil { ...@@ -320,8 +365,10 @@ public class ConversionUtil {
movingObjects.add(obj); movingObjects.add(obj);
} }
mObjToN = (MovingObject obj) -> mObjNumberById.get(obj.getId());
operationTemplates = new ArrayList<>(task.getTemplates()); operationTemplates = new ArrayList<>(task.getTemplates());
if (task.isTypified()) {
operationTemplates = renumberOperations(task);
}
storages = new ArrayList<>(task.getStorages()); storages = new ArrayList<>(task.getStorages());
cargoes = new ArrayList<>(task.getCargoes()); cargoes = new ArrayList<>(task.getCargoes());
...@@ -337,6 +384,50 @@ public class ConversionUtil { ...@@ -337,6 +384,50 @@ public class ConversionUtil {
} }
nObjWithStorage = movingObjects.size() + storages.size(); nObjWithStorage = movingObjects.size() + storages.size();
{
typeToN = new TreeMap<>();
int next = 0;
for (Integer type : task.getVesselTypes().keySet()) {
typeToN.put(type, next);
next++;
}
for (Integer type : task.getEquipmentsTypes().keySet()) {
typeToN.put(type, next);
next++;
}
}
{
objectsOfType = arrayOfIntegerSet(typeToN.size());
for (MovingObject obj : movingObjects) {
if (obj.getType().isPresent()) {
objectsOfType.get(typeToN.get(obj.getType().getAsInt())).add(mObjToN(obj) + 1);
}
}
}
{
movingOpOfObj = arrayOfIntegerArrays(movingObjects.size());
operationsDestination = new ArrayList<>();
mainObjOfOperation = new ArrayList<>();
isMooringOp = new ArrayList<>();
initMovingObjectLocationDefinition();
}
}
private ArrayList<Integer> getNumbersOfResourcesTypes(OperationTemplate t) {
ArrayList<Integer> res = new ArrayList<>();
if (t instanceof LoadingTemplate) {
res.addAll(((LoadingTemplate) t).getResourcesTypes());
}
if (t instanceof MooringTemplate) {
res.addAll(((MooringTemplate) t).getResourcesTypes());
}
if (t instanceof MovingTemplate) {
res.addAll(((MovingTemplate) t).getResourcesTypes());
}
res.replaceAll(typeToN::get);
return res;
} }
/* Операции прибытия/отбытия в локацию. (В том числе и швартовка.) */ /* Операции прибытия/отбытия в локацию. (В том числе и швартовка.) */
...@@ -358,9 +449,9 @@ public class ConversionUtil { ...@@ -358,9 +449,9 @@ public class ConversionUtil {
ArrayList<Integer> movingObjN = new ArrayList<>(); ArrayList<Integer> movingObjN = new ArrayList<>();
for (MovingObject obj : op.getResources()) { for (MovingObject obj : op.getResources()) {
movingObjN.add(mObjToN.apply(obj)); movingObjN.add(mObjToN(obj));
} }
movingObjN.add(mObjToN.apply(op.getMover())); movingObjN.add(mObjToN(op.getMover()));
for (Integer n : movingObjN) { for (Integer n : movingObjN) {
arrivalOp .get(n).get(getLocNById(op.getDestination().getId(), false)).add(i + 1); arrivalOp .get(n).get(getLocNById(op.getDestination().getId(), false)).add(i + 1);
...@@ -371,9 +462,9 @@ public class ConversionUtil { ...@@ -371,9 +462,9 @@ public class ConversionUtil {
ArrayList<Integer> movingObjN = new ArrayList<>(); ArrayList<Integer> movingObjN = new ArrayList<>();
for (MovingObject obj : op.getResources()) { for (MovingObject obj : op.getResources()) {
movingObjN.add(mObjToN.apply(obj)); movingObjN.add(mObjToN(obj));
} }
movingObjN.add(mObjToN.apply(op.getMoorer())); movingObjN.add(mObjToN(op.getMoorer()));
for (Integer n : movingObjN) { for (Integer n : movingObjN) {
arrivalOp .get(n).get(getLocNById(op.getStartLocation().getId(), op.isDirect())).add(i + 1); arrivalOp .get(n).get(getLocNById(op.getStartLocation().getId(), op.isDirect())).add(i + 1);
...@@ -390,7 +481,7 @@ public class ConversionUtil { ...@@ -390,7 +481,7 @@ public class ConversionUtil {
private void initialLocations() throws IOException { private void initialLocations() throws IOException {
ArrayList<Integer> initialStates = integerArray(movingObjects.size(), 0); ArrayList<Integer> initialStates = integerArray(movingObjects.size(), 0);
for (MovingObjectState state : task.getVesselInitialState()) { for (MovingObjectState state : task.getVesselInitialState()) {
initialStates.set(mObjToN.apply(state.getVessel()), getLocNById(state.getLocation().getId(), false)); 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);
writer.write("\n"); writer.write("\n");
...@@ -446,7 +537,7 @@ public class ConversionUtil { ...@@ -446,7 +537,7 @@ public class ConversionUtil {
private void finalLocations() throws IOException { private void finalLocations() throws IOException {
ArrayList<Integer> finalStates = integerArray(movingObjects.size(), -1); ArrayList<Integer> finalStates = integerArray(movingObjects.size(), -1);
for (MovingObjectState state : task.getVesselEndState()) { for (MovingObjectState state : task.getVesselEndState()) {
finalStates.set(mObjToN.apply(state.getVessel()), getLocNById(state.getLocation().getId(), false)); 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);
} }
...@@ -457,7 +548,7 @@ public class ConversionUtil { ...@@ -457,7 +548,7 @@ public class ConversionUtil {
ArrayList<ArrayList<Integer>> operationsResourcesStartLoc = new ArrayList<>(); ArrayList<ArrayList<Integer>> operationsResourcesStartLoc = new ArrayList<>();
BiConsumer<MovingObject, Integer> addResource = (MovingObject r, Integer stLoc) -> { BiConsumer<MovingObject, Integer> addResource = (MovingObject r, Integer stLoc) -> {
operationsResources.get(operationsResources.size() - 1).add(mObjToN.apply(r) + 1); operationsResources.get(operationsResources.size() - 1).add(mObjToN(r) + 1);
operationsResourcesStartLoc.get(operationsResourcesStartLoc.size() - 1).add(stLoc + 1); operationsResourcesStartLoc.get(operationsResourcesStartLoc.size() - 1).add(stLoc + 1);
}; };
...@@ -486,7 +577,7 @@ public class ConversionUtil { ...@@ -486,7 +577,7 @@ public class ConversionUtil {
} }
} }
writeArrayOfSetAs2DArray(writer, "operations_resources", operationsResources); writeArrayOfSetAs2DArray(writer, "operations_resources", operationsResources);
writeArrayOfSetAs2DArray(writer, "operations_resources_start_loc", operationsResourcesStartLoc, false); writeArrayOfSetAs2DArray(writer, "operations_resources_start_loc", operationsResourcesStartLoc, false, false);
writer.write("\n"); writer.write("\n");
} }
...@@ -544,7 +635,7 @@ public class ConversionUtil { ...@@ -544,7 +635,7 @@ public class ConversionUtil {
initialStorageVol.get(movingObjects.size() + stN).set(cargoN, val); initialStorageVol.get(movingObjects.size() + stN).set(cargoN, val);
} else if (st.getStorage() instanceof TransportShip) { } else if (st.getStorage() instanceof TransportShip) {
TransportShip ship = (TransportShip) st.getStorage(); TransportShip ship = (TransportShip) st.getStorage();
initialStorageVol.get(mObjToN.apply(ship)).set(cargoN, val); initialStorageVol.get(mObjToN(ship)).set(cargoN, val);
} }
} }
for (StorageState st : task.getStorageEndState()) { for (StorageState st : task.getStorageEndState()) {
...@@ -557,7 +648,7 @@ public class ConversionUtil { ...@@ -557,7 +648,7 @@ public class ConversionUtil {
finalStorageVol.get(movingObjects.size() + stN).set(cargoN, val); finalStorageVol.get(movingObjects.size() + stN).set(cargoN, val);
} else if (st.getStorage() instanceof TransportShip) { } else if (st.getStorage() instanceof TransportShip) {
TransportShip ship = (TransportShip) st.getStorage(); TransportShip ship = (TransportShip) st.getStorage();
finalStorageVol.get(mObjToN.apply(ship)).set(cargoN, val); finalStorageVol.get(mObjToN(ship)).set(cargoN, val);
} }
} }
write2DArrayOfInt(writer, "initial_storage_vol", initialStorageVol); write2DArrayOfInt(writer, "initial_storage_vol", initialStorageVol);
...@@ -617,7 +708,7 @@ public class ConversionUtil { ...@@ -617,7 +708,7 @@ public class ConversionUtil {
if (operationTemplates.get(i) instanceof LoadingTemplate) { if (operationTemplates.get(i) instanceof LoadingTemplate) {
LoadingTemplate op = (LoadingTemplate) operationTemplates.get(i); LoadingTemplate op = (LoadingTemplate) operationTemplates.get(i);
int storageN = storNById.get(op.getStorage().getId()); int storageN = storNById.get(op.getStorage().getId());
int shipN = mObjToN.apply(op.getLoader()); int shipN = mObjToN(op.getLoader());
int cargoN = cargoNById.get(op.getCargo().getId()); int cargoN = cargoNById.get(op.getCargo().getId());
loadingOpDelta.add(-(int)op.getIntensity()); loadingOpDelta.add(-(int)op.getIntensity());
...@@ -644,9 +735,9 @@ public class ConversionUtil { ...@@ -644,9 +735,9 @@ public class ConversionUtil {
ArrayList<ArrayList<Integer>> movingOpOfObj = new ArrayList<>(); ArrayList<ArrayList<Integer>> movingOpOfObj = new ArrayList<>();
BiConsumer<MovingObject, Integer> addUsOp = (MovingObject obj, Integer op) -> BiConsumer<MovingObject, Integer> addUsOp = (MovingObject obj, Integer op) ->
objUsefulOperations.get(mObjToN.apply(obj)).add(op + 1); objUsefulOperations.get(mObjToN(obj)).add(op + 1);
BiConsumer<MovingObject, Integer> addMovingOp = (MovingObject obj, Integer op) -> BiConsumer<MovingObject, Integer> addMovingOp = (MovingObject obj, Integer op) ->
movingOpOfObj.get(mObjToN.apply(obj)).add(op + 1); movingOpOfObj.get(mObjToN(obj)).add(op + 1);
for (int i = 0; i < movingObjects.size(); i++) { for (int i = 0; i < movingObjects.size(); i++) {
movingOpOfObj.add(new ArrayList<>()); movingOpOfObj.add(new ArrayList<>());
...@@ -692,7 +783,7 @@ public class ConversionUtil { ...@@ -692,7 +783,7 @@ public class ConversionUtil {
ArrayList<ArrayList<Integer>> objUsefulOperations = new ArrayList<>(); ArrayList<ArrayList<Integer>> objUsefulOperations = new ArrayList<>();
BiConsumer<MovingObject, Integer> addUsOp = (MovingObject obj, Integer op) -> BiConsumer<MovingObject, Integer> addUsOp = (MovingObject obj, Integer op) ->
objUsefulOperations.get(mObjToN.apply(obj)).add(op + 1); objUsefulOperations.get(mObjToN(obj)).add(op + 1);
for (int i = 0; i < movingObjects.size(); i++) { for (int i = 0; i < movingObjects.size(); i++) {
objUsefulOperations.add(new ArrayList<>()); objUsefulOperations.add(new ArrayList<>());
...@@ -726,25 +817,29 @@ public class ConversionUtil { ...@@ -726,25 +817,29 @@ public class ConversionUtil {
writer.write("\n"); writer.write("\n");
} }
private void movingObjectLocationDefinition() throws IOException { private void initMovingObjectLocationDefinition() {
ArrayList<ArrayList<Integer>> movingOpOfObj = new ArrayList<>();
ArrayList<Integer> operationsDestination = new ArrayList<>();
for (int i = 0; i < movingObjects.size(); i++) {
movingOpOfObj.add(new ArrayList<>());
}
BiConsumer<MovingObject, Integer> addMovingOp = (MovingObject obj, Integer op) -> BiConsumer<MovingObject, Integer> addMovingOp = (MovingObject obj, Integer op) ->
movingOpOfObj.get(mObjToN.apply(obj)).add(op + 1); movingOpOfObj.get(mObjToN(obj)).add(op + 1);
for (int i = 0; i < operationTemplates.size(); i++) { for (int i = 0; i < operationTemplates.size(); i++) {
OperationTemplate t = operationTemplates.get(i); OperationTemplate t = operationTemplates.get(i);
mainObjOfOperation.add(mObjToN(getExecutor(t)));
isMooringOp.add(t instanceof MooringTemplate);
if ((t instanceof MovingTemplate) || (t instanceof MooringTemplate)) { if ((t instanceof MovingTemplate) || (t instanceof MooringTemplate)) {
addMovingOp.accept(getExecutor(t), i); addMovingOp.accept(getExecutor(t), i);
if (!task.isTypified()) {
for (MovingObject obj : getResources(t)) { for (MovingObject obj : getResources(t)) {
addMovingOp.accept(obj, i); addMovingOp.accept(obj, i);
} }
} else {
for (Integer typeId : new TreeSet<>(getNumbersOfResourcesTypes(t))) {
for (Integer objId : objectsOfType.get(typeId)) {
movingOpOfObj.get(objId - 1).add(i + 1);
}
}
}
} }
if (t instanceof MovingTemplate) { if (t instanceof MovingTemplate) {
MovingTemplate op = (MovingTemplate)t; MovingTemplate op = (MovingTemplate)t;
...@@ -756,8 +851,12 @@ public class ConversionUtil { ...@@ -756,8 +851,12 @@ public class ConversionUtil {
operationsDestination.add(getLocNById(t.getStartLocation().getId(), false)); operationsDestination.add(getLocNById(t.getStartLocation().getId(), false));
} }
} }
}
writeArrayOfSetAs2DArray(writer, "moving_op_of_obj", movingOpOfObj); private void movingObjectLocationDefinition() throws IOException {
writeArray(writer, "is_mooring_op", isMooringOp);
writeArray(writer, "main_obj_of_operation", mainObjOfOperation, (Integer val) -> val + 1);
writeArrayOfSetAs2DArray(writer, "moving_op_of_obj", movingOpOfObj, true, true);
writeArray(writer, "operations_destination", operationsDestination, (Integer val) -> val + 1); writeArray(writer, "operations_destination", operationsDestination, (Integer val) -> val + 1);
writer.write("\n"); writer.write("\n");
} }
...@@ -838,6 +937,181 @@ public class ConversionUtil { ...@@ -838,6 +937,181 @@ public class ConversionUtil {
} }
} }
/* Каждую операцию лишает типизации по главному действующему лицу. */
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.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) {
if (obj.getType().isPresent()) {
shipsByType.get(obj.getType().getAsInt()).add(obj);
}
}
ArrayList<OperationTemplate> result = new ArrayList<>();
for (OperationTemplate op : task.getTemplates()) {
if (op instanceof LoadingTemplate) {
LoadingTemplate t = (LoadingTemplate)op;
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 (op instanceof MooringTemplate) {
MooringTemplate t = (MooringTemplate)op;
if (t.getMoorerType().isPresent()) {
for (MovingObject obj : shipsByType.get(t.getMoorerType().getAsInt())) {
assert(obj instanceof TransportShip);
result.add(new MooringTemplate((TransportShip)obj, t.getStartLocation(), t.getResourcesTypes(),
t.getDuration(), t.isDirect(), t.getId()));
}
}
}
if (op instanceof MovingTemplate) {
MovingTemplate t = (MovingTemplate)op;
if (t.getMoverType().isPresent()) {
for (MovingObject obj : shipsByType.get(t.getMoverType().getAsInt())) {
result.add(new MovingTemplate(obj, t.getStartLocation(), t.getDestination(), t.getResourcesTypes(),
t.getDuration(), t.getId()));
}
}
}
}
return result;
}
private void conflictingOperationsOnStorageAndOnTypeOnMainObject() throws IOException {
ArrayList<Pair<Integer, Integer>> conflictingPairs = new ArrayList<>();
for (int i = 0; i < operationTemplates.size(); i++) {
for (int j = i + 1; j < operationTemplates.size(); j++) {
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.getLoader() == op2.getLoader()) &&
(op1.getStorage() == op2.getStorage()) &&
(op1.getStartLocation() == op2.getStartLocation())) {
conflictingPairs.add(new Pair<>(i + 1, j + 1));
}
}
{ // Взаимоисключение операций перемещения и грузообработки с общим деятелем.
// TODO вынести в отдельный constraint
OperationTemplate t1 = operationTemplates.get(i);
OperationTemplate t2 = operationTemplates.get(j);
if (t1 instanceof LoadingTemplate) {
OperationTemplate t3 = t1;
t1 = t2;
t2 = t3;
}
if (((t1 instanceof MovingTemplate) || (t1 instanceof MooringTemplate))
&& (t2 instanceof LoadingTemplate)) {
if (getExecutor(t1) == getExecutor(t2)) {
conflictingPairs.add(new Pair<>(i + 1, j + 1));
}
}
}
{ // Взаимоисключение операций швартовки/отшвартовки с одним причалом.
// TODO выделить в отдельный constraint
if ((operationTemplates.get(i) instanceof MooringTemplate) &&
(operationTemplates.get(j) instanceof MooringTemplate)) {
MooringTemplate op1 = (MooringTemplate) operationTemplates.get(i);
MooringTemplate op2 = (MooringTemplate) operationTemplates.get(j);
if (op1.getStartLocation() == op2.getStartLocation()) {
conflictingPairs.add(new Pair<>(i + 1, j + 1));
}
}
}
}
}
writer.write("n_conflicting_op = " + conflictingPairs.size() + ";\n");
writeArray(writer, "confl_op_1", conflictingPairs, Pair::getKey);
writeArray(writer, "confl_op_2", conflictingPairs, Pair::getValue);
writer.write("\n");
}
private void typifiedResourcesDefinition() throws IOException {
{ // objects_of_type и operations_that_used_obj_as_resource
writer.write("n_resources_types = " + typeToN.size() + ";\n");
writeArray(writer, "objects_of_type", objectsOfType, ConversionUtil::setToString);
ArrayList<Set<Integer>> res = arrayOfIntegerSet(movingObjects.size());
for (int i = 0; i < operationTemplates.size(); i++) {
for (Integer typeNo : getNumbersOfResourcesTypes(operationTemplates.get(i))) {
for (int obj : objectsOfType.get(typeNo)) {
res.get(obj - 1).add(i + 1);
}
}
}
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);
writer.write("\n");
}
{ // counters, operations_resources_start_loc
ArrayList<Integer> counterType = new ArrayList<>();
ArrayList<Integer> operationOfCounter = new ArrayList<>();
ArrayList<Integer> requiredCounterValues = new ArrayList<>();
ArrayList<Set<Integer>> countersOfOperation = arrayOfIntegerSet(operationTemplates.size());
ArrayList<Integer> operationsResourcesStartLoc = new ArrayList<>();
for (int i = 0; i < operationTemplates.size(); i++) {
Map<Integer, Integer> numberOfTypes = new TreeMap<>();
for (int type : getNumbersOfResourcesTypes(operationTemplates.get(i))) {
if (!numberOfTypes.containsKey(type)) {
numberOfTypes.put(type, 1);
} else {
numberOfTypes.put(type, numberOfTypes.get(type) + 1);
}
}
for (Map.Entry<Integer, Integer> p : numberOfTypes.entrySet()) {
counterType.add(p.getKey());
operationOfCounter.add(i);
requiredCounterValues.add(p.getValue());
countersOfOperation.get(i).add(counterType.size());
operationsResourcesStartLoc.add(locationNumberById.get(new Pair<>(operationTemplates.get(i).getStartLocation().getId(), false)));
}
}
writer.write("n_resources_counters = " + counterType.size() + ";\n");
writeArray(writer, "counter_type", counterType, (Integer val) -> val + 1);
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);
}
}
/* С типизацией. */ /* С типизацией. */
void portToMiniZinc_2() throws IOException { void portToMiniZinc_2() throws IOException {
...@@ -848,7 +1122,7 @@ public class ConversionUtil { ...@@ -848,7 +1122,7 @@ public class ConversionUtil {
writer = new FileWriter(fileName, false); writer = new FileWriter(fileName, false);
writer.write("n_intervals = " + n_intervals + ";\n"); writer.write("n_intervals = " + n_intervals + ";\n");
writer.write("n_operations = " + task.getTemplates().size() + ";\n"); writer.write("n_operations = " + operationTemplates.size() + ";\n");
writer.write("n_locations = " + locationNumberById.size() + ";\n"); writer.write("n_locations = " + locationNumberById.size() + ";\n");
writer.write("n_moving_obj = " + movingObjects.size() + ";\n"); writer.write("n_moving_obj = " + movingObjects.size() + ";\n");
...@@ -856,11 +1130,12 @@ public class ConversionUtil { ...@@ -856,11 +1130,12 @@ public class ConversionUtil {
movingObjectLocationDefinition(); movingObjectLocationDefinition();
initialLocations(); initialLocations();
finalLocations();
weatherWindows(); weatherWindows();
conflictingOperationsOnStorageAndOnTypeOnMainObject();
operationsContinuity(); operationsContinuity();
finalLocations(); typifiedResourcesDefinition();
presenceOfResourcesInLocation();
conflictingOperations();
writer.write("n_obj_with_storage = " + nObjWithStorage + ";\n"); writer.write("n_obj_with_storage = " + nObjWithStorage + ";\n");
writer.write("n_cargo_types = " + cargoes.size() + ";\n"); writer.write("n_cargo_types = " + cargoes.size() + ";\n");
...@@ -891,13 +1166,22 @@ public class ConversionUtil { ...@@ -891,13 +1166,22 @@ public class ConversionUtil {
} }
} }
static public void portToMiniZinc_2(TaskCase task, String fileName) {
try {
Task taskData = new Task(task, fileName);
taskData.portToMiniZinc_2();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private static class OperationsComparator implements Comparator<Operation> { private static class OperationsComparator implements Comparator<Operation> {
public int compare(Operation op1, Operation op2) { public int compare(Operation op1, Operation op2) {
return Double.compare(op1.getStart(), op2.getStart()); return Double.compare(op1.getStart(), op2.getStart());
} }
} }
static public void resolveMiniZincResults(TaskCase task, String fileName) { public static void resolveMiniZincResults(TaskCase task, String fileName) {
ArrayList<Operation> operations = null; ArrayList<Operation> operations = null;
Integer result = null; Integer result = null;
...@@ -906,72 +1190,147 @@ public class ConversionUtil { ...@@ -906,72 +1190,147 @@ public class ConversionUtil {
String line; String line;
Map<String, ArrayList<ArrayList<String>>> arrays = new TreeMap<>();
while (((line = br.readLine()) != null)) { while (((line = br.readLine()) != null)) {
line = line.trim(); line = line.trim();
if (line.equals("")) { if (line.equals("")) {
continue; continue;
} }
String regexpr = "^\\[.*]\\z"; int pos = 0;
if (line.matches(regexpr)) { while ((pos < line.length()) && (line.charAt(pos) != ' ')) {
if (operations != null) { pos++;
continue;
} }
String []rawTokens = line.split("[\\s\\[\\],]"); String name = line.substring(0, pos);
ArrayList<String> tokens = new ArrayList<>();
for (String str : rawTokens) { if (name.equals("=====UNSATISFIABLE=====")) {
if (!str.isEmpty()) { result = -1;
tokens.add(str); break;
} }
if (name.equals("----------")) {
break;
} }
final int n_intervals = (int)task.getPlanningInterval(); if (name.matches("\\d+")) {
if (result != null) {
if (tokens.size() != (n_intervals + 2) * task.getTemplates().size()) { continue;
throw new ParserException("Invalid length of \"op_status\""); }
result = Integer.parseInt(name);
continue;
} }
operations = new ArrayList<>(); while ((pos < line.length()) && (line.charAt(pos) != '[') && (line.charAt(pos) != '{')) {
pos++;
for (int i = 0; i < task.getTemplates().size(); i++) { }
int duration = 0; int arrayFirstDim = ((int) task.getPlanningInterval()) + 2;
for (int j = 0; j < n_intervals + 2; j++) {
if (tokens.get(i * (n_intervals + 2) + j).equals("true")) {
duration++;
} else if (duration != 0) {
Operation op = new Operation();
op.setStart(j - duration - 1);
op.setDuration(duration);
op.setTemplate(task.getTemplates().get(i));
operations.add(op);
duration = 0; if (line.charAt(pos) == '{') {
pos++;
int nextPos = pos;
while (line.charAt(nextPos) != '}') {
nextPos++;
} }
arrayFirstDim = Integer.valueOf(line.substring(pos, nextPos).trim());
pos = nextPos + 1;
while (line.charAt(pos) != '[') {
pos++;
} }
} }
continue;
int pos2 = pos;
while ((pos2 < line.length()) && (line.charAt(pos2) != ']')) {
pos2++;
} }
if (line.matches("\\d+")) { String values = line.substring(pos + 1, pos2);
if (result != null) { ArrayList<String> elements = new ArrayList<>();
continue;
for (String val : values.split(",")) {
elements.add(val.trim());
} }
result = Integer.parseInt(line);
continue; if ((arrayFirstDim != 0) && (elements.size() % arrayFirstDim == 0)) {
ArrayList<ArrayList<String>> res = new ArrayList<>();
for (int i = 0; i < elements.size(); i += arrayFirstDim) {
ArrayList<String> subRes = new ArrayList<>();
for (int j = 0; j < arrayFirstDim; j++) {
subRes.add(elements.get(i + j));
} }
if (line.equals("=====UNSATISFIABLE=====")) { res.add(subRes);
result = -1;
} }
break; arrays.put(name, res);
} }
}
if (result == null) { if (result == null) {
throw new ParserException("No result in input"); throw new ParserException("No result in input");
} }
if (operations == null) { if (!arrays.containsKey("op_status")) {
if (result == -1) { if (result == -1) {
operations = new ArrayList<>(); operations = new ArrayList<>();
} else { } else {
throw new ParserException("No \"op_status\" in input"); throw new ParserException("No \"op_status\" in input");
} }
} }
if (result != -1) {
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);
}
Map<Integer, OperationTemplate> operationById = new TreeMap<>();
for (OperationTemplate operation : task.getTemplates()) {
operationById.put(operation.getId(), operation);
}
Map<Integer, MovingObject> objByNo = new TreeMap<>();
{
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 (int opNo = 0; opNo < opStatus.size(); opNo++) {
int duration = 0;
for (int t = 0; t < opStatus.get(opNo).size(); t++) {
if (opStatus.get(opNo).get(t).equals("true")) {
duration++;
} else if (duration != 0) {
Operation op = new Operation();
op.setStart(t - duration - 1);
op.setDuration(duration);
op.setTemplate(operationById.get(templates.get(opNo).getId()));
if (task.isTypified()) {
op.setExecutor(ConversionUtil.getExecutor(templates.get(opNo)));
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));
}
}
op.setResources(resources);
}
operations.add(op);
duration = 0;
}
}
}
}
operations.sort(new OperationsComparator()); operations.sort(new OperationsComparator());
task.setSolution(operations); task.setSolution(operations);
task.setSolution_result(result); task.setSolution_result(result);
......
...@@ -22,9 +22,9 @@ public class LoadingEquipment extends MovingObject{ ...@@ -22,9 +22,9 @@ public class LoadingEquipment extends MovingObject{
@Override @Override
public String toString() { public String toString() {
String res = getId() + ";" + getName(); String res = getId() + "; " + getName();
if (getType().isPresent()) { if (getType().isPresent()) {
res += ";" + getType().getAsInt(); res += "; " + getType().getAsInt();
} }
return res; return res;
} }
......
...@@ -95,13 +95,16 @@ public class LoadingTemplate extends OperationTemplate { ...@@ -95,13 +95,16 @@ public class LoadingTemplate extends OperationTemplate {
return cargo; return cargo;
} }
public LoadingTemplate(TransportShip loader, Berth berth, Storage storage, double intensity, int id) { public LoadingTemplate(TransportShip loader, Berth berth, Storage storage, Cargo cargo,
List<Integer> resourcesTypes, boolean withMooring, double intensity, int id) {
super(id, berth); super(id, berth);
this.loader = loader; this.loader = loader;
this.storage = storage; this.storage = storage;
this.resources = new ArrayList<>(); this.resources = new ArrayList<>();
this.resourcesTypes = new ArrayList<>(); this.resourcesTypes = new ArrayList<>(resourcesTypes);
this.withMooring = withMooring;
this.intensity = intensity; this.intensity = intensity;
this.cargo = cargo;
} }
public LoadingTemplate() { public LoadingTemplate() {
......
package inport; package inport;
import java.io.*; import java.io.*;
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;
import static inport.Testing.solveTask_1; import static inport.Testing.solveTask_1;
import static inport.Testing.solveTask_2;
import static inport.Testing.test_1; import static inport.Testing.test_1;
import inport.ConversionUtil.*;
public class Main { public class Main {
...@@ -27,7 +32,12 @@ public class Main { ...@@ -27,7 +32,12 @@ public class Main {
break; break;
} }
String error = solveTask_1(task); String error;
if (!task.isTypified()) {
error = solveTask_1(task);
} else {
error = solveTask_2(task);
}
long finish = System.currentTimeMillis(); long finish = System.currentTimeMillis();
System.out.println((finish - start) + " milliseconds"); System.out.println((finish - start) + " milliseconds");
...@@ -81,16 +91,29 @@ public class Main { ...@@ -81,16 +91,29 @@ public class Main {
break; break;
} }
case "debug" : { case "debug" : {
String fileName = args[1]; String fileName = "experiment/in.ipp";
String output = args[2]; String solverResults = "temp_data/solver_results.txt";
String output = "experiment/debug_info.txt";
TaskCase task = new TaskCase(); TaskCase task = new TaskCase();
try { try {
task.deserialize(fileName); task.deserialize(fileName);
task.serialize(output);
} catch (IOException e) { } catch (IOException e) {
System.out.println(e.getMessage()); System.out.println(e.getMessage());
break;
} }
String error = solveTask_2(task);
if (!error.isEmpty()) {
System.out.println("Error : " + error);
break;
} else {
task.serialize(fileName);
}
debugInfo(task, solverResults, output);
break; break;
} }
case "testing" : case "testing" :
...@@ -100,4 +123,145 @@ public class Main { ...@@ -100,4 +123,145 @@ public class Main {
System.out.println("Unknown type \"" + type + "\""); System.out.println("Unknown type \"" + type + "\"");
} }
} }
private static void debugInfo(TaskCase task, String solverResults, String output) {
try (FileInputStream fstream = new FileInputStream(solverResults)) {
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
FileWriter writer = new FileWriter(output, false);
{
ArrayList<OperationTemplate> operations = new ArrayList<>(task.getTemplates());
if (task.isTypified()) {
operations = Task.renumberOperations(task);
}
writer.write("operations :\n");
int no = 1;
for (OperationTemplate op : operations) {
writer.write(" " + no + " " + op.toString() + "\n");
no++;
}
writer.write("\n");
}
Task t = new Task(task, "");
{
ArrayList<MovingObject> movingObjects = new ArrayList<>();
movingObjects.addAll(task.getShips());
movingObjects.addAll(task.getTows());
movingObjects.addAll(task.getEquipments());
Map<Integer, MovingObject> objByNo = new TreeMap<>();
for (MovingObject obj : movingObjects) {
objByNo.put(t.getMObjNumberById().get(obj.getId()), obj);
}
writer.write("moving_objects : \n");
for (int i = 0; i < movingObjects.size(); i++) {
writer.write(" " + (i + 1) + " " + objByNo.get(i).toString() + "\n");
}
writer.write("\n");
}
String line;
int linesNumber = 0;
while (((line = br.readLine()) != null)) {
line = line.trim();
if (line.equals("")) {
continue;
}
linesNumber++;
if (linesNumber <= 1) {
continue;
}
int pos = 0;
while ((pos < line.length()) && (line.charAt(pos) != ' ')) {
pos++;
}
String name = line.substring(0, pos);
if (name.equals("----------")) {
break;
}
while ((pos < line.length()) && (line.charAt(pos) != '[') && (line.charAt(pos) != '{')) {
pos++;
}
int arrayFirstDim = ((int) task.getPlanningInterval()) + 2;
if (line.charAt(pos) == '{') {
pos++;
int nextPos = pos;
while (line.charAt(nextPos) != '}') {
nextPos++;
}
arrayFirstDim = Integer.valueOf(line.substring(pos, nextPos).trim());
pos = nextPos + 1;
while (line.charAt(pos) != '[') {
pos++;
}
}
int pos2 = pos;
while ((pos2 < line.length()) && (line.charAt(pos2) != ']')) {
pos2++;
}
String values = line.substring(pos + 1, pos2);
ArrayList<String> elements = new ArrayList<>();
for (String val : values.split(",")) {
elements.add(val.trim());
}
if (name.equals("current_moving_operation")) {
ArrayList<ArrayList<Integer>> movingOpOfObj = t.getMovingOpOfObj();
for (int i = 0; i < elements.size(); i += arrayFirstDim) {
for (int j = 0; j < arrayFirstDim; j++) {
int val = Integer.valueOf(elements.get(i + j));
if (val != 0) {
elements.set(i + j, Integer.toString(movingOpOfObj.get(i / arrayFirstDim).get(val - 1)));
}
}
}
name = name + " *";
}
{ // bool to int
for (int i = 0; i < elements.size(); i++) {
if (elements.get(i).equals("true")) {
elements.set(i, "1");
}
if (elements.get(i).equals("false")) {
elements.set(i, "0");
}
}
}
int maxLength = 0;
for (String val : elements) {
maxLength = Math.max(maxLength, val.length());
}
if ((arrayFirstDim != 0) && (elements.size() % arrayFirstDim == 0)) {
writer.write(name + " :\n");
for (int i = 0; i < elements.size(); i += arrayFirstDim) {
writer.write(" ");
for (int j = 0; j < arrayFirstDim; j++) {
String val = elements.get(i + j);
for (int k = val.length(); k < maxLength; k++) {
writer.write(" ");
}
writer.write(val + " ");
}
writer.write("\n");
}
writer.write("\n");
}
}
writer.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
package inport; package inport;
import java.util.List;
import java.util.OptionalInt; import java.util.OptionalInt;
/** /**
...@@ -59,10 +60,11 @@ public class MooringTemplate extends TowUsingTemplate { ...@@ -59,10 +60,11 @@ public class MooringTemplate extends TowUsingTemplate {
this.moorer = moorer; this.moorer = moorer;
} }
public MooringTemplate(TransportShip moorer, Berth berth, double duration, boolean direct, int id) { public MooringTemplate(TransportShip moorer, Berth berth, List<Integer> resourcesTypes, double duration, boolean direct, int id) {
super(duration, id, berth); super(duration, id, berth);
this.moorer = moorer; this.moorer = moorer;
this.direct = direct; this.direct = direct;
this.setResourcesTypes(resourcesTypes);
} }
public MooringTemplate() { public MooringTemplate() {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
package inport; package inport;
import java.util.List;
import java.util.OptionalInt; import java.util.OptionalInt;
/** /**
...@@ -60,10 +61,11 @@ public class MovingTemplate extends TowUsingTemplate { ...@@ -60,10 +61,11 @@ public class MovingTemplate extends TowUsingTemplate {
this.moverType = moverType; this.moverType = moverType;
} }
public MovingTemplate(MovingObject mover, Berth source, Berth destination, double duration, int id) { public MovingTemplate(MovingObject mover, Berth source, Berth destination, List<Integer> resourcesTypes, double duration, int id) {
super(duration, id, source); super(duration, id, source);
this.mover = mover; this.mover = mover;
this.destination = destination; this.destination = destination;
this.setResourcesTypes(resourcesTypes);
} }
public MovingTemplate() { public MovingTemplate() {
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
*/ */
package inport; package inport;
import java.util.List;
/** /**
* *
* @author topazh_ag * @author topazh_ag
...@@ -13,6 +15,22 @@ public class Operation { ...@@ -13,6 +15,22 @@ public class Operation {
private OperationTemplate template; private OperationTemplate template;
private double start; private double start;
private double duration; private double duration;
private MovingObject executor;
private List<MovingObject> resources;
public List<MovingObject> getResources() {
return resources;
}
public void setResources(List<MovingObject> resources) {
this.resources = resources;
}
public MovingObject getExecutor() {
return executor;
}
public void setExecutor(MovingObject executor) {
this.executor = executor;
}
/** /**
* Get the value of duration * Get the value of duration
...@@ -75,8 +93,25 @@ public class Operation { ...@@ -75,8 +93,25 @@ public class Operation {
@Override @Override
public String toString() { public String toString() {
return template.getId() + "; R; " + start + "; " + duration; if (executor == null) {
executor = ConversionUtil.getExecutor(template);
}
if (resources == null) {
resources = ConversionUtil.getResources(template);
}
StringBuilder sb = new StringBuilder();
sb.append(template.getId()).append("; R; ").append(start).append("; ").append(duration);
sb.append(" (").append(executor.getId()).append(" [");
boolean isFirst = true;
for (MovingObject obj : resources) {
if (isFirst) {
isFirst = false;
} else {
sb.append(", ");
}
sb.append(obj.getId());
}
sb.append("])");
return sb.toString();
} }
} }
...@@ -26,6 +26,14 @@ public class Testing { ...@@ -26,6 +26,14 @@ public class Testing {
ConversionUtil::resolveMiniZincResults); ConversionUtil::resolveMiniZincResults);
} }
public static String solveTask_2(TaskCase task) {
return solveTask(
task,
"conversion_2.mzn",
ConversionUtil::portToMiniZinc_2,
ConversionUtil::resolveMiniZincResults);
}
/* Возвращает описание ошибки, если ошибки не было, то пустую строку. */ /* Возвращает описание ошибки, если ошибки не было, то пустую строку. */
public static String solveTask(TaskCase task, public static String solveTask(TaskCase task,
String constraintName, String constraintName,
...@@ -63,6 +71,13 @@ public class Testing { ...@@ -63,6 +71,13 @@ public class Testing {
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream())); BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String output = br.lines().collect(Collectors.joining("\n")); String output = br.lines().collect(Collectors.joining("\n"));
BufferedReader br2 = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String errors = br.lines().collect(Collectors.joining("\n"));
System.out.println("output : " + output);
System.out.println("errors : " + errors);
if (output.trim().equals("=====UNSATISFIABLE=====")) { if (output.trim().equals("=====UNSATISFIABLE=====")) {
task.setSolution(new ArrayList<>()); task.setSolution(new ArrayList<>());
task.setSolution_result(-1); task.setSolution_result(-1);
...@@ -72,7 +87,7 @@ public class Testing { ...@@ -72,7 +87,7 @@ public class Testing {
} catch (UncheckedIOException | IOException | InterruptedException | ParserException ex) { } catch (UncheckedIOException | IOException | InterruptedException | ParserException ex) {
return ex.getMessage(); return ex.getMessage();
} finally { } finally {
removeDirectory(directory); // removeDirectory(directory);
} }
return ""; return "";
} }
......
...@@ -21,9 +21,9 @@ public class Tow extends MovingObject { ...@@ -21,9 +21,9 @@ public class Tow extends MovingObject {
@Override @Override
public String toString() { public String toString() {
String res = getId() + ";" + getName() + ";1000000"; String res = getId() + "; " + getName() + "; 1000000";
if (getType().isPresent()) { if (getType().isPresent()) {
res += ";" + getType().getAsInt(); res += "; " + getType().getAsInt();
} }
return res; return res;
} }
......
...@@ -32,9 +32,9 @@ public class TransportShip extends MovingObject { ...@@ -32,9 +32,9 @@ public class TransportShip extends MovingObject {
@Override @Override
public String toString() { public String toString() {
String res = getId() + ";" + getName() + ";" + cargoMax; String res = getId() + "; " + getName() + "; " + cargoMax;
if (getType().isPresent()) { if (getType().isPresent()) {
res += ";" + getType().getAsInt(); res += "; " + getType().getAsInt();
} }
return res; return res;
} }
......
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