Commit 5ef77a15 authored by Vladislav Kiselev's avatar Vladislav Kiselev

Новая оптимизация.

parent 8853ebdd
...@@ -81,7 +81,7 @@ array [0..n_moving_obj, 0..n_operations] of bool : moving_op_of_obj; ...@@ -81,7 +81,7 @@ array [0..n_moving_obj, 0..n_operations] of bool : moving_op_of_obj;
); );
array [1..n_locations] of 0..n_locations : twin_location = [i - 1 + (i mod 2) * 2 | i in 1..n_locations]; array [1..n_locations] of 0..n_locations : twin_location = [i - 1 + (i mod 2) * 2 | i in 1..n_locations];
% TODO нумерация с нуля array [1..n_locations] of 1..n_locations : main_location = [i - ((i + 1) mod 2)| i in 1..n_locations];
array [0..n_operations] of 0..n_locations : operations_destination; % Локация в которой окажется объект после завершения операции. array [0..n_operations] of 0..n_locations : operations_destination; % Локация в которой окажется объект после завершения операции.
...@@ -212,9 +212,10 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац ...@@ -212,9 +212,10 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац
); );
% Участие объекта в операциях грузообработки. % Участие объекта в операциях грузообработки.
array [0..n_moving_obj, 1..n_intervals] of var bool : is_involved_in_cargo_op; array [0..n_moving_obj, 0..n_intervals] of var bool : is_involved_in_cargo_op;
constraint forall (t in 1..n_intervals) (is_involved_in_cargo_op[0, t] = false); % Фиктивный объект. constraint forall (t in 1..n_intervals) (is_involved_in_cargo_op[0, t] = false); % Фиктивный объект.
constraint forall (obj in 1..n_moving_obj) (is_involved_in_cargo_op[obj, 0] = false);
% Операции погрузки, которые используют этот объект в качестве главного или в качестве бункеровщика. % Операции погрузки, которые используют этот объект в качестве главного или в качестве бункеровщика.
array [0..n_moving_obj] of set of 0..n_operations : related_cargo_op; array [0..n_moving_obj] of set of 0..n_operations : related_cargo_op;
...@@ -222,11 +223,9 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац ...@@ -222,11 +223,9 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац
% Операции отшвартовки, которые используют объект в качестве главного. % Операции отшвартовки, которые используют объект в качестве главного.
array [0..n_moving_obj] of set of 1..n_operations : related_unmooring_op; array [0..n_moving_obj] of set of 1..n_operations : related_unmooring_op;
% TODO узнать про where
% Определение is_involved_in_cargo_op. % Определение is_involved_in_cargo_op.
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) (
is_involved_in_cargo_op[obj, t] = ( is_involved_in_cargo_op[obj, t] = (
% (exists (op in 1..n_operations where (not is_moving_operation[op]) /\ (main_obj_of_operation[op] = obj)) (
(exists (op in related_cargo_op[obj]) (op_status[op, t])) (exists (op in related_cargo_op[obj]) (op_status[op, t]))
\/ \/
((participation_as_resource[obj, t] != 0) /\ (not is_moving_operation[participation_as_resource[obj, t]])) ((participation_as_resource[obj, t] != 0) /\ (not is_moving_operation[participation_as_resource[obj, t]]))
...@@ -351,6 +350,8 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац ...@@ -351,6 +350,8 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац
array [1..n_loading_op] of 1..n_operations : loading_op_n; % Номера среди общего списка операций. array [1..n_loading_op] of 1..n_operations : loading_op_n; % Номера среди общего списка операций.
array [1..n_all_storage_sections] of set of 1..n_loading_op : involved_operations; array [1..n_all_storage_sections] of set of 1..n_loading_op : involved_operations;
array [1..n_moving_obj] of set of 1..n_all_storage_sections : sections_of_moving_obj;
array [1..n_moving_obj] of bool : is_sections_of_moving_obj_empty;
constraint forall (storage in 1..n_all_storage_sections, t in 1..(n_intervals + 1)) ( constraint forall (storage in 1..n_all_storage_sections, t in 1..(n_intervals + 1)) (
storage_used_volume[storage, t] = ( storage_used_volume[storage, t] = (
...@@ -509,6 +510,51 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац ...@@ -509,6 +510,51 @@ array [0..n_operations] of 0..n_locations : operations_destination; % Локац
) -> is_attended_useful_op_in_cur_loc[obj, t - 1] ) -> is_attended_useful_op_in_cur_loc[obj, t - 1]
); );
% Оптимизация - если объект не может совершить в данной локации операции без выхода за границы хранилища, а так же если он
% может уйти только своим ходом, то он либо уходит немедленно, либо остаётся на месте навсегда.
array [1..n_all_storage_sections, 1..n_locations] of int : min_positive_cargo_val; % Объём максимальной положительной операции, которая может быть произведена с этой секцией в этом хранилище. Если в локации таковой нет, то это значение объёма хранилища + 1.
array [1..n_all_storage_sections, 1..n_locations] of int : max_negative_cargo_val;
array [1..n_moving_obj, 1..n_locations] of bool : can_obj_leave_loc_only_alone;
array [1..n_moving_obj, 1..n_locations, 1..n_intervals] of bool : is_fixed_op_planned_in_future;
array [0..n_moving_obj, 0..(n_intervals + 1)] of var bool : can_obj_theoretically_use_cargo_op;
% Определение can_obj_theoretically_use_cargo_op.
constraint 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]
\/
exists (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)
)
)
);
constraint forall (t in 0..(n_intervals + 1)) (can_obj_theoretically_use_cargo_op[0, t] = false);
constraint forall (obj in 1..n_moving_obj) (can_obj_theoretically_use_cargo_op[obj, 0] = false);
% Остановился ли объект окончательно, начиная с данного интервала.
array [0..n_moving_obj, 0..(n_intervals + 1)] of var bool : is_obj_totally_terminated;
constraint forall (obj in 1..n_moving_obj) (is_obj_totally_terminated[obj, n_intervals + 1] = true);
constraint forall (t in 0..(n_intervals + 1)) (is_obj_totally_terminated[0, t] = true);
constraint forall (obj in 1..n_moving_obj, t in 0..n_intervals) (
is_obj_totally_terminated[obj, t] = (
(current_moving_operation[obj, t] = 0)
/\ (not is_involved_in_cargo_op[obj, t])
/\ (is_obj_totally_terminated[obj, t + 1])
)
);
% Само ограничение.
constraint forall (obj in 1..n_moving_obj, t in 1..n_intervals) (
( (can_obj_leave_loc_only_alone[obj, m_obj_loc[obj, t]])
/\ (not can_obj_theoretically_use_cargo_op[obj, t])
/\ (not is_fixed_op_planned_in_future[obj, m_obj_loc[obj, t], t])
) ->
(is_obj_totally_terminated[obj, t] \/ (current_moving_operation[obj, t] != 0))
);
% Критерий оптимизации % Критерий оптимизации
array [1..(n_intervals + 1)] of var bool : is_not_terminated; array [1..(n_intervals + 1)] of var bool : is_not_terminated;
...@@ -541,16 +587,25 @@ output [show(sum(is_not_terminated)), "\n", ...@@ -541,16 +587,25 @@ output [show(sum(is_not_terminated)), "\n",
"is_involved_in_cargo_op = {", show(n_intervals), "} ", show(is_involved_in_cargo_op), "\n\n", "is_involved_in_cargo_op = {", show(n_intervals), "} ", show(is_involved_in_cargo_op), "\n\n",
"m_obj_loc = ", show(m_obj_loc), "\n\n", "m_obj_loc = ", show(m_obj_loc), "\n\n",
/*
"prev_m_obj_loc = {", show(n_intervals + 2), "} ", show(prev_m_obj_loc), "\n\n", "prev_m_obj_loc = {", show(n_intervals + 2), "} ", show(prev_m_obj_loc), "\n\n",
"is_obj_involved_in_useful_operation = {", show(n_intervals + 2), "} ", show(is_obj_involved_in_useful_operation), "\n\n", "is_obj_involved_in_useful_operation = {", show(n_intervals + 2), "} ", show(is_obj_involved_in_useful_operation), "\n\n",
"is_attended_useful_op_in_cur_loc = {", show(n_intervals + 2), "} ", show(is_attended_useful_op_in_cur_loc), "\n\n", "is_attended_useful_op_in_cur_loc = {", show(n_intervals + 2), "} ", show(is_attended_useful_op_in_cur_loc), "\n\n",
*/
"can_obj_theoretically_use_cargo_op = {", show(n_intervals + 2), "} ", show(can_obj_theoretically_use_cargo_op), "\n\n",
"is_obj_totally_terminated = {", show(n_intervals + 2), "} ", show(is_obj_totally_terminated), "\n\n",
"main_location = {", show(n_locations), "} ", show(main_location), "\n\n",
"is_fixed_op_planned_in_future = {", show(n_locations), " ", show(n_intervals), "} ", show(is_fixed_op_planned_in_future), "\n\n",
"can_obj_leave_loc_only_alone {", show(n_locations), "} = ", show(can_obj_leave_loc_only_alone), "\n\n",
/* /*
"is_op_possible {", show(n_intervals), "} = ", show(is_op_possible), "\n\n", "is_op_possible {", show(n_intervals), "} = ", show(is_op_possible), "\n\n",
"debug_1 {", show(n_intervals), "} = ", show(debug_1), "\n\n", "debug_1 {", show(n_intervals), "} = ", show(debug_1), "\n\n",
"is_enough_free_resources {", show(n_intervals), "} = ", show(is_enough_free_resources), "\n\n", "is_enough_free_resources {", show(n_intervals), "} = ", show(is_enough_free_resources), "\n\n",
"operation_of_counter {", show(n_resources_counters), "} = ", show(operation_of_counter), "\n\n", "operation_of_counter {", show(n_resources_counters), "} = ", show(operation_of_counter), "\n\n",
"possible_resources_counter {", show(n_intervals), "} = ", show(possible_resources_counter), "\n\n", "possible_resources_counter {", show(n_intervals), "} = ", show(possible_resources_counter), "\n\n",
*/ */
""]; ""];
...@@ -116,6 +116,26 @@ public class ConversionUtil { ...@@ -116,6 +116,26 @@ public class ConversionUtil {
writer.write("]);\n"); writer.write("]);\n");
} }
static private <T> void write3dArray(FileWriter writer,
String name,
ArrayList<ArrayList<ArrayList<T>>> array,
Function<T, String> toString) throws IOException {
int dim1 = array.size();
int dim2 = (dim1 > 0) ? array.get(0).size() : 0;
int dim3 = (dim2 > 0) ? array.get(0).get(0).size() : 0;
writer.write(name + " = array3d(1.." + dim1 + ", 1.." + dim2 + ", 1.." + dim3 + ", ");
ArrayList<String> values = new ArrayList<>();
for (ArrayList<ArrayList<T>> a2 : array) {
for (ArrayList<T> a1 : a2) {
for (T val : a1) {
values.add(toString.apply(val));
}
}
}
writer.write("[" + String.join(", ", values) + "]);\n");
}
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 {
...@@ -896,6 +916,21 @@ public class ConversionUtil { ...@@ -896,6 +916,21 @@ public class ConversionUtil {
bunker_of_cargo_op.add(0); bunker_of_cargo_op.add(0);
} }
} }
ArrayList<ArrayList<Integer>> sections_of_moving_obj = arrayOfIntegerArrays(movingObjects.size());
for (int i = 0; i < movingObjects.size(); i++) {
if (movingObjects.get(i) instanceof TransportShip) {
TransportShip ship = ((TransportShip) movingObjects.get(i));
for (Pair<Cargo, Double> p : ship.getStorageSections()) {
sections_of_moving_obj.get(i).add(sectionIdToN(ship, p.getKey()) + 1);
}
}
}
ArrayList<Boolean> is_sections_of_moving_obj_empty = new ArrayList<>();
for (ArrayList<Integer> sections : sections_of_moving_obj) {
is_sections_of_moving_obj_empty.add(sections.isEmpty());
}
writer.write("n_loading_op = " + loadingOpDelta.size() + ";\n"); writer.write("n_loading_op = " + loadingOpDelta.size() + ";\n");
writeArray(writer, "involved_operations", involvedOperations, ConversionUtil::arrayToStringAsSet); writeArray(writer, "involved_operations", involvedOperations, ConversionUtil::arrayToStringAsSet);
...@@ -913,6 +948,9 @@ public class ConversionUtil { ...@@ -913,6 +948,9 @@ public class ConversionUtil {
writeArray(writer, "operations_cargo_t", operations_cargo_t, Optional.of(1)); writeArray(writer, "operations_cargo_t", operations_cargo_t, Optional.of(1));
writeArray(writer, "bunker_of_cargo_op", bunker_of_cargo_op, Optional.of(0)); writeArray(writer, "bunker_of_cargo_op", bunker_of_cargo_op, Optional.of(0));
writeArray(writer, "sections_of_moving_obj", sections_of_moving_obj, ConversionUtil::arrayToStringAsSet);
writeArray(writer, "is_sections_of_moving_obj_empty", is_sections_of_moving_obj_empty);
writer.write("\n"); writer.write("\n");
} }
...@@ -1319,6 +1357,17 @@ public class ConversionUtil { ...@@ -1319,6 +1357,17 @@ public class ConversionUtil {
} }
} }
} }
{ // Взаимоисключение всех возможных пар операций перемещения с одним деятелем и пунктом отправления.
if ((operationTemplates.get(i) instanceof MovingTemplate) &&
(operationTemplates.get(j) instanceof MovingTemplate)) {
MovingTemplate op1 = (MovingTemplate) operationTemplates.get(i);
MovingTemplate op2 = (MovingTemplate) operationTemplates.get(j);
if ((op1.getMover() == op2.getMover()) && (op1.getStartLocation() == op2.getStartLocation())) {
conflictingOperationsG.get(i).add(j + 1);
}
}
}
} }
} }
writeArray(writer, "conflicting_operations", conflictingOperationsG, ConversionUtil::setToString, writeArray(writer, "conflicting_operations", conflictingOperationsG, ConversionUtil::setToString,
...@@ -1358,6 +1407,8 @@ public class ConversionUtil { ...@@ -1358,6 +1407,8 @@ public class ConversionUtil {
ArrayList<Integer> fixedOpEnd = new ArrayList<>(); ArrayList<Integer> fixedOpEnd = new ArrayList<>();
ArrayList<Integer> fixedOpIntensity = new ArrayList<>(); ArrayList<Integer> fixedOpIntensity = new ArrayList<>();
ArrayList<ArrayList<ArrayList<Boolean>>> is_fixed_op_planned_in_future = new ArrayList<>();
class OperationData implements Comparable<OperationData> { class OperationData implements Comparable<OperationData> {
private int opId, executorId; private int opId, executorId;
private OptionalInt bunkerId; private OptionalInt bunkerId;
...@@ -1404,6 +1455,16 @@ public class ConversionUtil { ...@@ -1404,6 +1455,16 @@ public class ConversionUtil {
} }
} }
for (int i = 0; i < movingObjects.size(); i++) {
is_fixed_op_planned_in_future.add(new ArrayList<>());
for (int j = 0; j < locationNumberById.size(); j++) {
is_fixed_op_planned_in_future.get(i).add(new ArrayList<>());
for (int k = 0; k < n_intervals; k++) {
is_fixed_op_planned_in_future.get(i).get(j).add(false);
}
}
}
for (Operation op : task.getFixedOperations()) { for (Operation op : task.getFixedOperations()) {
if (op.getFixation()) { if (op.getFixation()) {
OptionalInt bunkerId = op.getBunker().map(b -> OptionalInt.of(b.getId())).orElse(OptionalInt.empty()); OptionalInt bunkerId = op.getBunker().map(b -> OptionalInt.of(b.getId())).orElse(OptionalInt.empty());
...@@ -1427,6 +1488,12 @@ public class ConversionUtil { ...@@ -1427,6 +1488,12 @@ public class ConversionUtil {
} }
} }
int loc = getLocNById(op.getTemplate().getStartLocation().getId(), false);
int executor = mObjToN(op.getExecutor());
for (int i = 0; i < end; i++) {
is_fixed_op_planned_in_future.get(executor).get(loc).set(i, true);
}
fixedOp.add(opNo + 1); fixedOp.add(opNo + 1);
TreeSet<Integer> resources = new TreeSet<>(); TreeSet<Integer> resources = new TreeSet<>();
for (MovingObject obj : op.getResources()) { for (MovingObject obj : op.getResources()) {
...@@ -1447,6 +1514,8 @@ public class ConversionUtil { ...@@ -1447,6 +1514,8 @@ public class ConversionUtil {
writeArray(writer, "fixed_op_intensity", fixedOpIntensity); writeArray(writer, "fixed_op_intensity", fixedOpIntensity);
locWrite2DArray(writer, "is_fixed", getIsFixedArray(), Objects::toString, true); locWrite2DArray(writer, "is_fixed", getIsFixedArray(), Objects::toString, true);
locWrite2DArray(writer, "is_obj_involved_in_fixed_op", is_obj_involved_in_fixed_op, Objects::toString, true); locWrite2DArray(writer, "is_obj_involved_in_fixed_op", is_obj_involved_in_fixed_op, Objects::toString, true);
write3dArray(writer, "is_fixed_op_planned_in_future", is_fixed_op_planned_in_future, Objects::toString);
} }
void defDataForCurMovingOp() throws IOException { void defDataForCurMovingOp() throws IOException {
...@@ -1548,6 +1617,62 @@ public class ConversionUtil { ...@@ -1548,6 +1617,62 @@ public class ConversionUtil {
writeArray(writer, "bunker_start_loc", bunkerStartLoc, (Integer val) -> val + 1, Optional.of(-1)); writeArray(writer, "bunker_start_loc", bunkerStartLoc, (Integer val) -> val + 1, Optional.of(-1));
} }
void dataForOptimization3() throws IOException {
ArrayList<ArrayList<Integer>> min_positive_cargo_val = arrayOfIntegerArrays(sectionNById.size());
ArrayList<ArrayList<Integer>> max_negative_cargo_val = arrayOfIntegerArrays(sectionNById.size());
ArrayList<ArrayList<Boolean>> can_obj_leave_loc_only_alone = new ArrayList<>();
for (int i = 0; i < sectionNById.size(); i++) {
for (int j = 0; j < locationNumberById.size(); j++) {
min_positive_cargo_val.get(i).add(maxStorageVol.get(i) + 1);
max_negative_cargo_val.get(i).add(-maxStorageVol.get(i) - 1);
}
}
for (int i = 0; i < movingObjects.size(); i++) {
can_obj_leave_loc_only_alone.add(new ArrayList<>());
for (int j = 0; j < locationNumberById.size(); j++) {
can_obj_leave_loc_only_alone.get(i).add((j + 1) % 2 == 1);
}
}
for (OperationTemplate t : operationTemplates) {
if (t instanceof LoadingTemplate) {
LoadingTemplate op = (LoadingTemplate) t;
int val = (int) op.getIntensity();
int loc = getLocNById(op.getStartLocation().getId(), false) ;
ArrayList<Pair<Integer, Integer>> sections = new ArrayList<>();
sections.add(new Pair<>(sectionIdToN(op.getLoader(), op.getCargo()), val));
if (op.getBunker().isPresent()) {
sections.add(new Pair<>(sectionIdToN(op.getBunker().get(), op.getCargo()), -val));
} else {
sections.add(new Pair<>(sectionIdToN(op.getStorage(), op.getCargo()), -val));
}
for (Pair<Integer, Integer> p : sections) {
if (p.getValue() > 0) {
min_positive_cargo_val.get(p.getKey()).set(loc, Math.min(p.getValue(), min_positive_cargo_val.get(p.getKey()).get(loc)));
} else {
max_negative_cargo_val.get(p.getKey()).set(loc, Math.max(p.getValue(), max_negative_cargo_val.get(p.getKey()).get(loc)));
}
}
} else if (t instanceof MovingTemplate) {
int loc = getLocNById(t.getStartLocation().getId(), false);
int obj = mObjToN(getExecutor(t));
if (! ((MovingTemplate) t).getResourcesTypes().isEmpty()) {
can_obj_leave_loc_only_alone.get(obj).set(loc, false);
}
}
}
write2DArrayOfInt(writer, "min_positive_cargo_val", min_positive_cargo_val, false);
write2DArrayOfInt(writer, "max_negative_cargo_val", max_negative_cargo_val, false);
locWrite2DArray(writer, "can_obj_leave_loc_only_alone", can_obj_leave_loc_only_alone, Objects::toString);
writer.write("\n");
}
/* С типизацией. */ /* С типизацией. */
void portToMiniZinc_2() throws IOException { void portToMiniZinc_2() throws IOException {
if (!task.isTypified()) { if (!task.isTypified()) {
...@@ -1588,6 +1713,7 @@ public class ConversionUtil { ...@@ -1588,6 +1713,7 @@ public class ConversionUtil {
boundaryStorageStates(); boundaryStorageStates();
cargoFlows(); cargoFlows();
cargoOperations(); cargoOperations();
dataForOptimization3();
fixedOperations(); fixedOperations();
} finally { } finally {
......
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