package vroom.common.modeling.dataModel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import vroom.common.modeling.util.CostCalculationDelegate;
import vroom.common.utilities.Utilities;
import vroom.common.utilities.dataModel.ObjectWithNameAndId;
/**
* <code>InstanceBase</code> is a base type to describe a VRP instance.
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a> - <a
* href="http://copa.uniandes.edu.co">Copa</a>, <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0 #created 15-Feb-2010 11:29:51 a.m.
*/
public abstract class InstanceBase extends ObjectWithNameAndId implements IVRPInstance {
/** The cost helper. */
private CostCalculationDelegate mCostHelper;
/*
* (non-Javadoc)
*
* @see
* vroom.common.modeling.dataModel.IVRPInstance#setCostHelper(vroom.common
* .modelling.dataModel.CostCalculationDelegate)
*/
@Override
public void setCostHelper(CostCalculationDelegate costHelper) {
mCostHelper = costHelper;
}
/**
* Getter for <code>costHelper</code>
*
* @return the costHelper
*/
@Override
public CostCalculationDelegate getCostDelegate() {
return mCostHelper;
}
/** The depots. */
private List<Depot> mDepots;
@Override
public List<Depot> getDepots() {
return new ArrayList<Depot>(mDepots);
}
/** The nodes defined in this instance */
private final Map<Integer, NodeVisit> mNodesVisits;
/**
* Getter for the set of node visits
*
* @return the reference to the set of nodes defined in this instance
*/
protected Map<Integer, NodeVisit> getNodeVisitsMap() {
return mNodesVisits;
}
/** A mapping between requests and the associated node visits */
private final Map<IVRPRequest, NodeVisit[]> mNodesMap;
/** The depots defined in this instance as node visits */
private final Map<Integer, NodeVisit> mDepotsVisits;
/**
* Getter for <code>depotsVisits</code>
*
* @return the depotsVisits
*/
@Override
public Set<INodeVisit> getDepotsVisits() {
return new HashSet<INodeVisit>(mDepotsVisits.values());
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#getNodeVisits()
*/
@Override
public Set<INodeVisit> getNodeVisits() {
return new HashSet<INodeVisit>(mNodesVisits.values());
}
/*
* (non-Javadoc)
*
* @see
* vroom.common.modeling.dataModel.IVRPInstance#getNodeVisits(vroom.common
* .modelling.dataModel.IRequest)
*/
@Override
public INodeVisit[] getNodeVisits(IVRPRequest request) {
return mNodesMap.get(request);
}
@Override
public INodeVisit getNodeVisit(int nodeID) {
if (mDepotsVisits.containsKey(nodeID))
return mDepotsVisits.get(nodeID);
else if (mNodesVisits.containsKey(nodeID))
return mNodesVisits.get(nodeID);
else
throw new IllegalArgumentException("No node or depot is associated with id " + nodeID);
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#getArcs()
*/
@Override
public Set<IArc> getArcs() {
return mArcs;
}
/** The arcs defined in this instance */
private final Set<IArc> mArcs;
/*
* (non-Javadoc)
*
* @see
* vroom.common.modeling.dataModel.IVRPInstance#setDepots(java.util.List)
*/
@Override
public void setDepots(List<Depot> depots) {
if (mDepots != null) {
throw new IllegalStateException("The depot list is already set for this instance:"
+ mDepots);
}
mDepots = depots;
if (depots != null) {
for (Depot depot : depots) {
mDepotsVisits.put(depot.getID(), newDepotVisit(depot));
}
}
}
protected NodeVisit newDepotVisit(Depot depot) {
return new NodeVisit(depot);
}
/** The fleet. */
private Fleet<?> mFleet;
/*
* (non-Javadoc)
*
* @see
* vroom.common.modeling.dataModel.IVRPInstance#setFleet(vroom.common.modeling
* .dataModel.Fleet)
*/
@Override
public void setFleet(Fleet<?> fleet) {
// if(mFleet!=null)
// throw new
// IllegalStateException("The fleet is already set for this instance:"+mFleet);
mFleet = fleet;
}
/** The routing problem. */
private final VehicleRoutingProblemDefinition mRoutingProblem;
/** The planning period. */
private IPlanningPeriod mPlanningPeriod;
/*
* (non-Javadoc)
*
* @see
* vroom.common.modeling.dataModel.IVRPInstance#setPlanningPeriod(vroom
* .common.modelling.dataModel.IPlanningPeriod)
*/
@Override
public void setPlanningPeriod(IPlanningPeriod planningPeriod) {
if (mPlanningPeriod != null) {
throw new IllegalStateException("The planning period is already set for this instance:"
+ mPlanningPeriod);
}
mPlanningPeriod = planningPeriod;
}
/** A flag defining whether this instance graph is symmetric or not **/
private boolean mSymmetric;
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#isSymmetric()
*/
@Override
public boolean isSymmetric() {
return mSymmetric;
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#setSymmetric(boolean)
*/
@Override
public void setSymmetric(boolean symmetric) {
mSymmetric = symmetric;
}
/**
* Instantiates a new instance base.
*
* @param id
* an id for this instance
* @param name
* a name for this instance
* @param routingProblem
* a definition of the associated routing problem
* @param fleet
* the fleet that will be associated with this instance
* @param depots
* a list of the depots present in this instance
* @param planningPeriod
* the planning period associated with this instance
* @param costDelegate
* a delegate for the calculation of costs
*/
public InstanceBase(int id, String name, VehicleRoutingProblemDefinition routingProblem,
Fleet<?> fleet, List<Depot> depots, IPlanningPeriod planningPeriod,
CostCalculationDelegate costDelegate) {
super(name, id);
mRoutingProblem = routingProblem;
mSymmetric = true;
mArcs = new HashSet<IArc>();
mNodesVisits = new HashMap<Integer, NodeVisit>();
mDepotsVisits = new HashMap<Integer, NodeVisit>();
mNodesMap = new HashMap<IVRPRequest, NodeVisit[]>();
setFleet(fleet);
setDepots(depots);
setCostHelper(costDelegate);
setPlanningPeriod(planningPeriod);
}
/**
* Creates a new empty <code>InstanceBase</code>
*
* @param id
* an id for this instance
* @param routingProblem
* a definition of the associated routing problem
*/
public InstanceBase(int id, String name, VehicleRoutingProblemDefinition routingProblem) {
this(id, name, routingProblem, null, null, null, null);
}
/*
* (non-Javadoc)
*
* @see
* vroom.common.modeling.dataModel.IVRPInstance#addRequest(vroom.common
* .modelling.dataModel.IRequest)
*/
@Override
public final boolean addRequest(IVRPRequest request) {
boolean b = addRequestInternal(request);
if (b) {
addNodes(request);
}
return b;
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#addRequests(java.util.
* Collection)
*/
@Override
public boolean addRequests(Collection<IVRPRequest> requests) {
boolean b = true;
for (IVRPRequest request : requests) {
b &= addRequest(request);
}
return b;
}
/**
* Add the {@link NodeVisit} corresponding to the given request to the set of node visits {@link #mNodesVisits}
*
* @param request
* the request for which the nodes will be generated
*/
private void addNodes(IVRPRequest request) {
NodeVisit[] nodes = NodeVisit.createNodeVisits(request);
// Adding arcs with the depots
for (NodeVisit depot : mDepotsVisits.values()) {
for (NodeVisit n : nodes) {
addArc(depot, n);
}
}
// Adding arcs with other nodes
for (NodeVisit node : mNodesVisits.values()) {
for (NodeVisit n : nodes) {
addArc(node, n);
}
}
for (NodeVisit n : nodes) {
mNodesVisits.put(n.getID(), n);
}
mNodesMap.put(request, nodes);
}
/**
* Add the arc(s) between node1 and node2. If the instance is {@link #isSymmetric() symmetric} then only one arc
* (node1,node2) is added, otherwise both are added.
*
* @param node1
* @param node2
*/
private void addArc(NodeVisit node1, NodeVisit node2) {
if (node1.compareTo(node2) > 0) {
NodeVisit tmp = node1;
node1 = node2;
node2 = tmp;
}
if (!Utilities.equal(node1, node2)) {
mArcs.add(new Arc(node1, node2, mCostHelper.getDistance(node1, node2), !isSymmetric()));
if (!isSymmetric()) {
mArcs.add(new Arc(node2, node1, mCostHelper.getDistance(node2, node1),
!isSymmetric()));
}
}
}
/**
* Add a new request to this instance.
*
* @param request
* @return <code>true</code> if the request was successfully added to the instance
*/
protected abstract boolean addRequestInternal(IVRPRequest request);
/*
* (non-Javadoc)
*
* @see
* vroom.common.modeling.dataModel.IVRPInstance#removeRequest(vroom.common
* .modelling.dataModel.IRequest)
*/
@Override
public boolean removeRequest(IVRPRequest request) {
throw new UnsupportedOperationException("Not implemented yet");
}
/*
* (non-Javadoc)
*
* @see
* vroom.common.modeling.dataModel.IVRPInstance#getCost(vroom.common.modeling
* .dataModel.Node, vroom.common.modeling.dataModel.Node)
*/
@Override
public double getCost(INodeVisit origin, INodeVisit destination) {
return mCostHelper.getCost(origin, destination);
}
/*
* (non-Javadoc)
*
* @see
* vroom.common.modeling.dataModel.IVRPInstance#getCost(vroom.common.modeling
* .dataModel.Node, vroom.common.modeling.dataModel.Node,
* vroom.common.modeling.dataModel.Vehicle)
*/
@Override
public double getCost(INodeVisit origin, INodeVisit destination, Vehicle vehicle) {
return mCostHelper.getCost(origin, destination, vehicle);
}
/*
* (non-Javadoc)
*
* @see
* vroom.common.modeling.dataModel.IVRPInstance#getInsertionCost(vroom.
* common.modelling.dataModel.Node, vroom.common.modeling.dataModel.Node,
* vroom.common.modeling.dataModel.Node,
* vroom.common.modeling.dataModel.Vehicle)
*/
@Override
public double getInsertionCost(INodeVisit node, INodeVisit pred, INodeVisit succ,
Vehicle vehicle) {
return mCostHelper.getInsertionCost(node, pred, succ, vehicle);
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#getDepot(int)
*/
@Override
public Depot getDepot(int depotId) {
return mDepots.get(depotId);
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#getFleet()
*/
@Override
public Fleet<?> getFleet() {
return mFleet;
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#getDepotCount()
*/
@Override
public int getDepotCount() {
return mDepots.size();
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#getRequestCount()
*/
@Override
public abstract int getRequestCount();
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#getRequests()
*/
@Override
public abstract List<IVRPRequest> getRequests();
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#getRoutingProblem()
*/
@Override
public VehicleRoutingProblemDefinition getRoutingProblem() {
return mRoutingProblem;
}
/*
* (non-Javadoc)
*
* @see vroom.common.modeling.dataModel.IVRPInstance#getPlanningPeriod()
*/
@Override
public IPlanningPeriod getPlanningPeriod() {
return mPlanningPeriod;
}
@Override
public String toString() {
return String.format("%s (size:%s fleet size:%s)", getName(), getRequestCount(), getFleet()
.isUnlimited() ? "na" : getFleet().size());
}
}// end VRPInstance