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; % Локац
)
);
% Фиксированные операции.
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 интервал).
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; % Локац
% Сам критерий оптимизации - если если операцию можно было начать на 1 интервал раньше, то её нужно начать раньше.
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;
import java.util.function.Function;
public class ConversionUtil {
static class PairComparator implements Comparator<Pair<Integer, Boolean>> {
public int compare(Pair<Integer, Boolean> p1, Pair<Integer, Boolean> p2) {
static class PairComparator<T extends Comparable, U extends Comparable> implements Comparator<Pair<T, U>> {
public int compare(Pair<T, U> p1, Pair<T, U> p2) {
int res = p1.getKey().compareTo(p2.getKey());
if (res != 0) {
return res;
......@@ -1150,6 +1150,65 @@ public class ConversionUtil {
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 {
{ // objects_of_type и operations_that_used_obj_as_resource
writer.write("n_resources_types = " + typeToN.size() + ";\n");
......@@ -1254,6 +1313,8 @@ public class ConversionUtil {
boundaryStorageStates();
cargoFlows();
cargoOperations();
fixedOperations();
} finally {
if (writer != null) {
writer.close();
......@@ -1390,6 +1451,7 @@ public class ConversionUtil {
}
Map<Integer, MovingObject> objByNo = new TreeMap<>();
ArrayList<ArrayList<Boolean>> isFixed;
{
Task t = new Task(task, "");
ArrayList<MovingObject> movingObjects = new ArrayList<>();
......@@ -1400,14 +1462,25 @@ public class ConversionUtil {
for (MovingObject obj : movingObjects) {
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++) {
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) {
int t = 0;
boolean lastFixation = false;
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();
op.setStart(t - duration - 1);
op.setDuration(duration);
......@@ -1428,9 +1501,25 @@ public class ConversionUtil {
op.setResources(resources);
}
op.setFixation(true);
if (! oldSolution.contains(op.toString())) {
op.setFixation(false);
}
operations.add(op);
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;
public class Operation {
private OperationTemplate template;
private boolean fixation = false;
private double start;
private double duration;
private MovingObject executor;
private List<MovingObject> resources;
public boolean getFixation() {
return fixation;
}
public void setFixation(boolean fixation) {
this.fixation = fixation;
}
public List<MovingObject> getResources() {
return resources;
}
......@@ -100,7 +108,8 @@ public class Operation {
resources = ConversionUtil.getResources(template);
}
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(" [");
boolean isFirst = true;
for (MovingObject obj : resources) {
......
......@@ -650,6 +650,34 @@ public class TaskCase {
case Solution: // Тут чтение операций если надо. Потом подумаем
if (numInside == 1) {
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;
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