diff --git a/src/inport/ConversionUtil.java b/src/inport/ConversionUtil.java index 1b11bd09c7c8b877cf347b5a8a59506f2f4db3b9..560bd837c6fbe3feab058aa3db97788d321e4d96 100644 --- a/src/inport/ConversionUtil.java +++ b/src/inport/ConversionUtil.java @@ -193,7 +193,7 @@ public class ConversionUtil { Function mObjToN = (MovingObject obj) -> mObjNumberById.get(obj.getId()); ArrayList operationTemplates = new ArrayList<>(task.getTemplates()); - { + { // Операции прибытия/отбытия в локацию. ArrayList>> arrivalOp = new ArrayList<>(); ArrayList>> departureOp = new ArrayList<>(); for (int i = 0; i < movingObjects.size(); i++) { @@ -231,10 +231,29 @@ public class ConversionUtil { initialStates.set(mObjToN.apply(state.getVessel()), locationNumberById.get(new Pair<>(state.getLocation().getId(), false))); } writeArray(writer, "initial_m_obj_loc", initialStates, (Integer p) -> p + 1); + writer.write("\n"); } - // TODO окна погоды. + { // Окна погоды. + ArrayList bw_op = new ArrayList<>(); + ArrayList bw_start = new ArrayList<>(); + ArrayList bw_fin = new ArrayList<>(); - writer.write("\n"); + for (int i = 0; i < operationTemplates.size(); i++) { + final int id = i; + operationTemplates.get(i).getTimeWindows().forEach( + (Double start, Double duration) -> { + bw_op.add(id + 1); + bw_start.add((int)Math.ceil(start)); + bw_fin.add((int)Math.floor(start + duration)); + } + ); + } + writer.write("n_bad_weather_windows = " + bw_op.size() + ";\n"); + writeArray(writer, "bw_op", bw_op); + writeArray(writer, "bw_start", bw_start); + writeArray(writer, "bw_fin", bw_fin); + writer.write("\n"); + } { // Непрерывность перемещения. ArrayList operationsDuration = integerArray(operationTemplates.size(), 0); ArrayList isMovingObj = new ArrayList<>(); @@ -260,6 +279,7 @@ public class ConversionUtil { writeArray(writer, "final_m_obj_loc", finalStates, (Integer p) -> p + 1); } { // Наличие всех ресурсов на месте. + // TODO покрывается "Конфликтующими операциями". ArrayList> operationsResources = new ArrayList<>(); ArrayList operationsStartLoc = integerArray(operationTemplates.size(), 0); for (int i = 0; i < operationTemplates.size(); i++) { diff --git a/test/conversion_0.mzn b/test/conversion_0.mzn index cd523c8bc41c663948cdc315a5324f433c478856..94a5d22f33b3d8aac8500cd5e904d54f16d02d15 100644 --- a/test/conversion_0.mzn +++ b/test/conversion_0.mzn @@ -108,6 +108,16 @@ constraint forall (t in 0..(n_intervals + 1), i in 1..n_conflicting_op) ( (op_status[confl_op_2[i], t] -> not op_status[confl_op_1[i], t]) ); +% Окна непогоды. +int : n_bad_weather_windows; +array [1..n_bad_weather_windows] of 1..n_operations : bw_op; +array [1..n_bad_weather_windows] of 0..(n_intervals + 1) : bw_start; +array [1..n_bad_weather_windows] of 0..(n_intervals + 1) : bw_fin; % Включительно. + +constraint forall (i in 1..n_bad_weather_windows) ( + forall (t in bw_start[i]..bw_fin[i]) (op_status[bw_op[i], t] == 0) +); + % Критерий оптимизации array [0..(n_intervals + 1)] of var bool : is_not_terminated; constraint (is_not_terminated[0] == 0 /\ is_not_terminated[n_intervals + 1] == 0); diff --git a/test/shortest_path_with_weather.ipp b/test/shortest_path_with_weather.ipp new file mode 100644 index 0000000000000000000000000000000000000000..bcd5e950f1017ec328cfcbc914bddaa73544c547 --- /dev/null +++ b/test/shortest_path_with_weather.ipp @@ -0,0 +1,49 @@ +Cargoes +0; Груз1 +Berths +1;Raid +2;Pier 1 +3;Pier 2 +4;Pier 3 +5;Pier 4 +6;Pier 5 +7;Pier 6 +Storages +Bunkers +Tows +Loading Equipments +Transport Ships +11;Ship 1;0.0 +12;Ship 2;0.0 + +Templates +101;mov;[]; 11;1;4;[];3.0 +102;mov;[]; 11;1;2;[];4.0 +103;mov;[]; 11;1;5;[];10.0 +104;mov;[5:1];11;2;3;[];9.0 +105;mov;[]; 11;3;1;[];5.0 +106;mov;[4:2];11;4;6;[];2.0 +107;mov;[]; 11;5;6;[];1.0 +108;mov;[]; 11;6;3;[];7.0 +109;mov;[]; 11;6;7;[];5.0 +110;mov;[]; 11;7;3;[];3.0 + +Cargo Flows +Initial Vessel State +11;1 +12;1 +Initial Storage State +0;11;0.0 +0;12;0.0 +Final Vessel State +11;3 +12;1 +Final Storage State +0;11;0.0 +0;12;0.0 + +Task Properties +30.0;0 + +Solution +15.0