| Home | OR-Objects | Tutorials | Prev | Next |
In this tutorial you will extend the problem introduced in Tutorial-4.
The supply service located at the depot now owns a fleet of helicopters.
The problem is to design delivery routes to serve all customers while minimizing
the flight distance and not exceeding the load capacity or the range of
the helicopters. A red dot (
)
marks a customer demanding a 300 kilogram payload. A yellow (
)
payload weighs 200 kilograms and a green (
)
weighs 100 kilograms. The black dot (
)
marks the depot. This tutorial also introduces geometric transform objects
which are used to convert between the geographic, map and screen coordinate
systems.
For simplicity, the material covered in Tutorial-4
and most of the applet details will be skipped. If you would like to see
all the details then view the complete source.
public void
initTutorial()
{
.
.
newAlgorithm(constructType, subalgorithmType, improveType);
geoRange = new drasys.or.geom.geo.Range(160, -6.5, 162, -5);
lonDist = new UniformDistribution(geoRange.west(), geoRange.east(), 123);
latDist = new UniformDistribution(geoRange.south(), geoRange.north(), 321);
loadDist = new DiscreteUniformDistribution(100,100,3);
setProjection("Mercator");
}
public void setProjection(String projectionStr)
{
if(projectionStr.equals("Mercator"))
projection = new Mercator(geoRange);
else if(projectionStr.equals("Albers"))
projection = new Albers(geoRange);
else if(projectionStr.equals("Lambert Conic"))
projection = new LambertConic(geoRange);
xyRange = projection.forward(geoRange);
PointI xyLowerLeft = projection.forward(geoRange.southwest());
PointI xyUpperRight = projection.forward(geoRange.northeast());
PointI screenLowerLeft = new Point(10, 150);
PointI screenUpperRight = new Point(240, 10);
screenTransform = new Transform(
xyLowerLeft, xyUpperRight,
screenLowerLeft, screenUpperRight);
newCustomers(sizeOfStops);
}
public void
mouseClick(int x, int y)
{
PointI projectedPoint = screenTransform.inverse(new Point(x,y));
projectedPoint = xyRange.bound(projectedPoint);
drasys.or.geom.geo.PointI geoPoint = projection.inverse(projectedPoint);
String lon = (""+(geoPoint.longitude()+5.0E-7)).substring(0,10);
String lat = (""+(geoPoint.latitude()-5.0E-7)).substring(0,9);
messageLabel.setText("Lon,Lat = "+lon+", "+lat);
}
class Customer
extends Point
implements DoubleI
{
double load;
PointI screenPoint;
Customer(double ld, PointI projectedPt, PointI screenPt)
{
super(projectedPt);
load = ld;
screenPoint = screenPt;
}
public double doubleValue(){return load;}
}
public void newCustomers(int n)
{
customers = new Customer[n+1];
PointGraph pointGraph = new PointGraph();
drasys.or.geom.geo.PointI geoPoint;
PointI xyPoint, screenPoint;
Object key = "Depot";
double load = 0;
for(int i=0; i<=n;){
geoPoint = new drasys.or.geom.geo.Point(
lonDist.getRandomScaler(),
latDist.getRandomScaler());
xyPoint = projection.forward(geoPoint);
if(!xyRange.includes(xyPoint)) continue;
screenPoint = screenTransform.forward(xyPoint);
customers[i] = new Customer(load, xyPoint, screenPoint);
pointGraph.addVertex(key, customers[i]);
key = new Integer(i);
load = loadDist.getRandomScaler();
i++;
}
graph = new MatrixGraph(pointGraph, null);
}
The Composite class is a generic implementation of a composite VRP algorithm. It is passed the construction and improvement algorithms when it is created. If null is passed for the improvement algorithm then only the construction algorithm will be used.
Composite vrp;
public void
newAlgorithm(String constructStr, String subalgorithmStr, String improveStr)
{
drasys.or.graph.tsp.ImproveI subalgorithm = null;
if(subalgorithmStr.equals("None"))
subalgorithm = null;
else if(subalgorithmStr.equals("2-Opt"))
subalgorithm = new drasys.or.graph.tsp.TwoOpt();
else if(subalgorithmStr.equals("3-Opt"))
subalgorithm = new drasys.or.graph.tsp.ThreeOpt();
else if(subalgorithmStr.equals("US-5"))
subalgorithm = new drasys.or.graph.tsp.Us(5);
ConstructI construct = null;
if(constructStr.equals("Clarke&Wright - savings list"))
construct = new ClarkeWright(iterations,strength,subalgorithm);
else if(constructStr.equals("Gillett&Miller - polar sweep"))
construct = new GillettMiller(iterations,strength,subalgorithm);
else if(constructStr.equals("Best Of Above")){
BestOf bestOf = new BestOf();
bestOf.addConstruct(new ClarkeWright(iterations,strength,subalgorithm));
bestOf.addConstruct(new GillettMiller(iterations,strength,subalgorithm));
construct = bestOf;
}
ImproveI improve = null;
if(improveStr.equals("None"))
improve = null;
else if(improveStr.equals("Improve With Tsp: 2-Opt"))
improve = new ImproveWithTSP(new drasys.or.graph.tsp.TwoOpt());
else if(improveStr.equals("Improve With Tsp: 3-Opt"))
improve = new ImproveWithTSP(new drasys.or.graph.tsp.ThreeOpt());
else if(improveStr.equals("Improve With Tsp: US-5"))
improve = new ImproveWithTSP(new drasys.or.graph.tsp.Us(5));
vrp = new Composite(construct, improve);
vrp.setCostConstraint(rangeConstraint*1000);
vrp.setCapacityConstraint(capacityConstraint);
}
public Vector[]
buildSolution(GraphI graph)
throws VertexNotFoundException, SolutionNotFoundException
{
vrp.setGraph(graph);
if(tourType.equals("Closed"))
vrp.constructClosedTours("Depot");
else if(tourType.equals("Inbound"))
vrp.constructInboundTours("Depot");
else if(tourType.equals("Outbound")){
vrp.constructOutboundTours("Depot");
}
return vrp.getTours();
}
public void
paintTours(Vector[] tours)
throws SolutionNotFoundException
{
int meters = 0;
Graphics g = this.getGraphics();
g.setColor(Color.blue);
for(int i=0; i<tours.length; i++){
Enumeration e=tours[i].elements();
e.nextElement(); // Skip Vertex
while(e.hasMoreElements()){
EdgeI edge = (EdgeI)e.nextElement();
Customer customer1 = (Customer)edge.getToVertex().getValue();
Customer customer2 = (Customer)edge.getFromVertex().getValue();
meters += customer1.distanceTo(customer2);
int x1 = (int)customer1.screenPoint.x();
int y1 = (int)customer1.screenPoint.y();
int x2 = (int)customer2.screenPoint.x();
int y2 = (int)customer2.screenPoint.y();
g.drawLine(x1, y1, x2, y2);
e.nextElement(); // Skip Vertex
}
}
String msg = "Vehicles - "+tours.length+", ";
msg += "Distance(Km) - "+meters/1000;
messageLabel.setText(msg);
}
![]() |
|
![]() |