Commit 84bd0eb0 authored by Vladislav Kiselev's avatar Vladislav Kiselev

Начало

parent 7a9c7444
/*
* 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();
}
}
/*
* 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);
}
}
/*
* 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]);
}
}
/*
* 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<Double, Double> flow;
public Map<Double, Double> getFlow() {
return flow;
}
public void setFlow(Map<Double, Double> 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<Double> keyTimes = flow.keySet();
double prevKey = -1.0;
for (Double keyTime : keyTimes)
{
if (forTime>prevKey && forTime<keyTime)
{
res = flow.get(prevKey);
isFound = true;
break;
} else
prevKey = keyTime;
}
if (!isFound && forTime>prevKey)
res = flow.get(prevKey);
return res;
}
public double getTotalValue(double forTime)
{
double res = 0.0;
boolean isFound = false;
Set<Double> keyTimes = flow.keySet();
double prevKey = -1.0;
for (Double keyTime : keyTimes)
{
if (forTime>prevKey && forTime<keyTime)
{
res += flow.get(prevKey)*(forTime-prevKey);
isFound = true;
break;
} else
{
res += flow.get(prevKey)*(keyTime-prevKey);
prevKey = keyTime;
}
}
if (!isFound && forTime>prevKey)
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<Integer, Storage> mp, Map<Integer, Cargo> 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);
}
}
}
package inport;
public class ConversionException extends Exception {
ConversionException(String mess) {
super(mess);
}
}
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<Pair<Integer, Boolean>> {
public int compare(Pair<Integer, Boolean> p1, Pair<Integer, Boolean> 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<ArrayList<ArrayList<Integer>>> operations) throws IOException {
writer.write(name + " = \n");
boolean isFirst0 = true;
for (ArrayList<ArrayList<Integer>> m1 : operations) {
if (isFirst0) {
isFirst0 = false;
writer.write(" [| ");
} else {
writer.write(" | ");
}
boolean isFirst1 = true;
for (ArrayList<Integer> 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 <T, E> void writeArray(FileWriter writer, String name, ArrayList<T> data, Function<T, E> 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 <T> void writeArray(FileWriter writer, String name, ArrayList<T> data) throws IOException {
writeArray(writer, name, data, (T val) -> val);
}
static private <T> String setToString(Set<T> 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<Integer> integerArray(int size, int initVal) {
ArrayList<Integer> 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<Berth> berths = new ArrayList<>(task.getBerths());
Map<Pair<Integer, Boolean>, 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<MovingObject> movingObjects = new ArrayList<>();
Map<Integer, Integer> 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<MovingObject, Integer> mObjToN = (MovingObject obj) -> mObjNumberById.get(obj.getId());
ArrayList<OperationTemplate> operationTemplates = new ArrayList<>(task.getTemplates());
{
ArrayList<ArrayList<ArrayList<Integer>>> arrivalOp = new ArrayList<>();
ArrayList<ArrayList<ArrayList<Integer>>> 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<Integer> 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<Integer> 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<Integer> operationsDuration = integerArray(operationTemplates.size(), 0);
ArrayList<Boolean> 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<Integer> 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<Set<Integer>> operationsResources = new ArrayList<>();
ArrayList<Integer> 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<Integer> 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);
}
}
}
}
/*
* 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);
}
}
/*
* 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<LoadingEquipment> resources;
private double intensity;
/**
* Get the value of resources
*
* @return the value of resources
*/
public List<LoadingEquipment> getResources() {
return resources;
}
/**
* Set the value of resources
*
* @param resources new value of resources
*/
public void setResources(List<LoadingEquipment> 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);
}
}
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());
}
}
}
/*
* 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();
}
}
/*
* 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();
}
}
/*
* 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();
}
}
/*
* 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();
}
}
/*
* 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;
}
}
/*
* 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<Double, Double> 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<Double, Double> getTimeWindows() {
return timeWindows;
}
public void setBanWindows(Map<Double, Double> 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);
}
}
}
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
/*
* 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<Integer, Cargo> 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);
}
}
/*
* 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<Integer, Storage> mp, Map<Integer, MovingObject> vp, Map<Integer, Cargo> 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());
}
}
/*
* 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<Cargo> cargoes;
private List<Berth> berths;
private List<Storage> storages;
private List<Bunker> bunkers;
private List<Tow> tows;
private List<LoadingEquipment> equipments;
// Обслуживаемые суда
private List<TransportShip> ships;
// Шаблоны операций
private List<OperationTemplate> templates;
// Внешние грузопотоки
private List<CargoFlow> cargoFlows;
// Начальное состояние
private List<MovingObjectState> vesselInitialState;
private List<StorageState> storageInitialState;
// Конечное состояние
private List<MovingObjectState> vesselEndState;
private List<StorageState> storageEndState;
// Горизонт планирования
private double planningInterval;
// Тип критерия оптимизации
private int criterionType;
// План - критерий
private double solution_result;
// План - решение
private List<Operation> solution;
/**
* Get the value of solution
*
* @return the value of solution
*/
public List<Operation> getSolution() {
return solution;
}
/**
* Set the value of solution
*
* @param solution new value of solution
*/
public void setSolution(List<Operation> 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<CargoFlow> getCargoFlows() {
return cargoFlows;
}
/**
* Set the value of cargoFlows
*
* @param cargoFlows new value of cargoFlows
*/
public void setCargoFlows(List<CargoFlow> cargoFlows) {
this.cargoFlows = cargoFlows;
}
/**
* Get the value of vesselEndState
*
* @return the value of vesselEndState
*/
public List<MovingObjectState> getVesselEndState() {
return vesselEndState;
}
/**
* Set the value of vesselEndState
*
* @param vesselEndState new value of vesselEndState
*/
public void setVesselEndState(List<MovingObjectState> vesselEndState) {
this.vesselEndState = vesselEndState;
}
public List<StorageState> getStorageEndState() {
return storageEndState;
}
public void setStorageEndState(List<StorageState> storageEndState) {
this.storageEndState = storageEndState;
}
/**
* Get the value of storageInitialState
*
* @return the value of storageInitialState
*/
public List<StorageState> getStorageInitialState() {
return storageInitialState;
}
/**
* Set the value of storageInitialState
*
* @param storageInitialState new value of storageInitialState
*/
public void setStorageInitialState(List<StorageState> storageInitialState) {
this.storageInitialState = storageInitialState;
}
/**
* Get the value of vesselInitialState
*
* @return the value of vesselInitialState
*/
public List<MovingObjectState> getVesselInitialState() {
return vesselInitialState;
}
/**
* Set the value of vesselInitialState
*
* @param vesselInitialState new value of vesselInitialState
*/
public void setVesselInitialState(List<MovingObjectState> vesselInitialState) {
this.vesselInitialState = vesselInitialState;
}
/**
* Get the value of templates
*
* @return the value of templates
*/
public List<OperationTemplate> getTemplates() {
return templates;
}
/**
* Set the value of templates
*
* @param templates new value of templates
*/
public void setTemplates(List<OperationTemplate> templates) {
this.templates = templates;
}
/**
* Get the value of ships
*
* @return the value of ships
*/
public List<TransportShip> getShips() {
return ships;
}
/**
* Set the value of ships
*
* @param ships new value of ships
*/
public void setShips(List<TransportShip> ships) {
this.ships = ships;
}
/**
* Get the value of equipments
*
* @return the value of equipments
*/
public List<LoadingEquipment> getEquipments() {
return equipments;
}
/**
* Set the value of equipments
*
* @param equipments new value of equipments
*/
public void setEquipments(List<LoadingEquipment> equipments) {
this.equipments = equipments;
}
/**
* Get the value of tows
*
* @return the value of tows
*/
public List<Tow> getTows() {
return tows;
}
/**
* Set the value of tows
*
* @param tows new value of tows
*/
public void setTows(List<Tow> tows) {
this.tows = tows;
}
/**
* Get the value of bunkers
*
* @return the value of bunkers
*/
public List<Bunker> getBunkers() {
return bunkers;
}
/**
* Set the value of bunkers
*
* @param bunkers new value of bunkers
*/
public void setBunkers(List<Bunker> bunkers) {
this.bunkers = bunkers;
}
/**
* Get the value of storages
*
* @return the value of storages
*/
public List<Storage> getStorages() {
return storages;
}
/**
* Set the value of storages
*
* @param storages new value of storages
*/
public void setStorages(List<Storage> storages) {
this.storages = storages;
}
/**
* Get the value of cargoes
*
* @return the value of cargoes
*/
public List<Cargo> getCargoes() {
return cargoes;
}
/**
* Set the value of cargoes
*
* @param cargoes new value of cargoes
*/
public void setCargoes(List<Cargo> cargoes) {
this.cargoes = cargoes;
}
/**
* Get the value of berths
*
* @return the value of berths
*/
public List<Berth> getBerths() {
return berths;
}
/**
* Set the value of berths
*
* @param berths new value of berths
*/
public void setBerths(List<Berth> 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<Integer, Berth> m_berth, Map<Integer, MovingObject> 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<Integer, Cargo> m_cargo = new HashMap<>();
Map<Integer, Berth> m_berth = new HashMap<>();
Map<Integer, Storage> m_storage = new HashMap<>();
Map<Integer, MovingObject> m_vessel = new HashMap<>();
Map<Integer, LoadingEquipment> m_equiopment = new HashMap<>();
Map<Integer, OperationTemplate> 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; i<tags.length; i++)
if (strLine.equals(tags[i]))
{
index = i+1;
serviceString = true;
break;
}
if (serviceString || strLine.length()<2 || index==0 || strLine.startsWith("/*"))
{
numInside = 0;
continue;
}
switch (index) {
case 1: Cargo c = new Cargo(strLine); cargoes.add(c); m_cargo.put(c.getId(), c);
break;
case 2: Berth b = new Berth(strLine); berths.add(b); m_berth.put(b.getId(), b);
break;
case 3: Storage s = new Storage(strLine, m_cargo); storages.add(s); m_storage.put(s.getId(), s);
break;
case 4:
break;
case 5: Tow t = new Tow(strLine); tows.add(t); m_vessel.put(t.getId(), t);
break;
case 6: LoadingEquipment l = new LoadingEquipment(strLine); equipments.add(l); m_equiopment.put(l.getId(), l); m_vessel.put(l.getId(), l);
break;
case 7: TransportShip ts = new TransportShip(strLine); ships.add(ts); m_vessel.put(ts.getId(), ts);
break;
case 8: String[] tokens = strLine.split(";");
if (tokens[1].trim().equals("mov"))
{
MovingTemplate mt = new MovingTemplate();
mt.setId(Integer.parseInt(tokens[0].trim()));
mt.setTimeWindow(tokens[2].trim());
int key = Integer.parseInt(tokens[3].trim());
mt.setMover(m_vessel.get(key));
key = Integer.parseInt(tokens[4].trim());
mt.setStartLocation(m_berth.get(key));
key = Integer.parseInt(tokens[5].trim());
mt.setDestination(m_berth.get(key));
String[] rs = tokens[6].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[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; i<nTimes; i++)
{
cIndex++;
if (res[cIndex]>0)
{
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<Object> resources1 = getResources(t1);
MovingObject doer2 = getDoer(t2);
Berth place2 = t2.getStartLocation();
List<Object> 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<Object> getResources(OperationTemplate t)
{
List<Object> 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<Integer> 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<MovingObject> vss = new ArrayList<MovingObject>();
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<nTimes; j++)
{
String clause = "";
for (int i=0; i<nOperations; i++)
clause += " "+xij(i, j, nTimes, false);
crit += " -"+degree+clause;
degree = degree * 2;
}
writer.write("min: " + crit + " ;\n");
*/
// Критерий оптимизации новый
String crit = "";
for (int j=0; j<nTimes; j++)
{
String clause = " +"+(j+1)+" "+fj(j, nBefore, true);
for (int k=j+1; k<nTimes; k++)
clause += " "+fj(k, nBefore, false);
crit += clause;
}
writer.write("min: " + crit + " ;\n");
// Вычисление служебных переменных для нового критерия
writer.write("* Criteria Variables \n");
for (int j=0; j<nTimes; j++)
{
String clause = " +1 " + fj(j, nBefore, true) + " +1";
for (OperationTemplate tp : templates)
{
int i = templates.indexOf(tp);
clause += " " + xij(i, j, nTimes, false);
}
writer.write(clause+" = 1 ;\n");
nCons++;
}
// Ограничения на окна непогоды
writer.write("* Time Window Constraints \n");
for (OperationTemplate tp : templates)
{
int i = templates.indexOf(tp);
Set<Double> 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<nOperations; i1++)
{
OperationTemplate t1 = templates.get(i1);
List<Integer> excluders = new ArrayList<Integer>();
for (int i2 = i1+1; i2<nOperations; i2++)
{
OperationTemplate t2 = templates.get(i2);
if (!isCompatible(t1, t2))
excluders.add(i2);
}
if (excluders.size()>0)
{
for (int j=0; j<nTimes; j++)
{
String clause = " +1 " + xij(i1,j,nTimes,false) + " +1 " + xij(i1,j,nTimes,true);
for (Integer exc : excluders)
clause += " " + xij(exc,j,nTimes,false);
writer.write(clause + " >= 1 ;\n");
nCons++;
}
}
}
/*
// Старая байда
// Буксиры
writer.write("* For Tows \n");
for (Tow tow : tows)
{
List<Integer> iks = new ArrayList<Integer>();
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<nTimes; j++)
{
writer.write(sum1(iks,j,nTimes,1)+" <= 1 ;\n");
nCons++;
}
}
// Краны
writer.write("* For Loading Equipments \n");
for (LoadingEquipment le : equipments)
{
List<Integer> iks = new ArrayList<Integer>();
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<nTimes; j++)
{
writer.write(sum1(iks,j,nTimes,1)+" <= 1 ;\n");
nCons++;
}
}
// Бункеровщики
writer.write("* For Bunkers \n");
for (Bunker bk : bunkers)
{
List<Integer> iks = new ArrayList<Integer>();
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<nTimes; j++)
{
writer.write(sum1(iks,j,nTimes,1)+" <= 1 ;\n");
nCons++;
}
}
// Причалы
writer.write("* For Berths \n");
for (Berth bt : berths)
{
List<Integer> mrks = new ArrayList<Integer>();
List<List<Integer>> opbs = new ArrayList<List<Integer>>();
for (TransportShip ship : ships)
opbs.add(new ArrayList<Integer>());
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<nTimes; j++)
{
writer.write(sum1(mrks,j,nTimes,1)+" <= 1 ;\n");
nCons++;
}
// На причале одновременно грузится (швартуется/бункеруется) только одно судно
if (filled)
for (int j=0; j<nTimes; j++)
{
String clause = "";
int nVess = 0;
for (List<Integer> 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<Integer> mvks = new ArrayList<Integer>();
List<Integer> loks = new ArrayList<Integer>();
List<Integer> mrks = new ArrayList<Integer>();
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; j<nTimes; j++)
{
String clause = sum1(mvks,j,nTimes,nLM);
clause += sum1(loks,j,nTimes,1);
clause += sum1(mrks,j,nTimes,1);
writer.write(clause+" <= " + nLM + " ;\n");
nCons++;
}
}
// TODO: Здесь еще как-то надо разбираться с пересечением швартовок, погрузок на разных причалах и т.д.
if (!loks.isEmpty())
{
}
}
*/
// Ограничения на непрерывность операций швартовки/перемещения
writer.write("* Unterminated Mooring and Moving \n");
for (OperationTemplate tpl : templates)
{
int ik = templates.indexOf(tpl);
int opd = -1;
if (tpl instanceof MovingTemplate)
{
MovingTemplate mt = (MovingTemplate)tpl;
opd = (int)(mt.getDuration() + 1.0 - 1e-7);
}
if (tpl instanceof MooringTemplate)
{
MooringTemplate mt = (MooringTemplate)tpl;
opd = (int)(mt.getDuration() + 1.0 - 1e-7);
}
int bJ = Math.min(nTimes, opd);
if (opd>0)
{
String res = "+1 " + xij(ik,0,nTimes,false) + " +1 "+xij(ik,0,nTimes,true);
for (int k=0; k<bJ; k++)
res += " " +xij(ik,k,nTimes,true);
writer.write(res+" >= 1 ;\n");
nCons++;
for (int j=1; j<nTimes; j++)
{
bJ = Math.min(nTimes, j+opd);
res = "-1 "+xij(ik,j-1,nTimes,false) + " " + xij(ik,j,nTimes,true) + " +1 "+xij(ik,j,nTimes,true) + " " + xij(ik,j-1,nTimes,false);
for (int k=j; k<bJ; k++)
res += " " +xij(ik,k,nTimes,true);
writer.write(res+" >= 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<LoadingTemplate> lts = new ArrayList<LoadingTemplate>();
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<nTimes; j++)
{
double sumV = V0;
if (ccf!=null)
sumV += ccf.getTotalValue(j);
String clause = "";
for (int l=0; l<=j; l++)
{
for (LoadingTemplate lt : lts)
{
int ik = templates.indexOf(lt);
int rate = (int)lt.getIntensity();
if (rate<0)
clause += " +" + (-rate) + " " + xij(ik, l, nTimes, true);
else
clause += " -" + rate + " " + xij(ik, l, nTimes, true);
}
}
String cl1 = clause + " >= " + (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<iniTime; j++)
{
String clause = "+1 "+wrbj(r, b, j, nBerths, nTimes, nVars, isMooring, false, true);
writer.write(clause + " = 0 ;\n");
nCons++;
if (isMooring)
{
clause = "+1 "+wrbj(r, b, j, nBerths, nTimes, nVars, isMooring, true, true);
writer.write(clause + " = 0 ;\n");
nCons++;
}
}
// В момент прибытия
if (!iniMoored)
{
String clause = "+1 "+wrbj(r, b, iniTime, nBerths, nTimes, nVars, isMooring, false, true);
writer.write(clause + " = 1 ;\n");
nCons++;
if (isMooring)
{
clause = "+1 "+wrbj(r, b, iniTime, nBerths, nTimes, nVars, isMooring, true, true);
writer.write(clause + " = 0 ;\n");
nCons++;
}
} else
{
String clause = "+1 "+wrbj(r, b, iniTime, nBerths, nTimes, nVars, isMooring, false, true);
writer.write(clause + " = 0 ;\n");
nCons++;
if (isMooring)
{
clause = "+1 "+wrbj(r, b, iniTime, nBerths, nTimes, nVars, isMooring, true, true);
writer.write(clause + " = 1 ;\n");
nCons++;
}
}
}
else
{
iniTime = 0;
String clause = "+1 "+wrbj(r, b, iniTime, nBerths, nTimes, nVars, isMooring, false, true);
writer.write(clause + " = 0 ;\n");
nCons++;
if (isMooring)
{
clause = "+1 "+wrbj(r, b, iniTime, nBerths, nTimes, nVars, isMooring, true, true);
writer.write(clause + " = 0 ;\n");
nCons++;
}
}
// Теперь на все остальные
List<Integer> rb_plus = new ArrayList<Integer>();
List<Integer> rb_minus = new ArrayList<Integer>();
List<Integer> rm_plus = new ArrayList<Integer>();
List<Integer> rm_minus = new ArrayList<Integer>();
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; j<nTimes; j++)
{
String rbm = "";
for (Integer i : rb_minus)
rbm += " " + xij(i,j-1,nTimes,false);
String rbp = " ";
for (Integer i : rb_plus)
rbp += " -1 " + wrbj(r, b, j-1, nBerths, nTimes, nVars, isMooring, false, false) + " " + xij(i, j-1, nTimes, true) + " " + xij(i, j, nTimes, false);
String clause = "1 "+wrbj(r, b, j, nBerths, nTimes, nVars, isMooring, false, true) + " -1 " + wrbj(r, b, j-1, nBerths, nTimes, nVars, isMooring, false, true) + rbm + rbp;
writer.write(clause + " = 0 ;\n");
nCons++;
}
}
if (isMooring) //(rm_plus.size()>0 && rm_minus.size()>0)
{
for (int j=1; j<nTimes; j++)
{
String rbm = "";
for (Integer i : rm_minus)
rbm += " " + xij(i,j-1,nTimes,false);
String rbp = " ";
for (Integer i : rm_plus)
rbp += " -1 " + wrbj(r, b, j-1, nBerths, nTimes, nVars, isMooring, true, false) + " " + xij(i, j-1, nTimes, true) + " " + xij(i, j, nTimes, false);
String clause = "1 "+wrbj(r, b, j, nBerths, nTimes, nVars, isMooring, true, true) + " -1 " + wrbj(r, b, j-1, nBerths, nTimes, nVars, isMooring, true, true) + rbm + rbp;
writer.write(clause + " = 0 ;\n");
nCons++;
}
}
}
}
// Нахождение всего там, где надо
writer.write("* Correct Places of Moving Resources \n");
for (OperationTemplate tp : templates)
{
int i = templates.indexOf(tp);
List<Integer> resources_f = new ArrayList<Integer>(); // Свободные
List<Integer> resources_m = new ArrayList<Integer>(); // Пришвартованные
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; j<nTimes; j++)
{
String clause = "1 "+xij(i, j, nTimes, false) + " +1 " + xij(i, j, nTimes, true);
if (!isAlways && j>0)
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<Integer> vc = new ArrayList<Integer>();
List<Integer> intens = new ArrayList<Integer>();
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; j<nTimes; j++)
{
String clause = "";
double sumplus = 0.0;
double summinus = 0.0;
for (int k=0; k<=j; k++)
{
int counter = 0;
for (int vci : vc)
{
sumplus += Math.max(intens.get(counter), 0.0);
summinus += Math.min(intens.get(counter), 0.0);
if (intens.get(counter)>0)
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<nTimes-1)
{
// Положительность груза на судне в каждый момент времени
if (summinus<-start)
{
writer.write(clause + " >= -" + 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<nTimes; j++)
{
String clause = "";
for (TransportShip v : ships)
{
int rdx = vss.indexOf(v);
clause += " +1 " + wrbj(rdx, bdx, j, nBerths, nTimes, nVars, isMooring, true, true);
}
writer.write(clause + " <= 1 ;\n");
nCons++;
}
}
}
writer.flush();
writer.close();
FileReader reader = new FileReader("temp");
writer = new FileWriter(fileName, false);
writer.write("* #variable= " + (nBefore + nAfter) + " #constraint= " + nCons + "\n");
BufferedReader breader = new BufferedReader(reader);
String line;
while ((line = breader.readLine()) != null) {
writer.write(line+"\n");
}
breader.close();
writer.flush();
writer.close();
return nOperations;
}
private static List<String> makeList(String... strings) {
return Arrays.asList(strings);
}
private static ArrayList<Set<Integer>> initArray(int size) {
ArrayList<Set<Integer>> 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<TransportShip> ships = new ArrayList<>(getShips());
Map<Integer, Integer> 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<Berth> berths = new ArrayList<>(getBerths());
Map<Integer, Integer> 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<Tow> tows = new ArrayList<>(getTows());
Map<Integer, Integer> 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<Set<Integer>> usingOperationsWithThisBerth = initArray(getBerths().size());
ArrayList<Set<Integer>> usingOperationsWithThisTransport = initArray(getShips().size());
ArrayList<Set<Integer>> 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<Pair<ArrayList<Set<Integer>>, String>> classesOfObjects = new ArrayList<>();
classesOfObjects.add(new Pair<>(usingOperationsWithThisBerth, "berths"));
classesOfObjects.add(new Pair<>(usingOperationsWithThisTransport, "transports"));
classesOfObjects.add(new Pair<>(usingOperationsWithThisTow, "tows"));
for (Pair<ArrayList<Set<Integer>>, 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");
}
}
}
/*
* 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);
}
}
/*
* 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<Tow> resources;
private double duration;
/**
* Get the value of resources
*
* @return the value of resources
*/
public List<Tow> getResources() {
return resources;
}
/**
* Set the value of resources
*
* @param resources new value of resources
*/
public void setResources(List<Tow> 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;
}
}
/*
* 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());
}
}
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}, {}, {}, {}, {}];
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"];
minizinc --solver Gecode conversion_0.mzn conversion_0.dzn
:: minizinc --solver Chuffed conversion_0.mzn conversion_0.data
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
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