diff --git a/src/inport/Berth.java b/src/inport/Berth.java new file mode 100644 index 0000000000000000000000000000000000000000..2e56e4939913957e3a241f8e865b77fdaf3b99f0 --- /dev/null +++ b/src/inport/Berth.java @@ -0,0 +1,81 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class Berth { + + private int id; + private String name; + private boolean isRaid; + + /** + * Get the value of name + * + * @return the value of name + */ + public String getName() { + return name; + } + + /** + * Set the value of name + * + * @param name new value of name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Get the value of id + * + * @return the value of id + */ + public int getId() { + return id; + } + + /** + * Set the value of id + * + * @param id new value of id + */ + public void setId(int id) { + this.id = id; + } + + public boolean getIsRaid() { + return isRaid; + } + + public void setIsRaid(boolean isRaid) { + this.isRaid = isRaid; + } + + public Berth(int id, String name, boolean isRaid) { + this.id = id; + this.name = name; + this.isRaid = isRaid; + } + + public Berth() { + } + + @Override + public String toString() { + return id + ";" + name; + } + + public Berth(String s) { + String[] tokens = s.split(";"); + id = Integer.parseInt(tokens[0].trim()); + name = tokens[1].trim(); + } + +} diff --git a/src/inport/Bunker.java b/src/inport/Bunker.java new file mode 100644 index 0000000000000000000000000000000000000000..3be110471fec467ac14e52363b8f4bbe5ffa6fc0 --- /dev/null +++ b/src/inport/Bunker.java @@ -0,0 +1,33 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class Bunker extends MovingObject { + + public Bunker(int id, String name) { + super(id, name); + } + + public Bunker() { + super( ); + } + + + @Override + public String toString() { + return getId() + ";" + getName(); + } + + public Bunker(String s) { + super(s); + } + + + +} diff --git a/src/inport/Cargo.java b/src/inport/Cargo.java new file mode 100644 index 0000000000000000000000000000000000000000..3b8b5638dd7de495f46f046c0bf8f0b96474471f --- /dev/null +++ b/src/inport/Cargo.java @@ -0,0 +1,91 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class Cargo { + + private double cost; + private int id; + private String name; + + /** + * Get the value of cost + * + * @return the value of cost + */ + public double getCost() { + return cost; + } + + /** + * Set the value of cost + * + * @param cost new value of cost + */ + public void setCost(double cost) { + this.cost = cost; + } + + /** + * Get the value of name + * + * @return the value of name + */ + public String getName() { + return name; + } + + /** + * Set the value of name + * + * @param name new value of name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Get the value of id + * + * @return the value of id + */ + public int getId() { + return id; + } + + /** + * Set the value of id + * + * @param id new value of id + */ + public void setId(int id) { + this.id = id; + } + + public Cargo(double cost, int id, String name) { + this.cost = cost; + this.id = id; + this.name = name; + } + + public Cargo() { + } + + @Override + public String toString() { + return id + ";" + name + ";" + cost; + } + + public Cargo(String s) { + String[] tokens = s.split(";"); + id = Integer.parseInt(tokens[0].trim()); + name = tokens[1].trim(); + cost = 0; //Double.parseDouble(tokens[2]); + } +} diff --git a/src/inport/CargoFlow.java b/src/inport/CargoFlow.java new file mode 100644 index 0000000000000000000000000000000000000000..cdc5459fd15b96fb1498ef0c322dd7e9355899c0 --- /dev/null +++ b/src/inport/CargoFlow.java @@ -0,0 +1,142 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * + * @author topazh_ag + */ +public class CargoFlow { + + private Storage storage; + private Cargo cargo; + Map flow; + + public Map getFlow() { + return flow; + } + + public void setFlow(Map flow) { + this.flow = flow; + } + + /** + * Get the value of storage + * + * @return the value of storage + */ + public Storage getStorage() { + return storage; + } + + /** + * Set the value of storage + * + * @param storage new value of storage + */ + public void setStorage(Storage storage) { + this.storage = storage; + } + + public Cargo getCargo() { + return cargo; + } + + public void setCargo(Cargo cargo) { + this.cargo = cargo; + } + + public CargoFlow() { + this.flow = new HashMap<>(); + } + + public CargoFlow(Storage storage, Cargo cargo) { + this.storage = storage; + this.cargo = cargo; + this.flow = new HashMap<>(); + } + + public double getCurrentValue(double forTime) + { + double res = 0.0; + boolean isFound = false; + Set keyTimes = flow.keySet(); + double prevKey = -1.0; + for (Double keyTime : keyTimes) + { + if (forTime>prevKey && forTimeprevKey) + res = flow.get(prevKey); + return res; + } + + public double getTotalValue(double forTime) + { + double res = 0.0; + boolean isFound = false; + Set keyTimes = flow.keySet(); + double prevKey = -1.0; + for (Double keyTime : keyTimes) + { + if (forTime>prevKey && forTimeprevKey) + res += flow.get(prevKey)*(forTime-prevKey); + return res; + } + + @Override + public String toString() { + String res = ""; + boolean first = true; + for(Double s : flow.keySet()) + { + if (!first) + res += "," + s+ ":" + flow.get(s); + else + res += s + ":" + flow.get(s); + first = false; + } + return storage.getId() + ";[" + res +"]"; + } + + public CargoFlow(String s, Map mp, Map cp) { + this.flow = new HashMap<>(); + String[] tokens = s.split(";"); + int key = Integer.parseInt(tokens[0].trim()); + storage = mp.get(key); + key = Integer.parseInt(tokens[1].trim()); + cargo = cp.get(key); + String[] rs = tokens[2].trim().replace("[", "").replace("]", "").split(","); + for (String crs : rs) + if (crs.length()>0) + { + String[] kv = crs.split(":"); + Double key1 = Double.parseDouble(kv[0].trim()); + Double value1 = Double.parseDouble(kv[1].trim()); + flow.put(key1, value1); + } + } +} diff --git a/src/inport/ConversionException.java b/src/inport/ConversionException.java new file mode 100644 index 0000000000000000000000000000000000000000..f266122b06e46bc76ee81ea6a260e238d18b21d3 --- /dev/null +++ b/src/inport/ConversionException.java @@ -0,0 +1,7 @@ +package inport; + +public class ConversionException extends Exception { + ConversionException(String mess) { + super(mess); + } +} diff --git a/src/inport/ConversionUtil.java b/src/inport/ConversionUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..bee75a7afe2f1a223eea3ce6ccbb4b77094e94c3 --- /dev/null +++ b/src/inport/ConversionUtil.java @@ -0,0 +1,217 @@ +package inport; + +import javafx.util.Pair; + +import java.io.FileWriter; +import java.io.IOException; +import java.util.*; +import java.util.function.Function; + +public class ConversionUtil { + static class PairComparator implements Comparator> { + public int compare(Pair p1, Pair p2) { + int res = p1.getKey().compareTo(p2.getKey()); + if (res != 0) { + return res; + } else { + return p1.getValue().compareTo(p2.getValue()); + } + } + } + + static private void write2DArray(FileWriter writer, + String name, + ArrayList>> operations) throws IOException { + writer.write(name + " = \n"); + boolean isFirst0 = true; + for (ArrayList> m1 : operations) { + if (isFirst0) { + isFirst0 = false; + writer.write(" [| "); + } else { + writer.write(" | "); + } + boolean isFirst1 = true; + for (ArrayList m2 : m1) { + if (isFirst1) { + isFirst1 = false; + } else { + writer.write(", "); + } + writer.write("{"); + boolean isFirst2 = true; + for (Integer val : m2) { + if (isFirst2) { + isFirst2 = false; + } else { + writer.write(", "); + } + writer.write((val + 1) + ""); + } + writer.write("}"); + } + writer.write("\n"); + } + writer.write(" |];\n"); + } + + static private void writeArray(FileWriter writer, String name, ArrayList data, Function f) throws IOException { + writer.write(name + " = ["); + for (int i = 0; i < data.size(); i++) { + if (i != 0) { + writer.write(", "); + } + writer.write(f.apply(data.get(i)).toString() + ""); + } + writer.write("];\n"); + } + + static private void writeArray(FileWriter writer, String name, ArrayList data) throws IOException { + writeArray(writer, name, data, (T val) -> val); + } + + static private String setToString(Set s) { + StringBuilder res = new StringBuilder(); + res.append("{"); + boolean isFirst = true; + for (T t : s) { + if (isFirst) { + isFirst = false; + } else { + res.append(", "); + } + res.append(t.toString()); + } + res.append("}"); + return res.toString(); + } + + static private ArrayList integerArray(int size, int initVal) { + ArrayList res = new ArrayList<>(); + for (int i = 0; i < size; i++) { + res.add(initVal); + } + return res; + } + + static public void portToMiniZinc(TaskCase task, String fileName) throws IOException { + try(FileWriter writer = new FileWriter(fileName, false)) { + int n_intervals = (int)task.getPlanningInterval(); + writer.write("n_intervals = " + n_intervals + ";\n"); + writer.write("n_operations = " + task.getTemplates().size() + ";\n"); + + ArrayList berths = new ArrayList<>(task.getBerths()); + Map, Integer> locationNumberById = new TreeMap<>(new PairComparator()); + for (Berth berth : berths) { + locationNumberById.put(new Pair<>(berth.getId(), false), locationNumberById.size()); + locationNumberById.put(new Pair<>(berth.getId(), true), locationNumberById.size()); + } + writer.write("n_locations = " + locationNumberById.size() + ";\n"); + + ArrayList movingObjects = new ArrayList<>(); + Map mObjNumberById = new TreeMap<>(); + for (MovingObject obj : task.getShips()) { + mObjNumberById.put(obj.getId(), movingObjects.size()); + movingObjects.add(obj); + } + for (MovingObject obj : task.getTows()) { + mObjNumberById.put(obj.getId(), movingObjects.size()); + movingObjects.add(obj); + } + writer.write("n_moving_obj = " + movingObjects.size() + ";\n"); + writer.write("\n"); + + 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++) { + arrivalOp.add(new ArrayList<>()); + departureOp.add(new ArrayList<>()); + for (int j = 0; j < locationNumberById.size(); j++) { + arrivalOp.get(i).add(new ArrayList<>()); + departureOp.get(i).add(new ArrayList<>()); + } + } + + for (int i = 0; i < operationTemplates.size(); i++) { + if (operationTemplates.get(i) instanceof MovingTemplate) { + MovingTemplate op = (MovingTemplate)operationTemplates.get(i); + + ArrayList movingObjN = new ArrayList<>(); + for (MovingObject obj : op.getResources()) { + movingObjN.add(mObjToN.apply(obj)); + } + movingObjN.add(mObjToN.apply(op.getMover())); + + for (Integer n : movingObjN) { + arrivalOp.get(n).get(locationNumberById.get(new Pair<>(op.getDestination().getId(), false))).add(i); + departureOp.get(n).get(locationNumberById.get(new Pair<>(op.getStartLocation().getId(), false))).add(i); + } + } + } + write2DArray(writer, "arrival_op", arrivalOp); + write2DArray(writer, "departure_op", departureOp); + } + + { // Начальные положения объектов. + ArrayList initialStates = integerArray(movingObjects.size(), 0); + for (MovingObjectState state : task.getVesselInitialState()) { + initialStates.set(mObjToN.apply(state.getVessel()), locationNumberById.get(new Pair<>(state.getLocation().getId(), false)) + 1); + } + writeArray(writer, "initial_m_obj_loc", initialStates); + } + // TODO окна погоды. + + writer.write("\n"); + { // Непрерывность перемещения. + ArrayList operationsDuration = integerArray(operationTemplates.size(), 0); + ArrayList isMovingObj = new ArrayList<>(); + for (int i = 0; i < operationTemplates.size(); i++) { + if (operationTemplates.get(i) instanceof MovingTemplate) { + MovingTemplate op = (MovingTemplate)operationTemplates.get(i); + int duration = (int)Math.ceil(op.getDuration()); + + operationsDuration.set(i, duration); + isMovingObj.add(true); + } else { + isMovingObj.add(false); + } + } + writeArray(writer, "operations_duration", operationsDuration); + writeArray(writer, "is_moving_operation", isMovingObj); + } + { // Конечные положения объектов. + ArrayList finalStates = integerArray(movingObjects.size(), 0); + for (MovingObjectState state : task.getVesselEndState()) { + finalStates.set(mObjToN.apply(state.getVessel()), locationNumberById.get(new Pair<>(state.getLocation().getId(), false))); + } + writeArray(writer, "final_m_obj_loc", finalStates); + } + { // Наличие всех ресурсов на месте. + ArrayList> operationsResources = new ArrayList<>(); + ArrayList operationsStartLoc = integerArray(operationTemplates.size(), 0); + for (int i = 0; i < operationTemplates.size(); i++) { + operationsResources.add(new TreeSet<>()); + if (operationTemplates.get(i) instanceof MovingTemplate) { + MovingTemplate op = (MovingTemplate)operationTemplates.get(i); + + Set s = new TreeSet<>(); + s.add(mObjToN.apply(op.getMover()) + 1); + for (MovingObject obj : op.getResources()) { + s.add(mObjToN.apply(obj) + 1); + } + operationsResources.set(i, s); + operationsStartLoc.set(i, locationNumberById.get(new Pair<>(op.getStartLocation().getId(), false))); + } + // TODO швартовка, погрузка. + } + writeArray(writer, "operations_start_loc", operationsStartLoc); + writeArray(writer, "operations_resources", operationsResources, ConversionUtil::setToString); + } + + } + } +} diff --git a/src/inport/LoadingEquipment.java b/src/inport/LoadingEquipment.java new file mode 100644 index 0000000000000000000000000000000000000000..be591e81e2b0ef9294a5b3059a1efd07f2f31adc --- /dev/null +++ b/src/inport/LoadingEquipment.java @@ -0,0 +1,31 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class LoadingEquipment extends MovingObject{ + + + public LoadingEquipment() { + super(); + } + + public LoadingEquipment(int id, String name) { + super(id, name); + } + + @Override + public String toString() { + return getId() + ";" + getName(); + } + + public LoadingEquipment(String s) { + super(s); + } + +} diff --git a/src/inport/LoadingTemplate.java b/src/inport/LoadingTemplate.java new file mode 100644 index 0000000000000000000000000000000000000000..add327842cb7687e00e074a25972f4c834d4864c --- /dev/null +++ b/src/inport/LoadingTemplate.java @@ -0,0 +1,97 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author topazh_ag + */ +public class LoadingTemplate extends OperationTemplate { + + private TransportShip loader; + private Storage storage; + private List resources; + private double intensity; + + + /** + * Get the value of resources + * + * @return the value of resources + */ + public List getResources() { + return resources; + } + + /** + * Set the value of resources + * + * @param resources new value of resources + */ + public void setResources(List resources) { + this.resources = resources; + } + + public TransportShip getLoader() { + return loader; + } + + public void setLoader(TransportShip loader) { + this.loader = loader; + } + + public double getIntensity() { + return intensity; + } + + public void setIntensity(double intensity) { + this.intensity = intensity; + } + + public Storage getStorage() { + return storage; + } + + public void setStorage(Storage storage) { + this.storage = storage; + } + + public LoadingTemplate(TransportShip loader, Berth berth, Storage storage, double intensity, int id) { + super(id, berth); + this.loader = loader; + this.storage = storage; + this.resources = new ArrayList<>(); + this.intensity = intensity; + } + + public LoadingTemplate() { + this.resources = new ArrayList<>(); + } + + @Override + public String toString() { + String res = ""; + boolean first = true; + for(LoadingEquipment eq : resources) + { + if (!first) + res += "," + eq.getId(); + else + res += eq.getId(); + first = false; + } + int source = loader.getId(); + if (intensity>0) + source = storage.getId(); + int target = loader.getId(); + if (intensity<=0) + target = storage.getId(); + int cargos = storage.getCargo().getId(); + return getId() + ";" + "loa;" + twtoString() + ";" + source + ";" + cargos + ";" + target + ";" + getStartLocation().getId() + ";[" + res +"];"+Math.abs(intensity); + } +} diff --git a/src/inport/Main.java b/src/inport/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..2120da521c3db83f3ff671bd57bba9e1c8a603db --- /dev/null +++ b/src/inport/Main.java @@ -0,0 +1,21 @@ +package inport; + +import java.io.IOException; + +public class Main { + + public static void main(String[] args) { + if (args.length < 2) { + System.out.println("To few arguments."); + return; + } + TaskCase task = new TaskCase(); + try { + task.deserialize(args[0]); +// task.simpleMiniZincConversion(args[1]); + ConversionUtil.portToMiniZinc(task, args[1]); + } catch (IOException ex) { + System.out.println(ex.getMessage()); + } + } +} diff --git a/src/inport/MooringTemplate.java b/src/inport/MooringTemplate.java new file mode 100644 index 0000000000000000000000000000000000000000..a496339c7645ec92ff2c7ab0d00d62c4ec4b47ac --- /dev/null +++ b/src/inport/MooringTemplate.java @@ -0,0 +1,80 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class MooringTemplate extends TowUsingTemplate { + + private TransportShip moorer; + private boolean direct; + + /** + * Get the value of direction + * + * @return the value of direction + */ + public boolean isDirect() { + return direct; + } + + /** + * Set the value of direction + * + * @param direction new value of direction + */ + public void setDirect(boolean direct) { + this.direct = direct; + } + + /** + * Get the value of moorer + * + * @return the value of moorer + */ + public MovingObject getMoorer() { + return moorer; + } + + /** + * Set the value of moorer + * + * @param mover new value of moorer + */ + public void setMoorer(TransportShip moorer) { + this.moorer = moorer; + } + + public MooringTemplate(TransportShip moorer, Berth berth, double duration, boolean direct, int id) { + super(duration, id, berth); + this.moorer = moorer; + this.direct = direct; + } + + public MooringTemplate() { + super(); + } + + @Override + public String toString() { + String res = ""; + boolean first = true; + for(Tow eq : getResources()) + { + if (!first) + res += "," + eq.getId(); + else + res += eq.getId(); + first = false; + } + String code = "mrn"; + if (!direct) + code = "unm"; + return getId() + ";" + code + ";" + twtoString() + ";" + moorer.getId() + ";" + getStartLocation().getId() + ";[" + res +"];"+getDuration(); + } + +} diff --git a/src/inport/MovingObject.java b/src/inport/MovingObject.java new file mode 100644 index 0000000000000000000000000000000000000000..a0adedc9ce2b837e64de9816628c05c8d5271b34 --- /dev/null +++ b/src/inport/MovingObject.java @@ -0,0 +1,66 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class MovingObject { + + private int id; + private String name; + + /** + * Get the value of name + * + * @return the value of name + */ + public String getName() { + return name; + } + + /** + * Set the value of name + * + * @param name new value of name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Get the value of id + * + * @return the value of id + */ + public int getId() { + return id; + } + + /** + * Set the value of id + * + * @param id new value of id + */ + public void setId(int id) { + this.id = id; + } + + public MovingObject(int id, String name) { + this.id = id; + this.name = name; + } + + public MovingObject() { + } + + public MovingObject(String s) { + String[] tokens = s.split(";"); + id = Integer.parseInt(tokens[0].trim()); + name = tokens[1].trim(); + } + +} diff --git a/src/inport/MovingObjectState.java b/src/inport/MovingObjectState.java new file mode 100644 index 0000000000000000000000000000000000000000..ebaeb3b0c33aa81fd5874de801b928b491c128ce --- /dev/null +++ b/src/inport/MovingObjectState.java @@ -0,0 +1,71 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class MovingObjectState { + + private MovingObject vessel; + private Berth location; + + /** + * Get the value of location + * + * @return the value of location + */ + public Berth getLocation() { + return location; + } + + /** + * Set the value of location + * + * @param location new value of location + */ + public void setLocation(Berth location) { + this.location = location; + } + + /** + * Get the value of vessel + * + * @return the value of vessel + */ + public MovingObject getVessel() { + return vessel; + } + + /** + * Set the value of vessel + * + * @param vessel new value of vessel + */ + public void setVessel(MovingObject vessel) { + this.vessel = vessel; + } + + /** + * + * @param vessel + * @param location + */ + public MovingObjectState(MovingObject vessel, Berth location) { + this.vessel = vessel; + this.location = location; + } + + public MovingObjectState() { + } + + @Override + public String toString() { + return getVessel().getId() + ";" + getLocation().getId(); + } + + +} diff --git a/src/inport/MovingTemplate.java b/src/inport/MovingTemplate.java new file mode 100644 index 0000000000000000000000000000000000000000..80063e601c72f14f52ee6b6ffc4a83d67e01c70f --- /dev/null +++ b/src/inport/MovingTemplate.java @@ -0,0 +1,79 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class MovingTemplate extends TowUsingTemplate { + + private MovingObject mover; + private Berth destination; + + + /** + * Get the value of destination + * + * @return the value of destination + */ + public Berth getDestination() { + return destination; + } + + /** + * Set the value of destination + * + * @param destination new value of destination + */ + public void setDestination(Berth destination) { + this.destination = destination; + } + + /** + * Get the value of mover + * + * @return the value of mover + */ + public MovingObject getMover() { + return mover; + } + + /** + * Set the value of mover + * + * @param mover new value of mover + */ + public void setMover(MovingObject mover) { + this.mover = mover; + } + + public MovingTemplate(MovingObject mover, Berth source, Berth destination, double duration, int id) { + super(duration, id, source); + this.mover = mover; + this.destination = destination; + } + + public MovingTemplate() { + super(); + } + + @Override + public String toString() { + String res = ""; + boolean first = true; + for(Tow eq : getResources()) + { + if (!first) + res += "," + eq.getId(); + else + res += eq.getId(); + first = false; + } + return getId() + ";" + "mov;" + twtoString() + ";" + mover.getId() + ";" + getStartLocation().getId() + ";" + destination.getId() + ";[" + res +"];"+getDuration(); + } + + +} diff --git a/src/inport/Operation.java b/src/inport/Operation.java new file mode 100644 index 0000000000000000000000000000000000000000..e97d0b857c8f1c19605007d017253c35e6d289bb --- /dev/null +++ b/src/inport/Operation.java @@ -0,0 +1,82 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class Operation { + + private OperationTemplate template; + private double start; + private double duration; + + /** + * Get the value of duration + * + * @return the value of duration + */ + public double getDuration() { + return duration; + } + + /** + * Set the value of duration + * + * @param duration new value of duration + */ + public void setDuration(double duration) { + this.duration = duration; + } + + + /** + * Get the value of start + * + * @return the value of start + */ + public double getStart() { + return start; + } + + /** + * Set the value of start + * + * @param start new value of start + */ + public void setStart(double start) { + this.start = start; + } + + + /** + * Get the value of template + * + * @return the value of template + */ + public OperationTemplate getTemplate() { + return template; + } + + /** + * Set the value of template + * + * @param template new value of template + */ + public void setTemplate(OperationTemplate template) { + this.template = template; + } + + public Operation() { + } + + @Override + public String toString() { + return template.getId() + "; R; " + start + "; " + duration; + } + + +} diff --git a/src/inport/OperationTemplate.java b/src/inport/OperationTemplate.java new file mode 100644 index 0000000000000000000000000000000000000000..a2d6003c3be54e3dfdcae18f269d7e1ad1de05ed --- /dev/null +++ b/src/inport/OperationTemplate.java @@ -0,0 +1,91 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +import java.util.HashMap; +import java.util.Map; + +/** + * + * @author topazh_ag + */ +public abstract class OperationTemplate { + + private int id; + private Berth startLocation; + Map timeWindows; + + /** + * Get the value of id + * + * @return the value of id + */ + public int getId() { + return id; + } + + /** + * Set the value of id + * + * @param id new value of id + */ + public void setId(int id) { + this.id = id; + } + + public Berth getStartLocation() { + return startLocation; + } + + public void setStartLocation(Berth startLocation) { + this.startLocation = startLocation; + } + + public Map getTimeWindows() { + return timeWindows; + } + + public void setBanWindows(Map timeWindows) { + this.timeWindows = timeWindows; + } + + protected String twtoString() { + String res = ""; + boolean first = true; + for(Double s : timeWindows.keySet()) + { + if (!first) + res += "," + s + ":" + timeWindows.get(s); + else + res += s + ":" + timeWindows.get(s); + first = false; + } + return "[" + res +"]"; + } + + public OperationTemplate(int id, Berth startLocation) { + this.id = id; + this.startLocation = startLocation; + this.timeWindows = new HashMap<>(); + } + + public OperationTemplate() { + this.timeWindows = new HashMap<>(); + } + + public void setTimeWindow(String s) { + this.timeWindows = new HashMap<>(); + String[] rs = s.replace("[", "").replace("]", "").split(","); + for (String crs : rs) + if (crs.length()>0) + { + String[] kv = crs.split(":"); + Double key1 = Double.parseDouble(kv[0]); + Double value1 = Double.parseDouble(kv[1]); + timeWindows.put(key1, value1); + } + } + +} diff --git a/src/inport/SerializationHelper.java b/src/inport/SerializationHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..889202f2ebe383e41d39492ad542f7c36584b054 --- /dev/null +++ b/src/inport/SerializationHelper.java @@ -0,0 +1,79 @@ +package inport; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.stream.util.StreamReaderDelegate; +import javax.xml.transform.stream.StreamResult; + +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/** + * + * @author topazh_ag + */ +public class SerializationHelper { + + public String serialize(Object object) throws Exception{ + StringWriter resultWriter = new StringWriter(); + StreamResult result = new StreamResult( resultWriter ); + XMLStreamWriter xmlStreamWriter = + XMLOutputFactory.newInstance().createXMLStreamWriter(result); + + JAXBContext context = JAXBContext.newInstance(object.getClass()); + Marshaller marshaller = context.createMarshaller(); + marshaller.marshal(new JAXBElement(new QName(object.getClass().getSimpleName()), object.getClass(), object), xmlStreamWriter); + + String res = resultWriter.toString(); + return res; + } + + public Object deserialize(String str, Class klass) throws Exception{ + + InputStream is = new ByteArrayInputStream(str.getBytes("UTF-8")); + XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(is); + reader = new CamelCaseTransfomingReaderDelegate(reader, klass); + + JAXBContext context = JAXBContext.newInstance(klass); + Unmarshaller unmarshaller = context.createUnmarshaller(); + + JAXBElement elem = unmarshaller.unmarshal(reader, klass); + Object object = elem.getValue(); + + return object; + } + + //adapts to Java property naming style + private static class CamelCaseTransfomingReaderDelegate extends StreamReaderDelegate { + + Class klass = null; + + public CamelCaseTransfomingReaderDelegate(XMLStreamReader xsr, Class klass) { + super(xsr); + this.klass = klass; + } + + @Override + public String getLocalName() { + String nodeName = super.getLocalName(); + if (!nodeName.equals(klass.getSimpleName())) + { + nodeName = nodeName.substring(0, 1).toLowerCase() + + nodeName.substring(1, nodeName.length()); + } + return nodeName.intern(); //NOTE: intern very important!.. + } + } +} \ No newline at end of file diff --git a/src/inport/Storage.java b/src/inport/Storage.java new file mode 100644 index 0000000000000000000000000000000000000000..0ceed25c3ae18dbd3d71838d785f15e421bab090 --- /dev/null +++ b/src/inport/Storage.java @@ -0,0 +1,115 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +import java.util.Map; + +/** + * + * @author topazh_ag + */ +public class Storage { + private int id; + private String name; + private double volume; + private Cargo cargo; + + /** + * Get the value of cargo + * + * @return the value of cargo + */ + public Cargo getCargo() { + return cargo; + } + + /** + * Set the value of cargo + * + * @param cargo new value of cargo + */ + public void setCargo(Cargo cargo) { + this.cargo = cargo; + } + + + /** + * Get the value of volume + * + * @return the value of volume + */ + public double getVolume() { + return volume; + } + + /** + * Set the value of volume + * + * @param volume new value of volume + */ + public void setVolume(double volume) { + this.volume = volume; + } + + /** + * Get the value of name + * + * @return the value of name + */ + public String getName() { + return name; + } + + /** + * Set the value of name + * + * @param name new value of name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Get the value of id + * + * @return the value of id + */ + public int getId() { + return id; + } + + /** + * Set the value of id + * + * @param id new value of id + */ + public void setId(int id) { + this.id = id; + } + + public Storage(int id, String name, double volume, Cargo cargo) { + this.id = id; + this.name = name; + this.volume = volume; + this.cargo = cargo; + } + + public Storage() { + } + + @Override + public String toString() { + return id + ";" + name + ";" + cargo.getId() + ";" +volume; + } + + public Storage(String s, Map cargoes) { + String[] tokens = s.split(";"); + id = Integer.parseInt(tokens[0].trim()); + name = tokens[1].trim(); + volume = Double.parseDouble(tokens[3].trim()); + int key = Integer.parseInt(tokens[2].trim()); + cargo = cargoes.get(key); + } +} diff --git a/src/inport/StorageState.java b/src/inport/StorageState.java new file mode 100644 index 0000000000000000000000000000000000000000..d2f9650d283b30e520763a5313123d58b9afa6ec --- /dev/null +++ b/src/inport/StorageState.java @@ -0,0 +1,97 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +import java.util.Map; + +/** + * + * @author topazh_ag + */ +public class StorageState { + + private Object storage; + private Cargo cargo; + private double cargoState; + + /** + * Get the value of storage + * + * @return the value of storage + */ + public Object getStorage() { + return storage; + } + + /** + * Set the value of storage + * + * @param storage new value of storage + */ + public void setStorage(Object storage) { + this.storage = storage; + } + + public Cargo getCargo() { + return cargo; + } + + public void setCargo(Cargo cargo) { + this.cargo = cargo; + } + + /** + * Get the value of cargoState + * + * @return the value of cargoState + */ + public double getCargoState() { + return cargoState; + } + + /** + * Set the value of cargoState + * + * @param cargoState new value of cargoState + */ + public void setCargoState(double cargoState) { + this.cargoState = cargoState; + } + + /** + * + * @param storage + */ + public StorageState(Object storage, Cargo cargo, double cargoState) { + this.storage = storage; + this.cargo = cargo; + this.cargoState = cargoState; + } + + public StorageState() { + } + + @Override + public String toString() { + if (storage instanceof Storage) + return cargo.getId() + ";" + ((Storage)storage).getId() + ";" + cargoState; + if (storage instanceof TransportShip) + return cargo.getId() + ";" + ((TransportShip)storage).getId() + ";" + cargoState; + return ""; + } + + public StorageState(String s, Map mp, Map vp, Map cp) { + String[] tokens = s.split(";"); + int key = Integer.parseInt(tokens[0].trim()); + cargo = cp.get(key); + key = Integer.parseInt(tokens[1].trim()); + if (mp.containsKey(key)) + storage = mp.get(key); + if (vp.containsKey(key)) + storage = vp.get(key); + cargoState = Double.parseDouble(tokens[2].trim()); + } + +} diff --git a/src/inport/TaskCase.java b/src/inport/TaskCase.java new file mode 100644 index 0000000000000000000000000000000000000000..3c5f288cd0c9289ce8ce1f536e9d359be12f2e89 --- /dev/null +++ b/src/inport/TaskCase.java @@ -0,0 +1,1820 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +import javafx.util.Pair; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author topazh_ag + */ +public class TaskCase { + + // Статическая структура порта + private List cargoes; + private List berths; + private List storages; + private List bunkers; + private List tows; + private List equipments; + + // Обслуживаемые суда + private List ships; + + // Шаблоны операций + private List templates; + + // Внешние грузопотоки + private List cargoFlows; + + // Начальное состояние + private List vesselInitialState; + private List storageInitialState; + + // Конечное состояние + private List vesselEndState; + private List storageEndState; + + // Горизонт планирования + private double planningInterval; + + // Тип критерия оптимизации + private int criterionType; + + // План - критерий + private double solution_result; + + // План - решение + private List solution; + + /** + * Get the value of solution + * + * @return the value of solution + */ + public List getSolution() { + return solution; + } + + /** + * Set the value of solution + * + * @param solution new value of solution + */ + public void setSolution(List solution) { + this.solution = solution; + } + + /** + * Get the value of planningInterval + * + * @return the value of planningInterval + */ + public double getPlanningInterval() { + return planningInterval; + } + + /** + * Set the value of planningInterval + * + * @param planningInterval new value of planningInterval + */ + public void setPlanningInterval(double planningInterval) { + this.planningInterval = planningInterval; + } + + public int getCriterionType() { + return criterionType; + } + + public void setCriterionType(int criterionType) { + this.criterionType = criterionType; + } + + public double getSolution_result() { + return solution_result; + } + + public void setSolution_result(double solution_result) { + this.solution_result = solution_result; + } + + /** + * Get the value of cargoFlows + * + * @return the value of cargoFlows + */ + public List getCargoFlows() { + return cargoFlows; + } + + /** + * Set the value of cargoFlows + * + * @param cargoFlows new value of cargoFlows + */ + public void setCargoFlows(List cargoFlows) { + this.cargoFlows = cargoFlows; + } + + /** + * Get the value of vesselEndState + * + * @return the value of vesselEndState + */ + public List getVesselEndState() { + return vesselEndState; + } + + /** + * Set the value of vesselEndState + * + * @param vesselEndState new value of vesselEndState + */ + public void setVesselEndState(List vesselEndState) { + this.vesselEndState = vesselEndState; + } + + public List getStorageEndState() { + return storageEndState; + } + + public void setStorageEndState(List storageEndState) { + this.storageEndState = storageEndState; + } + + + /** + * Get the value of storageInitialState + * + * @return the value of storageInitialState + */ + public List getStorageInitialState() { + return storageInitialState; + } + + /** + * Set the value of storageInitialState + * + * @param storageInitialState new value of storageInitialState + */ + public void setStorageInitialState(List storageInitialState) { + this.storageInitialState = storageInitialState; + } + + + /** + * Get the value of vesselInitialState + * + * @return the value of vesselInitialState + */ + public List getVesselInitialState() { + return vesselInitialState; + } + + /** + * Set the value of vesselInitialState + * + * @param vesselInitialState new value of vesselInitialState + */ + public void setVesselInitialState(List vesselInitialState) { + this.vesselInitialState = vesselInitialState; + } + + + + /** + * Get the value of templates + * + * @return the value of templates + */ + public List getTemplates() { + return templates; + } + + /** + * Set the value of templates + * + * @param templates new value of templates + */ + public void setTemplates(List templates) { + this.templates = templates; + } + + + + /** + * Get the value of ships + * + * @return the value of ships + */ + public List getShips() { + return ships; + } + + /** + * Set the value of ships + * + * @param ships new value of ships + */ + public void setShips(List ships) { + this.ships = ships; + } + + + + /** + * Get the value of equipments + * + * @return the value of equipments + */ + public List getEquipments() { + return equipments; + } + + /** + * Set the value of equipments + * + * @param equipments new value of equipments + */ + public void setEquipments(List equipments) { + this.equipments = equipments; + } + + + + /** + * Get the value of tows + * + * @return the value of tows + */ + public List getTows() { + return tows; + } + + /** + * Set the value of tows + * + * @param tows new value of tows + */ + public void setTows(List tows) { + this.tows = tows; + } + + + /** + * Get the value of bunkers + * + * @return the value of bunkers + */ + public List getBunkers() { + return bunkers; + } + + /** + * Set the value of bunkers + * + * @param bunkers new value of bunkers + */ + public void setBunkers(List bunkers) { + this.bunkers = bunkers; + } + + /** + * Get the value of storages + * + * @return the value of storages + */ + public List getStorages() { + return storages; + } + + /** + * Set the value of storages + * + * @param storages new value of storages + */ + public void setStorages(List storages) { + this.storages = storages; + } + + /** + * Get the value of cargoes + * + * @return the value of cargoes + */ + public List getCargoes() { + return cargoes; + } + + /** + * Set the value of cargoes + * + * @param cargoes new value of cargoes + */ + public void setCargoes(List cargoes) { + this.cargoes = cargoes; + } + + /** + * Get the value of berths + * + * @return the value of berths + */ + public List getBerths() { + return berths; + } + + /** + * Set the value of berths + * + * @param berths new value of berths + */ + public void setBerths(List berths) { + this.berths = berths; + } + + public TaskCase() { + cargoes = new ArrayList<>(); + berths = new ArrayList<>(); + storages = new ArrayList<>(); + bunkers = new ArrayList<>(); + tows = new ArrayList<>(); + equipments = new ArrayList<>(); + ships = new ArrayList<>(); + + templates = new ArrayList<>(); + + cargoFlows = new ArrayList<>(); + + vesselInitialState = new ArrayList<>(); + storageInitialState = new ArrayList<>() ; + + vesselEndState = new ArrayList<>(); + storageEndState = new ArrayList<>(); + + solution = new ArrayList<>(); + + } + + private MovingObjectState fromString(String s, Map m_berth, Map m_vessel) + { + String[] tkns1 = s.split(";"); + MovingObjectState st = new MovingObjectState(); + int key = Integer.parseInt(tkns1[0].trim()); + MovingObject vs = m_vessel.get(key); + st.setVessel(vs); + key = Integer.parseInt(tkns1[1].trim()); + st.setLocation(m_berth.get(key)); + return st; + } + + public void deserialize(String fileName) throws IOException + { + cargoes.clear(); berths.clear(); storages.clear(); bunkers.clear(); tows.clear(); equipments.clear(); ships.clear(); templates.clear(); + cargoFlows.clear(); vesselInitialState.clear(); storageInitialState.clear(); vesselEndState.clear(); storageEndState.clear(); + solution.clear(); + + String[] tags = {"Cargoes", "Berths", "Storages", "Bunkers", "Tows", "Loading Equipments", "Transport Ships", "Templates", "Time Windows", "Cargo Flows", "Initial Vessel State", "Initial Storage State", "Final Vessel State", "Final Storage State", "Task Properties", "Solution"}; + // Open the file + FileInputStream fstream; + try + { + fstream = new FileInputStream(fileName); + BufferedReader br = new BufferedReader(new InputStreamReader(fstream)); + String strLine; + int index = 0; + Map m_cargo = new HashMap<>(); + Map m_berth = new HashMap<>(); + Map m_storage = new HashMap<>(); + Map m_vessel = new HashMap<>(); + Map m_equiopment = new HashMap<>(); + Map m_template = new HashMap<>(); + //Read File Line By Line + int numInside = 0; + while ((strLine = br.readLine()) != null) + { + numInside ++; + boolean serviceString = false; + for (int i = 0; i0) + { + key = Integer.parseInt(crs.trim()); + mt.getResources().add((Tow)m_vessel.get(key)); + } + mt.setDuration(Double.parseDouble(tokens[7].trim())); + templates.add(mt); + m_template.put(mt.getId(), mt); + } + if (tokens[1].trim().equals("mrn") || tokens[1].trim().equals("unm")) + { + MooringTemplate mt = new MooringTemplate(); + mt.setId(Integer.parseInt(tokens[0].trim())); + mt.setDirect(true); + if (tokens[1].trim().equals("unm")) + mt.setDirect(false); + mt.setTimeWindow(tokens[2].trim()); + int key = Integer.parseInt(tokens[3].trim()); + mt.setMoorer((TransportShip)m_vessel.get(key)); + key = Integer.parseInt(tokens[4].trim()); + mt.setStartLocation(m_berth.get(key)); + String[] rs = tokens[5].trim().replace("[", "").replace("]", "").split(","); + for (String crs : rs) + if (crs.length()>0) + { + key = Integer.parseInt(crs.trim()); + mt.getResources().add((Tow)m_vessel.get(key)); + } + mt.setDuration(Double.parseDouble(tokens[6].trim())); + templates.add(mt); + m_template.put(mt.getId(), mt); + } + if (tokens[1].trim().equals("loa")) + { + LoadingTemplate mt = new LoadingTemplate(); + mt.setId(Integer.parseInt(tokens[0].trim())); + mt.setTimeWindow(tokens[2].trim()); + int direct = 1; + // Источник. Пока пара - это только хранилище-судно. С бункеровкой будем разбираться потом + int key = Integer.parseInt(tokens[3].trim()); + if (m_vessel.containsKey(key)) + { + mt.setLoader((TransportShip)m_vessel.get(key)); + direct = -1; + } + if (m_storage.containsKey(key)) + { + mt.setStorage((Storage)m_storage.get(key)); + direct = 1; + } + // Груз. Пока не нужен + // Приемник. Пока пара - это только хранилище-судно. С бункеровкой будем разбираться потом + key = Integer.parseInt(tokens[5].trim()); + if (m_vessel.containsKey(key)) + { + mt.setLoader((TransportShip)m_vessel.get(key)); + direct = 1; + } + if (m_storage.containsKey(key)) + { + mt.setStorage((Storage)m_storage.get(key)); + direct = - 1; + } + key = Integer.parseInt(tokens[6].trim()); + mt.setStartLocation(m_berth.get(key)); + String[] rs = tokens[7].trim().replace("[", "").replace("]", "").split(","); + for (String crs : rs) + if (crs.length()>0) + { + key = Integer.parseInt(crs.trim()); + mt.getResources().add(m_equiopment.get(key)); + } + mt.setIntensity(direct*Double.parseDouble(tokens[8].trim())); + templates.add(mt); + m_template.put(mt.getId(), mt); + } + break; + case 9: + break; + case 10: cargoFlows.add(new CargoFlow(strLine, m_storage, m_cargo)); + break; + case 11: vesselInitialState.add(fromString(strLine, m_berth, m_vessel)); + break; + case 12: storageInitialState.add(new StorageState(strLine, m_storage, m_vessel, m_cargo)); + break; + case 13: vesselEndState.add(fromString(strLine, m_berth, m_vessel)); + break; + case 14: storageEndState.add(new StorageState(strLine, m_storage, m_vessel, m_cargo)); + break; + case 15: + { + String[] rs = strLine.split(";"); + planningInterval = Double.parseDouble(rs[0].trim()); + criterionType = Integer.parseInt(rs[1].trim()); + } + break; + case 16: // Тут чтение операций если надо. Потом подумаем + break; + default: + break; + } + } + //Close the input stream + br.close(); + } catch (FileNotFoundException ex) { + Logger.getLogger(TaskCase.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public void serialize(String fileName) + { + try(FileWriter writer = new FileWriter(fileName, false)) + { + // запись всего + writer.write("Cargoes"+"\n"); + for (Cargo c : cargoes) + writer.write(c.toString()+"\n"); + writer.write("Berths"+"\n"); + for (Berth c : berths) + writer.write(c.toString()+"\n"); + writer.write("Storages"+"\n"); + for (Storage c : storages) + writer.write(c.toString()+"\n"); + writer.write("Bunkers"+"\n"); + for (Bunker c : bunkers) + writer.write(c.toString()+"\n"); + writer.write("Tows"+"\n"); + for (Tow c : tows) + writer.write(c.toString()+"\n"); + writer.write("Loading Equipments"+"\n"); + for (LoadingEquipment c : equipments) + writer.write(c.toString()+"\n"); + writer.write("Transport Ships"+"\n"); + for (TransportShip c : ships) + writer.write(c.toString()+"\n"); + writer.write("\n"); + writer.write("Templates"+"\n"); + for (OperationTemplate c : templates) + writer.write(c.toString()+"\n"); + writer.write("\n"); + writer.write("Cargo Flows"+"\n"); + for (CargoFlow c : cargoFlows) + writer.write(c.toString()+"\n"); + writer.write("Initial Vessel State"+"\n"); + for (MovingObjectState c : vesselInitialState) + writer.write(c.toString()+"\n"); + writer.write("Initial Storage State"+"\n"); + for (StorageState c : storageInitialState) + writer.write(c.toString()+"\n"); + writer.write("Final Vessel State"+"\n"); + for (MovingObjectState c : vesselEndState) + writer.write(c.toString()+"\n"); + writer.write("Final Storage State"+"\n"); + for (StorageState c : storageEndState) + writer.write(c.toString()+"\n"); + writer.write("\n"); + writer.write("Task Properties"+"\n"); + writer.write(planningInterval+";"+criterionType+"\n"); + writer.write("\n"); + writer.write("Solution"+"\n"); + writer.write(solution_result+"\n"); + for (Operation c : solution) + writer.write(c.toString()+"\n"); + writer.flush(); + } + catch(IOException ex){ + + System.out.println(ex.getMessage()); + } + } + + public void formSolutionFromPB(int res[]) + { + int nTimes = (int) (planningInterval + 1.0 - 1e-7); + int rLength = res.length; + solution_result = 0.0; + for (int k=1; k<=nTimes; k++) + if (res[rLength-k]>0) + { + solution_result = nTimes - k + 1; + break; + } + int cIndex = -1; + + for (OperationTemplate template : templates) + { + boolean inBlock = false; + int duration = 0; + Operation operation = null; + for (int i=0; i0) + { + if (inBlock) + duration++; + else + { + // Это начало блока + operation = new Operation(); + operation.setTemplate(template); + operation.setStart(i+1); + inBlock = true; + } + } else + { + if (inBlock) + { + // Это окончание блока + operation.setDuration(duration+1.0); + duration = 0; + solution.add(operation); + inBlock = false; + } + + } + } + if (inBlock) + { + // Это окончание блока + operation.setDuration(duration+1.0); + solution.add(operation); + } + } + } + + private boolean isCompatible(OperationTemplate t1, OperationTemplate t2) + { + MovingObject doer1 = getDoer(t1); + Berth place1 = t1.getStartLocation(); + List resources1 = getResources(t1); + MovingObject doer2 = getDoer(t2); + Berth place2 = t2.getStartLocation(); + List resources2 = getResources(t2); + // Пересекаемость ресурсов + for (Object res2 : resources2) + if (resources1.contains(res2)) + return false; + // Выполнитель = ресурс + if (resources1.contains(doer2)) + return false; + // Ресурс = выполнитель + if (resources2.contains(doer1)) + return false; + + // Выполнитель = выполнитель + if (doer1.equals(doer2)) + { + // Это не погрузка + if (!(t1 instanceof LoadingTemplate) || (!(t2 instanceof LoadingTemplate))) + return false; + // Разные причалы + if (!place1.equals(place2)) + return false; + Storage s1 = ((LoadingTemplate)t1).getStorage(); + Storage s2 = ((LoadingTemplate)t2).getStorage(); + // В одно хранилище + if (s1.equals(s2)) + return false; + } + else + // На одном причале и это не перемещения + if (place1.equals(place2) && (!(t1 instanceof MovingTemplate)) && (!(t2 instanceof MovingTemplate))) + return false; + + return true; + } + + MovingObject getDoer(OperationTemplate t) + { + if (t instanceof LoadingTemplate) + return ((LoadingTemplate)t).getLoader(); + if (t instanceof MooringTemplate) + return ((MooringTemplate)t).getMoorer(); + if (t instanceof MovingTemplate) + return ((MovingTemplate)t).getMover(); + return null; + } + + List getResources(OperationTemplate t) + { + List res = new ArrayList<>(); + if (t instanceof LoadingTemplate) + res.addAll(((LoadingTemplate)t).getResources()); + if (t instanceof MooringTemplate) + res.addAll(((MooringTemplate)t).getResources()); + if (t instanceof MovingTemplate) + res.addAll(((MovingTemplate)t).getResources()); + return res; + } + + private String xij(int i, int j, int nJ, boolean plus) + { + int number = i*nJ + j + 1; + String prefix = ""; + if (!plus) + prefix ="~"; + return prefix+"x"+number; + } + + private String wrbj(int r, int b, int j, int nB, int nJ, int nIni, boolean isMooring, boolean moored, boolean plus) + { + int number = nIni + r*nJ*nB + b*nJ + j + 1; + if (isMooring) + { + if (moored) + number = nIni + r*nJ*nB*2 + b*nJ*2 + nJ + j + 1; + else + number = nIni + r*nJ*nB*2 + b*nJ*2 + j + 1; + } + String prefix = ""; + if (!plus) + prefix ="~"; + return prefix+"x"+number; + } + + private String sum1(List iks, int j, int nJ, int weight) + { + String res = ""; + for (Integer ik : iks) + res += " +" + weight + " "+xij(ik, j, nJ, true); + return res; + } + + private String fj(int j, int nBefore, boolean plus) + { + int number = nBefore + j + 1; + String prefix = ""; + if (!plus) + prefix ="~"; + return prefix+"x"+number; + } + + + + public int pb_formalize(String fileName/*, int indent*/) throws IOException + { + + + FileWriter writer = new FileWriter("temp", false); + int nCons = 0; + + List vss = new ArrayList(); + vss.addAll(ships); + vss.addAll(bunkers); + vss.addAll(tows); + vss.addAll(equipments); + + // Выяснение вопроса с наличием швартовки + boolean isMooring = false; + for (OperationTemplate tp : templates) + if (tp instanceof MooringTemplate) + { + isMooring = true; + break; + } + + + + + int nTimes = (int) (planningInterval + 1.0 - 1e-7); + int nOperations = templates.size(); + int nVars = nTimes*nOperations; + int nBerths = berths.size(); + int nVessels = vss.size(); + int mult =1; + if (isMooring) + mult = 2; + int nSuppVars = nVessels*nBerths*mult*nTimes; + int nBefore = nVars + nSuppVars; + int nAfter = nTimes; + + // String s1 = wrbj(0, 1, 17, 6, 18, 756, true, true, true); + // String s2 = wrbj(0, 2, 0, 6, 18, 756, true, false, true); + // String s23 = s1+s2; + + // Критерий оптимизации старый + /* + nAfter = 0; + String crit = ""; + int degree = 1; + for (int j=nTimes - indent; j starts = tp.timeWindows.keySet(); + for (Double start : starts) + { + // Определяем стартовый индекс + int jstart = (int)(start.doubleValue()); + Double duration = tp.timeWindows.get(start); + int jend = (int)(start.doubleValue()+duration.doubleValue()); + for (int j=jstart; j<=jend; j++) + { + writer.write(" +1 "+xij(i,j,nTimes,true)+" = 0 ;\n"); + nCons++; + } + } + } + + //!!!! Неразделимость ресурсов для операций. + writer.write("* Resource Unsharedness \n"); + // Новая байда + for (int i1 = 0; i1 excluders = new ArrayList(); + for (int i2 = i1+1; i20) + { + for (int j=0; j= 1 ;\n"); + nCons++; + } + } + } + + /* + // Старая байда + + // Буксиры + writer.write("* For Tows \n"); + for (Tow tow : tows) + { + List iks = new ArrayList(); + for (OperationTemplate tpl : templates) + { + int ik = templates.indexOf(tpl); + if (tpl instanceof MovingTemplate) + { + MovingTemplate mt = (MovingTemplate)tpl; + if (mt.getMover().equals(tow)) + iks.add(ik); + if (mt.getResources().contains(tow)) + iks.add(ik); + } + if (tpl instanceof MooringTemplate) + { + MooringTemplate mt = (MooringTemplate)tpl; + if (mt.getResources().contains(tow)) + iks.add(ik); + } + } + + if (!iks.isEmpty()) + for (int j=0; j iks = new ArrayList(); + for (OperationTemplate tpl : templates) + { + int ik = templates.indexOf(tpl); + if (tpl instanceof LoadingTemplate) + { + LoadingTemplate mt = (LoadingTemplate)tpl; + if (mt.getResources().contains(le)) + iks.add(ik); + } + if (tpl instanceof BunkeringTemplate) + { + BunkeringTemplate bt = (BunkeringTemplate)tpl; + if (bt.getResources().contains(le)) + iks.add(ik); + } + } + if (!iks.isEmpty()) + for (int j=0; j iks = new ArrayList(); + for (OperationTemplate tpl : templates) + { + int ik = templates.indexOf(tpl); + if (tpl instanceof BunkeringTemplate) + { + BunkeringTemplate bt = (BunkeringTemplate)tpl; + if (bt.getBunker().equals(bk)) + iks.add(ik); + } + } + if (!iks.isEmpty()) + for (int j=0; j mrks = new ArrayList(); + List> opbs = new ArrayList>(); + for (TransportShip ship : ships) + opbs.add(new ArrayList()); + boolean filled = false; + for (OperationTemplate tpl : templates) + { + int ik = templates.indexOf(tpl); + + if (tpl instanceof MooringTemplate) + { + MooringTemplate mt = (MooringTemplate)tpl; + if (mt.getBerth().equals(bt)) + { + mrks.add(ik); + int ind = ships.indexOf(mt.getMoorer()); + if (ind>=0) + { + opbs.get(ind).add(ik); + filled = true; + } + } + } + if (tpl instanceof LoadingTemplate) + { + LoadingTemplate lt = (LoadingTemplate)tpl; + if (lt.getBerth().equals(bt)) + { + int ind = ships.indexOf(lt.getLoader()); + if (ind>=0) + { + opbs.get(ind).add(ik); + filled = true; + } + } + } + if (tpl instanceof BunkeringTemplate) + { + BunkeringTemplate bkt = (BunkeringTemplate)tpl; + if (bkt.getBerth().equals(bt)) + { + int ind = ships.indexOf(bkt.getLoader()); + if (ind>=0) + { + opbs.get(ind).add(ik); + filled = true; + } + } + } + + + } + // На причале одновременно выполняется только одна операция швартовки + if (!mrks.isEmpty()) + for (int j=0; j vsops : opbs) + { + if (!vsops.isEmpty()) + { + nVess ++; + String vsop = " +1 "; + for (Integer i : vsops) + vsop += xij(i,j,nTimes,false) + " "; + clause += vsop; + } + } + writer.write(clause + " >= " + (nVess-1) + " ; \n"); + nCons++; + } + + } + + // Суда + writer.write("* For Vessels \n"); + for (MovingObject vs : vss) + { + List mvks = new ArrayList(); + List loks = new ArrayList(); + List mrks = new ArrayList(); + + for (OperationTemplate tpl : templates) + { + int ik = templates.indexOf(tpl); + + // Перемещения + if (tpl instanceof MovingTemplate) + { + MovingTemplate mt = (MovingTemplate)tpl; + if (mt.getMover().equals(vs)) + mvks.add(ik); + } + // Погрузка + if (tpl instanceof LoadingTemplate) + { + LoadingTemplate lt = (LoadingTemplate)tpl; + if (lt.getLoader().equals(vs)) + loks.add(ik); + } + // Швартовка + if (tpl instanceof MooringTemplate) + { + MooringTemplate rt = (MooringTemplate)tpl; + if (rt.getMoorer().equals(vs)) + mrks.add(ik); + } + // Бункеровка + if (tpl instanceof BunkeringTemplate) + { + BunkeringTemplate bt = (BunkeringTemplate)tpl; + if (bt.getLoader().equals(vs)) + loks.add(ik); + } + } + // Судно только в одном перемещении и при этом не может быть ни под погрузкой, ни под швартовкой + + if (!mvks.isEmpty()) + { + int nLM = loks.size()+mrks.size()+1; + for (int j=0; j0) + { + String res = "+1 " + xij(ik,0,nTimes,false) + " +1 "+xij(ik,0,nTimes,true); + for (int k=0; k= 1 ;\n"); + nCons++; + for (int j=1; j= 0 ;\n"); + nCons++; + } + } + + } + + // Ограничения на объем хранилищ. Проверить!!! + writer.write("* Current Storage Volume Constraints \n"); + for (Storage st : storages) + { + int V = (int)st.getVolume(); + double V0 = 0; + for (StorageState sst : storageInitialState) + if (sst.getStorage().equals(st)) + { + V0 = (int)sst.getCargoState(); + break; + } + CargoFlow ccf = null; + for (CargoFlow cf : cargoFlows) + if (cf.getStorage().equals(st)) + { + ccf = cf; + break; + } + List lts = new ArrayList(); + for (OperationTemplate tpl : templates) + { + if (tpl instanceof LoadingTemplate) + { + LoadingTemplate lt = (LoadingTemplate)tpl; + if (lt.getStorage().equals(st)) + lts.add(lt); + } + } + if (lts.size()>0) + { + for (int j=0; j= " + (int)(-sumV) + " ;\n"; + writer.write(cl1); + nCons++; + String cl2 = clause + " <= " + (int)(V-sumV) + " ;\n"; + writer.write(cl2); + nCons++; + } + } + + } + + // Определение локационных переменных + writer.write("* Location Variables \n"); + for (MovingObject v : vss) + { + // Нахождение начального состояния для судна. Потом читать из незавершенных операций + MovingObjectState iniState = null; + int iniTime = 0; + boolean iniMoored = false; + for (MovingObjectState state : vesselInitialState) + if (state.getVessel().equals(v)) + { + iniState = state; + break; + } + + int r = vss.indexOf(v); + for (Berth berth : berths) + { + int b = berths.indexOf(berth); + // Сперва ограничения на начальное состояние + if (iniState!=null && iniState.getLocation().equals(berth)) + { + // До прибытия + for(int j=0; j rb_plus = new ArrayList(); + List rb_minus = new ArrayList(); + List rm_plus = new ArrayList(); + List rm_minus = new ArrayList(); + for (OperationTemplate tp : templates) + { + if (tp instanceof MovingTemplate) + { + int idx = templates.indexOf(tp); + MovingTemplate mtp = (MovingTemplate)tp; + // Перемещение основного судна + if (mtp.getMover().equals(v)) + { + if (mtp.getDestination().equals(berth)) + rb_plus.add(idx); + if (mtp.getStartLocation().equals(berth)) + rb_minus.add(idx); + } + // Перемещение его помоганцев + for (Tow tow : mtp.getResources()) + if (tow.equals(v)) + { + if (mtp.getDestination().equals(berth)) + rb_plus.add(idx); + if (mtp.getStartLocation().equals(berth)) + rb_minus.add(idx); + } + } + // TODO: отработка швартовки + if (tp instanceof MooringTemplate) + { + int idx = templates.indexOf(tp); + MooringTemplate mtp = (MooringTemplate)tp; + // Перемещение основного судна + if (mtp.getMoorer().equals(v)) + { + if (mtp.getStartLocation().equals(berth) && mtp.isDirect()) // Пришвартовка + { + rm_plus.add(idx); + rb_minus.add(idx); + } + if (mtp.getStartLocation().equals(berth) && (!mtp.isDirect())) // Отшвартовка + { + rm_minus.add(idx); + rb_plus.add(idx); + } + } + } + } + + if (true) //(rb_plus.size()>0 && rb_minus.size()>0) + { + for (int j=1; j0 && rm_minus.size()>0) + { + for (int j=1; j resources_f = new ArrayList(); // Свободные + List resources_m = new ArrayList(); // Пришвартованные + Berth b = tp.getStartLocation(); + boolean isAlways = true; + if (tp instanceof LoadingTemplate) + { + int idx = vss.indexOf(((LoadingTemplate)tp).getLoader()); + if (b.getIsRaid() || (!isMooring)) + resources_f.add(idx); + else + resources_m.add(idx); + for (MovingObject mo : ((LoadingTemplate)tp).getResources()) + resources_f.add(vss.indexOf(mo)); + } + if (tp instanceof MooringTemplate) + { + int idx = vss.indexOf(((MooringTemplate)tp).getMoorer()); + if (((MooringTemplate)tp).isDirect()) + resources_f.add(idx); + else + resources_m.add(idx); + for (Tow tow : ((MooringTemplate)tp).getResources()) + resources_f.add(vss.indexOf(tow)); + isAlways = false; + } + if (tp instanceof MovingTemplate) + { + int idx = vss.indexOf(((MovingTemplate)tp).getMover()); + resources_f.add(idx); + for (Tow tow : ((MovingTemplate)tp).getResources()) + resources_f.add(vss.indexOf(tow)); + isAlways = false; + } + int bi = berths.indexOf(b); + for (int j=0; j0) + clause = "-1 " + xij(i, j, nTimes, true) + " " + xij(i, j-1, nTimes, false) + " +1 " + xij(i, j, nTimes, true) +" " + xij(i, j-1, nTimes, false); + String clause_f = clause; + String clause_m = clause; + if (resources_f.size()>0) + { + for (Integer r : resources_f) + clause_f += " " + wrbj(r, bi, j, nBerths, nTimes, nVars, isMooring, false, true); + if (isAlways || j==0) + writer.write(clause_f + " >= 1 ;\n"); + else + writer.write(clause_f + " >= 0 ;\n"); + nCons++; + } + if (resources_m.size()>0) + { + for (Integer r : resources_m) + clause_m += " " + wrbj(r, bi, j, nBerths, nTimes, nVars, isMooring, true, true); + if (isAlways || j==0) + writer.write(clause_m + " >= 1 ;\n"); + else + writer.write(clause_m + " >= 0 ;\n"); + nCons++; + } + } + } + + // Состояние загрузки судов + writer.write("* Ship Loading States \n"); + // Тут пок огшраничение только на местонахождение транспортных судов + for (TransportShip s : ships) + { + StorageState state1 = null; + StorageState state2 = null; + MovingObjectState eState = null; + for (StorageState state : storageInitialState) + if (state.getStorage().equals(s)) + { + state1 = (StorageState)state; + break; + } + for (StorageState state : storageEndState) + if (state.getStorage().equals(s)) + { + state2 = (StorageState)state; + break; + } + for (MovingObjectState state : vesselEndState) + if (state.getVessel().equals(s)) + { + eState = (MovingObjectState)state; + break; + } + for (Cargo c : cargoes) + { + int start = 0; + int finish = 0; + if (state1!=null && state1.getCargo().equals(c)) + start = (int)state1.getCargoState(); + if (state2!=null && state2.getCargo().equals(c)) + finish = (int)state2.getCargoState(); + List vc = new ArrayList(); + List intens = new ArrayList(); + for (OperationTemplate tp : templates) + if (tp instanceof LoadingTemplate) + { + int i = templates.indexOf(tp); + LoadingTemplate ltp = (LoadingTemplate)tp; + if (ltp.getLoader().equals(s) && ltp.getStorage().getCargo().equals(c)) + { + vc.add(i); + intens.add((int)ltp.getIntensity()); + } + } + for (int j=0; j0) + clause += " +" + intens.get(counter) + " " +xij(vci, k, nTimes, true); + if (intens.get(counter)<0) + clause += " " + intens.get(counter) + " " +xij(vci, k, nTimes, true); + counter++; + } + } + if (clause.length()>0) + { + if (j= -" + start + " ;\n"); + nCons++; + } + // Ограничение на грузоподъемность судна + int maxLoad = (int)(s.getCargoMax()+1.0); + if (sumplus > (maxLoad - start)) + { + writer.write(clause + " <= " + (maxLoad - start) + " ;\n"); + nCons++; + } + } + else + { + // Конечное состояние судна + writer.write(clause + " = " + (finish - start) + " ;\n"); + nCons++; + } + } + } + } + + // Нахождение всех судов в конечный момент в нужном состоянии + writer.write("* Final Ship Locations \n"); + if (eState!=null) + { + int vi = vss.indexOf(s); + for (Berth berth : berths) + { + int bi = berths.indexOf(berth); + String clause = " +1 "+wrbj(vi, bi, nTimes-1, nBerths, nTimes, nVars, isMooring, false, true) + " = "; + if (eState.getLocation().equals(berth)) + { + writer.write(clause + "1 ;\n"); + nCons++; + } + else + { + writer.write(clause + "0 ;\n"); + nCons++; + } + } + } + + } + + // Невозможность одновременного нахождения двух пришвартованных судов у одного причала + writer.write("* No more than 1 vessel moored to berth \n"); + if (isMooring) + { + for (Berth b : berths) + { + if (b.getIsRaid()) + continue; + int bdx = berths.indexOf(b); + for (int j=1; j makeList(String... strings) { + return Arrays.asList(strings); + } + + private static ArrayList> initArray(int size) { + ArrayList> res = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + res.add(new TreeSet<>()); + } + return res; + } + + public void simpleMiniZincConversion(String fileName) throws IOException, ConversionException { + try(FileWriter writer = new FileWriter(fileName, false)) { + writer.write("include \"globals.mzn\";\n"); + int n_intervals = (int)getPlanningInterval(); + + writer.write("int: n_intervals = " + n_intervals + ";\n"); + + ArrayList ships = new ArrayList<>(getShips()); + Map shipNumberById = new TreeMap<>(); + for (int i = 0; i < ships.size(); i++) { + shipNumberById.put(ships.get(i).getId(), i); + } + writer.write("int: n_transports = " + ships.size() + ";\n"); + + ArrayList berths = new ArrayList<>(getBerths()); + Map berthNumberById = new TreeMap<>(); + for (int i = 0; i < berths.size(); i++) { + berthNumberById.put(berths.get(i).getId(), i); + } + writer.write("int: n_berths = " + berths.size() + ";\n"); + + ArrayList tows = new ArrayList<>(getTows()); + Map towNumberById = new TreeMap<>(); + for (int i = 0; i < tows.size(); i++) { + towNumberById.put(tows.get(i).getId(), i); + } + writer.write("int: n_tows = " + tows.size() + ";\n"); + + writer.write("\n"); + + writer.write("set of int: Operations_identifiers = {-2, -1"); + for(OperationTemplate operation : getTemplates()) { + writer.write(", " + operation.getId()); + } + writer.write("};\n"); + + writer.write("enum Berth_status = {free, moored, berthing, de_berthing};\n"); + + writer.write("array [1..n_berths, 0..n_intervals] of var 0..n_transports : transport_in_berthing;\n"); + writer.write("array [1..n_berths, 0..n_intervals] of var Berth_status : berths_status;\n"); + // -2 - занят, -1 - свободен, i - начало i-той операции. + writer.write("array [1..n_berths, 0..n_intervals] of var Operations_identifiers : berths_operations;\n\n"); + + writer.write("enum Moving_obj_status = {in_the_way, in_place};\n"); + + writer.write("array [1..n_transports, 0..n_intervals] of var 1..n_berths : transports_destination;\n"); + writer.write("array [1..n_transports, 0..n_intervals] of var Moving_obj_status : transports_status;\n"); + writer.write("array [1..n_transports, 0..n_intervals] of var Operations_identifiers : transports_operations;\n\n"); + + writer.write("array [1..n_tows, 0..n_intervals] of var 1..n_berths : tows_destination;\n"); + writer.write("array [1..n_tows, 0..n_intervals] of var Moving_obj_status : tows_status;\n"); + writer.write("array [1..n_tows, 0..n_intervals] of var Operations_identifiers : tows_operations;\n\n"); + + { // Пункт назначения может измениться только в начале новой реальной операции. + for (String name : makeList("transports", "tows")) { + writer.write("constraint forall (i in 1..n_" + name + ", j in 1..n_intervals)" + + "((" + name + "_operations[i, j] in {-2, -1}) -> " + + "(" + name + "_destination[i, j] == " + name + "_destination[i, j - 1]));\n"); + } + // Из свободного состояния нельзя перейти в "занято". + for (String name : makeList("berths", "transports", "tows")) { + writer.write("constraint forall (i in 1..n_" + name + ", j in 1..n_intervals) " + + "((" + name + "_operations[i, j] == -2) -> (" + name + "_operations[i, j - 1] != -1));\n"); + } + writer.write("\n"); + } + + { // Начальные состояния. + // Все объекты на своих местах. + for (MovingObjectState state : getVesselInitialState()) { + int dest_n = berthNumberById.get(state.getLocation().getId()); + int obj_id = state.getVessel().getId(); + if (shipNumberById.containsKey(obj_id)) { + writer.write("constraint (transports_destination[" + (shipNumberById.get(obj_id) + 1) + ", 0] == " + (dest_n + 1) + ");\n"); + continue; + } + if (towNumberById.containsKey(obj_id)) { + writer.write("constraint (tows_destination[" + (towNumberById.get(obj_id) + 1) + ", 0] == " + (dest_n + 1) + ");\n"); + continue; + } + throw new ConversionException("Unknown id " + obj_id + " - not transport and not tow."); + } + writer.write("\n"); + // Никто ничего не делает. + for (String name : makeList("berths", "transports", "tows")) { + writer.write("constraint forall (i in 1..n_" + name + ") (" + name + "_operations[i, 0] == -1);\n"); + } + writer.write("\n"); + + // Все на месте. + for (String name : makeList("transports", "tows")) { + writer.write("constraint forall (i in 1..n_" + name + ") (" + name + "_status[i, 0] == in_place);\n"); + } + writer.write("\n"); + // Все причалы изначально пусты. + // TODO учесть операции в процессе. + writer.write("constraint forall (i in 1..n_berths) (transport_in_berthing[i, 0] == 0);\n\n"); + } + + { // Конечные состояния. + // TODO + } + + // Причал свободен <=> его не занимает ни один корабль (фиктивный корабль с индексом 0). + writer.write("constraint forall (i in 1..n_berths, j in 1..n_intervals)" + + "((berths_status[i, j] == free) == (transport_in_berthing[i, j] == 0));\n"); + + // Причал занят кораблём -> пункт назначения корабля - данный причал, и он на месте. + writer.write("constraint forall (i in 1..n_berths, j in 1..n_intervals)" + + "(transport_in_berthing[i, j] > 0 -> " + + "((transports_destination[transport_in_berthing[i, j], j] == i)) /\\ (transports_status[transport_in_berthing[i, j], j] == in_place));\n"); + + ArrayList> usingOperationsWithThisBerth = initArray(getBerths().size()); + ArrayList> usingOperationsWithThisTransport = initArray(getShips().size()); + ArrayList> usingOperationsWithThisTow = initArray(getTows().size()); + + { // Операции перемещения. + for (OperationTemplate t : getTemplates()) { + if (t instanceof MovingTemplate) { + MovingTemplate operation = (MovingTemplate)t; + // TODO рассмотреть общий случай, ввести отдельный движущийся объект. + int transportNo = shipNumberById.get(operation.getMover().getId()); + int destNo = berthNumberById.get(operation.getDestination().getId()); + + usingOperationsWithThisBerth.get(destNo).add(operation.getId()); + usingOperationsWithThisTransport.get(transportNo).add(operation.getId()); + + { // Если операция началась - то началась у всех. + // TODO + } + +// operation.getResources(); + } + } + writer.write("\n"); + } + + { // Запрещаем все операции, которые не используют данный объект. + ArrayList>, String>> classesOfObjects = new ArrayList<>(); + classesOfObjects.add(new Pair<>(usingOperationsWithThisBerth, "berths")); + classesOfObjects.add(new Pair<>(usingOperationsWithThisTransport, "transports")); + classesOfObjects.add(new Pair<>(usingOperationsWithThisTow, "tows")); + + for (Pair>, String> p : classesOfObjects) { + for (int key = 0; key < p.getKey().size(); key++) { + writer.write("constraint forall (j in 0..n_intervals) (" + p.getValue() + "_operations[" + (key + 1) + ", j] in {-2, -1"); + + for (Integer usedOperation : p.getKey().get(key)) { + writer.write(", " + usedOperation); + } + writer.write("});\n"); + } + } + writer.write("\n"); + } + + writer.write("\nsolve satisfy;\n\n"); + writer.write("output ["); + for (String name : makeList("transport_in_berthing", "berths_status", "berths_operations", + "transports_destination", "transports_status", "transports_operations", + "tows_destination", "tows_status", "tows_operations")) { + writer.write("\"" + name + " = \", show(" + name + "), \"\\n\",\n "); + } + writer.write("];\n"); + } + } +} diff --git a/src/inport/Tow.java b/src/inport/Tow.java new file mode 100644 index 0000000000000000000000000000000000000000..bbcf746ff8cfdec2da0b3d9b8eecba86a840a0d1 --- /dev/null +++ b/src/inport/Tow.java @@ -0,0 +1,30 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class Tow extends MovingObject { + + public Tow(int id, String name) { + super(id, name); + } + + public Tow() { + } + + @Override + public String toString() { + return getId() + ";" + getName() + ";1000000"; + } + + public Tow(String s) { + super(s); + } + + +} diff --git a/src/inport/TowUsingTemplate.java b/src/inport/TowUsingTemplate.java new file mode 100644 index 0000000000000000000000000000000000000000..f79ea36c713d9be8e99767450dbd04fc29e6317b --- /dev/null +++ b/src/inport/TowUsingTemplate.java @@ -0,0 +1,85 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author topazh_ag + */ +public abstract class TowUsingTemplate extends OperationTemplate { + + + private List resources; + private double duration; + + + /** + * Get the value of resources + * + * @return the value of resources + */ + public List getResources() { + return resources; + } + + /** + * Set the value of resources + * + * @param resources new value of resources + */ + public void setResources(List resources) { + this.resources = resources; + } + + /** + * Get the value of duration + * + * @return the value of duration + */ + public double getDuration() { + return duration; + } + + /** + * Set the value of duration + * + * @param duration new value of duration + */ + public void setDuration(double duration) { + this.duration = duration; + } + + + + public TowUsingTemplate(double duration, int id, Berth startLocation) { + super(id, startLocation); + this.resources = new ArrayList<>(); + this.duration = duration; + } + + public TowUsingTemplate() { + this.resources = new ArrayList<>(); + } + + @Override + public String toString() { + String res = ""; + boolean first = true; + for(Tow eq : resources) + { + if (!first) + res += "," + eq.getId(); + else + res += eq.getId(); + first = false; + } + return getId() + ";" + "tut" + ";" + ";[" + res +"];"+duration; + } + + +} diff --git a/src/inport/TransportShip.java b/src/inport/TransportShip.java new file mode 100644 index 0000000000000000000000000000000000000000..9c64925e886c4f84ff20eaf61d6aa79138b2fe63 --- /dev/null +++ b/src/inport/TransportShip.java @@ -0,0 +1,42 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package inport; + +/** + * + * @author topazh_ag + */ +public class TransportShip extends MovingObject { + + private double cargoMax; + + public double getCargoMax() { + return cargoMax; + } + + public void setCargoMax(double cargoMax) { + this.cargoMax = cargoMax; + } + + public TransportShip(int id, String name, double cargoMax) { + super(id, name); + this.cargoMax = cargoMax; + } + + public TransportShip() { + } + + @Override + public String toString() { + return getId() + ";" + getName() + ";" + cargoMax; + } + + public TransportShip(String s) { + super(s); + String[] tokens = s.split(";"); + cargoMax = Double.parseDouble(tokens[2].trim()); + } + +} diff --git a/test/conversion_0.dzn b/test/conversion_0.dzn new file mode 100644 index 0000000000000000000000000000000000000000..6942c13d28682d0182b2fcd8366baaca8b578e17 --- /dev/null +++ b/test/conversion_0.dzn @@ -0,0 +1,20 @@ +n_intervals = 24; +n_operations = 16; +n_locations = 6; +n_moving_obj = 2; + +arrival_op = + [| {2, 4}, {}, {1, 6}, {}, {3, 5}, {} + | {8, 10}, {}, {7, 12}, {}, {9, 11}, {} + |]; +departure_op = + [| {1, 3}, {}, {2, 5}, {}, {4, 6}, {} + | {7, 9}, {}, {8, 11}, {}, {10, 12}, {} + |]; +initial_m_obj_loc = [1, 1]; + +operations_duration = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]; +is_moving_operation = [true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false]; +final_m_obj_loc = [0, 0]; +operations_start_loc = [0, 2, 0, 4, 2, 4, 0, 2, 0, 4, 2, 4, 0, 0, 0, 0]; +operations_resources = [{1}, {1}, {1}, {1}, {1}, {1}, {2}, {2}, {2}, {2}, {2}, {2}, {}, {}, {}, {}]; diff --git a/test/conversion_0.mzn b/test/conversion_0.mzn new file mode 100644 index 0000000000000000000000000000000000000000..cc2a8d5411b11a94a8fbc2524cfbfde5a3ce53f0 --- /dev/null +++ b/test/conversion_0.mzn @@ -0,0 +1,79 @@ +include "globals.mzn"; + +int : n_intervals; +int : n_operations; +int : n_locations; +int : n_moving_obj; + +array [1..n_operations, 0..(n_intervals + 1)] of var bool : op_status; +array [1..n_operations, 0..(n_intervals + 1)] of var bool : op_start; +array [1..n_operations, 0..(n_intervals + 1)] of var bool : op_fin; + +% 0 - локация не определена. +array [1..n_moving_obj, 0..(n_intervals + 1)] of var 0..n_locations : m_obj_loc; % Moving object location. + +array [1..n_moving_obj, 1..n_locations] of set of 1..n_operations : arrival_op; +array [1..n_moving_obj, 1..n_locations] of set of 1..n_operations : departure_op; + +% Определение m_obj_loc. +constraint forall (i in 1..n_moving_obj, j in 1..(n_intervals + 1)) + ((m_obj_loc[i, j] != 0) -> ( + (m_obj_loc[i, j] == m_obj_loc[i, j - 1] /\ (forall (k in departure_op[i, m_obj_loc[i, j]]) (op_status[k, j - 1] == 0))) + \/ + (not (forall (k in arrival_op[i, m_obj_loc[i, j]]) (op_fin[i, j - 1] == 0))) + )); + +% Начальное состояние. +array [1..n_moving_obj] of var 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]); + +% Конечное состояние. +array [1..n_moving_obj] of var 0..n_locations : final_m_obj_loc; +constraint forall (i in 1..n_moving_obj) ( + (final_m_obj_loc[i] != 0) -> + (m_obj_loc[i, n_intervals + 1] = final_m_obj_loc[i]) +); + +constraint forall (i in 1..n_operations, j in {0, n_intervals + 1}) (op_status[i, j] == 0); % Краевые значения. + +% Определение op_start и op_fin. +constraint forall (i in 1..n_operations) (op_start[i, 0] == 0 /\ op_fin[i, n_intervals + 1] == 0); +constraint forall (i in 1..n_operations, j in 1..(n_intervals + 1)) (op_start[i, j] = op_status[i, j] /\ not op_status[i, j - 1]); +constraint forall (i in 1..n_operations, j in 1..n_intervals ) (op_fin [i, j] = op_status[i, j] /\ not op_status[i, j + 1]); + +% Непрерывность перемещения. +array [1..n_operations] of var int : operations_duration; +array [1..n_operations] of var bool : is_moving_operation; + +constraint forall (i in 1..n_operations) ( + if (is_moving_operation[i]) then ( + forall (j in 1..n_intervals) ( + if (j + operations_duration[i] > n_intervals + 1) then + op_start[i, j] = 0 + else ( + (op_start[i, j] == 1) -> ( + (forall (k in 1..(operations_duration[i] - 1)) + (op_status[i, j + k] == 1) + ) /\ + (op_status[i, j + operations_duration[i]] == 0) + ) + ) + endif + ) + ) else true + endif +); + +% Наличие всех ресурсов на месте. +array [1..n_operations] of set of 1..n_moving_obj : operations_resources; +array [1..n_operations] of 0..n_locations : operations_start_loc; + +constraint forall (op in 1..n_operations, j in 1..n_intervals) ( + forall (obj in operations_resources[op]) ( + (op_start[op, j]) -> (m_obj_loc[obj, j] == operations_start_loc[op]) + ) +); + +solve satisfy; + +output ["op_status = ", show(op_status), "\n"]; diff --git a/test/conversion_0_start.bat b/test/conversion_0_start.bat new file mode 100644 index 0000000000000000000000000000000000000000..eb4e93a08fa155bf9c566038706035dd73bfa403 --- /dev/null +++ b/test/conversion_0_start.bat @@ -0,0 +1,2 @@ +minizinc --solver Gecode conversion_0.mzn conversion_0.dzn +:: minizinc --solver Chuffed conversion_0.mzn conversion_0.data diff --git a/test/in_1.ipp b/test/in_1.ipp new file mode 100644 index 0000000000000000000000000000000000000000..dfdfc6794df70b6a2a8f5418a9728d5c3e1c1350 --- /dev/null +++ b/test/in_1.ipp @@ -0,0 +1,63 @@ +Cargoes +0;LNG;0.0 +Berths +1;Raid +2;Pier 1 +3;Pier 2 +Storages +4;Storage 1;0;10000.0 +Bunkers +Tows +Loading Equipments +Transport Ships +5;Ship 1;2000.0 +6;Ship 2;2000.0 + +Templates +7;mov;[];5;1;2;[];1.0 +8;mov;[];5;2;1;[];1.0 +9;mov;[];5;1;3;[];1.0 +10;mov;[];5;3;1;[];1.0 +11;mov;[];5;2;3;[];1.0 +12;mov;[];5;3;2;[];1.0 +13;mov;[];6;1;2;[];1.0 +14;mov;[];6;2;1;[];1.0 +15;mov;[];6;1;3;[];1.0 +16;mov;[];6;3;1;[];1.0 +17;mov;[];6;2;3;[];1.0 +18;mov;[];6;3;2;[];1.0 +19;loa;[];4;0;5;2;[];100.0 +20;loa;[];4;0;5;3;[];50.0 +21;loa;[];4;0;6;2;[];100.0 +22;loa;[];4;0;6;3;[];50.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 +24.0;0 + +Solution +16.0 +7; R; 1.0; 1.0 +10; R; 16.0; 1.0 +11; R; 9.0; 1.0 +14; R; 16.0; 1.0 +15; R; 1.0; 1.0 +18; R; 8.0; 1.0 +19; R; 2.0; 7.0 +20; R; 10.0; 6.0 +21; R; 9.0; 7.0 +22; R; 2.0; 6.0