Commit c489eecc authored by Vladislav Kiselev's avatar Vladislav Kiselev

Поддержка фиксированных операций и соответствующий тест.

parent 4c4fdc33
...@@ -344,6 +344,24 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ...@@ -344,6 +344,24 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац
) )
); );
% Фиксированные операции.
int : n_fixed_op;
array [1..n_fixed_op] of 1..n_operations : fixed_op;
array [1..n_fixed_op] of set of 1..n_moving_obj : fixed_op_resources;
array [1..n_fixed_op] of 1..n_intervals : fixed_op_start;
array [1..n_fixed_op] of 1..n_intervals : fixed_op_end; % Включительно.
array [1..n_operations, 1..n_intervals] of bool : is_fixed;
constraint forall (no in 1..n_fixed_op, op = fixed_op[no]) (
forall (t in fixed_op_start[no]..fixed_op_end[no]) (
(op_status[op, t]) /\
forall (obj in fixed_op_resources[no]) (
participation_as_resource[obj, t] = op
)
)
);
% Оптимизация - сдвиг в начало. % Оптимизация - сдвиг в начало.
% Возможно ли начать операцию в данный интервал (если предположить, что операция длится 1 интервал). % Возможно ли начать операцию в данный интервал (если предположить, что операция длится 1 интервал).
array [1..n_operations, 1..n_intervals] of var bool : is_op_possible; array [1..n_operations, 1..n_intervals] of var bool : is_op_possible;
...@@ -415,7 +433,7 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац ...@@ -415,7 +433,7 @@ array [1..n_operations] of 1..n_locations : operations_destination; % Локац
% Сам критерий оптимизации - если если операцию можно было начать на 1 интервал раньше, то её нужно начать раньше. % Сам критерий оптимизации - если если операцию можно было начать на 1 интервал раньше, то её нужно начать раньше.
constraint forall (op in 1..n_operations, t in 2..n_intervals) ( constraint forall (op in 1..n_operations, t in 2..n_intervals) (
op_start[op, t] -> not is_op_possible[op, t - 1] (op_start[op, t] /\ (not is_fixed[op, t])) -> not is_op_possible[op, t - 1]
); );
% Критерий оптимизации % Критерий оптимизации
......
...@@ -8,8 +8,8 @@ import java.util.function.BiConsumer; ...@@ -8,8 +8,8 @@ import java.util.function.BiConsumer;
import java.util.function.Function; import java.util.function.Function;
public class ConversionUtil { public class ConversionUtil {
static class PairComparator implements Comparator<Pair<Integer, Boolean>> { static class PairComparator<T extends Comparable, U extends Comparable> implements Comparator<Pair<T, U>> {
public int compare(Pair<Integer, Boolean> p1, Pair<Integer, Boolean> p2) { public int compare(Pair<T, U> p1, Pair<T, U> p2) {
int res = p1.getKey().compareTo(p2.getKey()); int res = p1.getKey().compareTo(p2.getKey());
if (res != 0) { if (res != 0) {
return res; return res;
...@@ -1150,6 +1150,65 @@ public class ConversionUtil { ...@@ -1150,6 +1150,65 @@ public class ConversionUtil {
writeArray(writer, "conflicting_operations", conflictingOperationsG, ConversionUtil::setToString); writeArray(writer, "conflicting_operations", conflictingOperationsG, ConversionUtil::setToString);
} }
public ArrayList<ArrayList<Boolean>> getIsFixedArray() {
Map<Pair<Integer, Integer>, Integer> opNoByOpIdAndExecutorNo = new TreeMap<>(new PairComparator<>());
for (int i = 0; i < operationTemplates.size(); i++) {
OperationTemplate op = operationTemplates.get(i);
opNoByOpIdAndExecutorNo.put(new Pair<>(op.getId(), getExecutor(op).getId()), i);
}
ArrayList<ArrayList<Boolean>> isFixed = new ArrayList<>();
for (int i = 0; i < operationTemplates.size(); i++) {
isFixed.add(new ArrayList<>());
for (int j = 0; j < n_intervals; j++) {
isFixed.get(i).add(false);
}
}
for (Operation op : task.getSolution()) {
if (op.getFixation()) {
int operation = opNoByOpIdAndExecutorNo.get(new Pair<>(op.getTemplate().getId(), op.getExecutor().getId()));
for (int i = (int)Math.floor(op.getStart()); i < (int)Math.ceil(op.getDuration() + op.getStart()); i++) {
isFixed.get(operation).set(i, true);
}
}
}
return isFixed;
}
private void fixedOperations() throws IOException {
ArrayList<Integer> fixedOp = new ArrayList<>();
ArrayList<Set<Integer>> fixedOpResources = new ArrayList<>();
ArrayList<Integer> fixedOpStart = new ArrayList<>();
ArrayList<Integer> fixedOpEnd = new ArrayList<>();
Map<Pair<Integer, Integer>, Integer> opNoByOpIdAndExecutorNo = new TreeMap<>(new PairComparator<>());
for (int i = 0; i < operationTemplates.size(); i++) {
OperationTemplate op = operationTemplates.get(i);
opNoByOpIdAndExecutorNo.put(new Pair<>(op.getId(), getExecutor(op).getId()), i);
}
for (Operation op : task.getSolution()) {
if (op.getFixation()) {
fixedOp.add(opNoByOpIdAndExecutorNo.get(new Pair<>(op.getTemplate().getId(), op.getExecutor().getId())) + 1);
TreeSet<Integer> resources = new TreeSet<>();
for (MovingObject obj : op.getResources()) {
resources.add(mObjToN(obj));
}
fixedOpResources.add(resources);
fixedOpStart.add((int)Math.floor(op.getStart()) + 1);
fixedOpEnd.add((int)Math.ceil(op.getDuration() + op.getStart()));
}
}
writer.write("n_fixed_op = " + fixedOp.size() + ";\n");
writeArray(writer, "fixed_op", fixedOp);
writeArray(writer, "fixed_op_resources", fixedOpResources, ConversionUtil::setToString);
writeArray(writer, "fixed_op_start", fixedOpStart);
writeArray(writer, "fixed_op_end", fixedOpEnd);
locWrite2DArray(writer, "is_fixed", getIsFixedArray(), Objects::toString);
}
private void typifiedResourcesDefinition() throws IOException { private void typifiedResourcesDefinition() throws IOException {
{ // objects_of_type и operations_that_used_obj_as_resource { // objects_of_type и operations_that_used_obj_as_resource
writer.write("n_resources_types = " + typeToN.size() + ";\n"); writer.write("n_resources_types = " + typeToN.size() + ";\n");
...@@ -1254,6 +1313,8 @@ public class ConversionUtil { ...@@ -1254,6 +1313,8 @@ public class ConversionUtil {
boundaryStorageStates(); boundaryStorageStates();
cargoFlows(); cargoFlows();
cargoOperations(); cargoOperations();
fixedOperations();
} finally { } finally {
if (writer != null) { if (writer != null) {
writer.close(); writer.close();
...@@ -1390,6 +1451,7 @@ public class ConversionUtil { ...@@ -1390,6 +1451,7 @@ public class ConversionUtil {
} }
Map<Integer, MovingObject> objByNo = new TreeMap<>(); Map<Integer, MovingObject> objByNo = new TreeMap<>();
ArrayList<ArrayList<Boolean>> isFixed;
{ {
Task t = new Task(task, ""); Task t = new Task(task, "");
ArrayList<MovingObject> movingObjects = new ArrayList<>(); ArrayList<MovingObject> movingObjects = new ArrayList<>();
...@@ -1400,14 +1462,25 @@ public class ConversionUtil { ...@@ -1400,14 +1462,25 @@ public class ConversionUtil {
for (MovingObject obj : movingObjects) { for (MovingObject obj : movingObjects) {
objByNo.put(t.getMObjNumberById().get(obj.getId()), obj); objByNo.put(t.getMObjNumberById().get(obj.getId()), obj);
} }
isFixed = t.getIsFixedArray();
}
Set<String> oldSolution = new TreeSet<>();
for (Operation op : task.getSolution()) {
if (op.getFixation()) {
oldSolution.add(op.toString());
}
} }
for (int opNo = 0; opNo < opStatus.size(); opNo++) { for (int opNo = 0; opNo < opStatus.size(); opNo++) {
int duration = 0; int duration = 0;
for (int t = 0; t < opStatus.get(opNo).size(); t++) { int t = 0;
if (opStatus.get(opNo).get(t).equals("true")) { boolean lastFixation = false;
duration++;
} else if (duration != 0) { while (t < opStatus.get(opNo).size()) {
if ((opStatus.get(opNo).get(t).equals("true") && (lastFixation != isFixed.get(opNo).get(t - 1)))
|| (opStatus.get(opNo).get(t).equals("false") && (duration != 0))) { // Добавляем новую операцию.
Operation op = new Operation(); Operation op = new Operation();
op.setStart(t - duration - 1); op.setStart(t - duration - 1);
op.setDuration(duration); op.setDuration(duration);
...@@ -1428,9 +1501,25 @@ public class ConversionUtil { ...@@ -1428,9 +1501,25 @@ public class ConversionUtil {
op.setResources(resources); op.setResources(resources);
} }
op.setFixation(true);
if (! oldSolution.contains(op.toString())) {
op.setFixation(false);
}
operations.add(op); operations.add(op);
duration = 0; duration = 0;
} }
if (opStatus.get(opNo).get(t).equals("true") && (lastFixation != isFixed.get(opNo).get(t - 1))) { // Остаёмся на месте.
lastFixation = isFixed.get(opNo).get(t - 1);
continue;
}
if (opStatus.get(opNo).get(t).equals("true")) {
duration++;
}
if ((0 <= t - 1) && (t - 1 < isFixed.get(opNo).size())) {
lastFixation = isFixed.get(opNo).get(t - 1);
}
t++;
} }
} }
} }
......
...@@ -13,11 +13,19 @@ import java.util.List; ...@@ -13,11 +13,19 @@ import java.util.List;
public class Operation { public class Operation {
private OperationTemplate template; private OperationTemplate template;
private boolean fixation = false;
private double start; private double start;
private double duration; private double duration;
private MovingObject executor; private MovingObject executor;
private List<MovingObject> resources; private List<MovingObject> resources;
public boolean getFixation() {
return fixation;
}
public void setFixation(boolean fixation) {
this.fixation = fixation;
}
public List<MovingObject> getResources() { public List<MovingObject> getResources() {
return resources; return resources;
} }
...@@ -100,7 +108,8 @@ public class Operation { ...@@ -100,7 +108,8 @@ public class Operation {
resources = ConversionUtil.getResources(template); resources = ConversionUtil.getResources(template);
} }
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(template.getId()).append("; R; ").append(start).append("; ").append(duration); sb.append(template.getId()).append("; ");
sb.append(fixation ? "F" : "R").append("; ").append(start).append("; ").append(duration);
sb.append(" (").append(executor.getId()).append(" ["); sb.append(" (").append(executor.getId()).append(" [");
boolean isFirst = true; boolean isFirst = true;
for (MovingObject obj : resources) { for (MovingObject obj : resources) {
......
...@@ -650,6 +650,34 @@ public class TaskCase { ...@@ -650,6 +650,34 @@ public class TaskCase {
case Solution: // Тут чтение операций если надо. Потом подумаем case Solution: // Тут чтение операций если надо. Потом подумаем
if (numInside == 1) { if (numInside == 1) {
solution_result = Double.parseDouble(strLine.trim()); solution_result = Double.parseDouble(strLine.trim());
} else {
String lStr = strLine.substring(0, strLine.indexOf('(')).trim();
String rStr = strLine.substring(strLine.indexOf('(') + 1, strLine.indexOf(')')).trim();
Operation op = new Operation();
{
String[] items = lStr.split(";");
op.setStart(Double.parseDouble(items[2].trim()));
op.setDuration(Double.parseDouble(items[3].trim()));
op.setTemplate(m_template.get(Integer.parseInt(items[0].trim())));
op.setFixation(items[1].trim().equals("F"));
}
{
String[] items = rStr.substring(rStr.indexOf('[') + 1, rStr.indexOf(']')).split(",");
ArrayList<MovingObject> resources = new ArrayList<>();
for (String item : items) {
if (item.trim().isEmpty()) {
continue;
}
resources.add(m_equipment.get(Integer.valueOf(item.trim())));
}
op.setResources(resources);
}
int exId = Integer.valueOf(rStr.substring(0, rStr.indexOf('[')).trim());
op.setExecutor(m_vessel.get(exId));
solution.add(op);
} }
break; break;
default: default:
......
Typified
1
Cargoes
0; LNG; 0.0
Berths
1; Raid
2; Pier 1
3; Pier 2
Storages
4; Storage 1; 0; 10000.0
Vessel Types
1001; Тип судна1
Bunkers
Tows
Loading Equipment Types
Loading Equipments
Transport Ships
5; Ship 1; 2000.0; 1001
6; Ship 2; 2000.0; 1001
Templates
7; mov; []; 1001; 1; 2; []; 1.0
8; mov; []; 1001; 2; 1; []; 1.0
9; mov; []; 1001; 1; 3; []; 1.0
10; mov; []; 1001; 3; 1; []; 1.0
11; mov; []; 1001; 2; 3; []; 1.0
12; mov; []; 1001; 3; 2; []; 1.0
19; loa; []; 4; 0; 1001; 2; []; 100.0; U
20; loa; []; 4; 0; 1001; 3; []; 50.0; U
21; mov; []; 1001; 1; 1; []; 3.0
Cargo Flows
Initial Vessel State
5; 1
6; 1
Initial Storage State
0; 5; 0.0
0; 6; 0.0
0; 4; 10000.0
Final Vessel State
5; 1
6; 1
Final Storage State
0; 5; 1000.0
0; 6; 1000.0
Task Properties
30.0; 0
Solution
18.0
21; F; 0.0; 3.0 (5 [])
19; F; 6.0; 3.0 (5 [])
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