mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
enhance TSPLIBReader to read most of the tsp instances
This commit is contained in:
parent
16085ab97a
commit
a0ac5b9935
1 changed files with 156 additions and 5 deletions
|
|
@ -19,10 +19,14 @@ package jsprit.instance.reader;
|
||||||
|
|
||||||
import jsprit.core.problem.Location;
|
import jsprit.core.problem.Location;
|
||||||
import jsprit.core.problem.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
|
import jsprit.core.problem.job.Job;
|
||||||
import jsprit.core.problem.job.Service;
|
import jsprit.core.problem.job.Service;
|
||||||
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
import jsprit.core.problem.vehicle.VehicleImpl;
|
import jsprit.core.problem.vehicle.VehicleImpl;
|
||||||
import jsprit.core.problem.vehicle.VehicleTypeImpl;
|
import jsprit.core.problem.vehicle.VehicleTypeImpl;
|
||||||
import jsprit.core.util.Coordinate;
|
import jsprit.core.util.Coordinate;
|
||||||
|
import jsprit.core.util.FastVehicleRoutingTransportCostsMatrix;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -33,6 +37,7 @@ public class TSPLIB95Reader {
|
||||||
|
|
||||||
private VehicleRoutingProblem.Builder vrpBuilder;
|
private VehicleRoutingProblem.Builder vrpBuilder;
|
||||||
|
|
||||||
|
|
||||||
public TSPLIB95Reader(VehicleRoutingProblem.Builder vrpBuilder) {
|
public TSPLIB95Reader(VehicleRoutingProblem.Builder vrpBuilder) {
|
||||||
this.vrpBuilder = vrpBuilder;
|
this.vrpBuilder = vrpBuilder;
|
||||||
}
|
}
|
||||||
|
|
@ -43,13 +48,18 @@ public class TSPLIB95Reader {
|
||||||
Coordinate[] coords = null;
|
Coordinate[] coords = null;
|
||||||
int[] demands = null;
|
int[] demands = null;
|
||||||
Integer capacity = null;
|
Integer capacity = null;
|
||||||
|
String edgeType = null;
|
||||||
|
String edgeWeightFormat = null;
|
||||||
List<Integer> depotIds = new ArrayList<Integer>();
|
List<Integer> depotIds = new ArrayList<Integer>();
|
||||||
boolean isCoordSection = false;
|
boolean isCoordSection = false;
|
||||||
boolean isDemandSection = false;
|
boolean isDemandSection = false;
|
||||||
boolean isDepotSection = false;
|
boolean isDepotSection = false;
|
||||||
|
boolean isEdgeWeightSection = false;
|
||||||
|
List<Double> edgeWeights = new ArrayList<Double>();
|
||||||
int dimensions = 0;
|
int dimensions = 0;
|
||||||
|
|
||||||
while( ( line = getLine(reader) ) != null ){
|
while( ( line = getLine(reader) ) != null ){
|
||||||
if(line.startsWith("EOF")){
|
if(line.startsWith("EOF") || line.contains("EOF")){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(line.startsWith("DIMENSION")){
|
if(line.startsWith("DIMENSION")){
|
||||||
|
|
@ -61,26 +71,53 @@ public class TSPLIB95Reader {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(line.startsWith("CAPACITY")){
|
if(line.startsWith("CAPACITY")){
|
||||||
String[] tokens = line.split(":");
|
String[] tokens = line.trim().split(":");
|
||||||
capacity = Integer.parseInt(tokens[1].trim());
|
capacity = Integer.parseInt(tokens[1].trim());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if(line.startsWith("EDGE_WEIGHT_TYPE")){
|
||||||
|
String[] tokens = line.trim().split(":");
|
||||||
|
edgeType = tokens[1].trim();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(line.startsWith("EDGE_WEIGHT_FORMAT")){
|
||||||
|
String[] tokens = line.trim().split(":");
|
||||||
|
edgeWeightFormat = tokens[1].trim();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if(line.startsWith("NODE_COORD_SECTION")){
|
if(line.startsWith("NODE_COORD_SECTION")){
|
||||||
isCoordSection = true;
|
isCoordSection = true;
|
||||||
isDemandSection = false;
|
isDemandSection = false;
|
||||||
isDepotSection = false;
|
isDepotSection = false;
|
||||||
|
isEdgeWeightSection = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(line.startsWith("DEMAND_SECTION")){
|
if(line.startsWith("DEMAND_SECTION")){
|
||||||
isDemandSection = true;
|
isDemandSection = true;
|
||||||
isCoordSection = false;
|
isCoordSection = false;
|
||||||
isDepotSection = false;
|
isDepotSection = false;
|
||||||
|
isEdgeWeightSection = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(line.startsWith("DEPOT_SECTION")){
|
if(line.startsWith("DEPOT_SECTION")){
|
||||||
isDepotSection = true;
|
isDepotSection = true;
|
||||||
isDemandSection = false;
|
isDemandSection = false;
|
||||||
isCoordSection = false;
|
isCoordSection = false;
|
||||||
|
isEdgeWeightSection = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(line.startsWith("EDGE_WEIGHT_SECTION")){
|
||||||
|
isDepotSection = false;
|
||||||
|
isCoordSection = false;
|
||||||
|
isDemandSection = false;
|
||||||
|
isEdgeWeightSection = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(line.startsWith("DISPLAY_DATA_SECTION")){
|
||||||
|
isDepotSection = false;
|
||||||
|
isCoordSection = true;
|
||||||
|
isDemandSection = false;
|
||||||
|
isEdgeWeightSection = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(isCoordSection){
|
if(isCoordSection){
|
||||||
|
|
@ -102,10 +139,16 @@ public class TSPLIB95Reader {
|
||||||
else{
|
else{
|
||||||
depotIds.add(Integer.parseInt(line));
|
depotIds.add(Integer.parseInt(line));
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(isEdgeWeightSection){
|
||||||
|
String[] tokens = line.trim().split("\\s+");
|
||||||
|
for (String s : tokens) edgeWeights.add(Double.parseDouble(s));
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(reader);
|
close(reader);
|
||||||
vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.INFINITE);
|
vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE);
|
||||||
for(Integer depotId : depotIds){
|
for(Integer depotId : depotIds){
|
||||||
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("typeId").addCapacityDimension(0,capacity).build();
|
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("typeId").addCapacityDimension(0,capacity).build();
|
||||||
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocationId(depotId.toString())
|
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocationId(depotId.toString())
|
||||||
|
|
@ -119,22 +162,130 @@ public class TSPLIB95Reader {
|
||||||
if(i==0) {
|
if(i==0) {
|
||||||
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("start")
|
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("start")
|
||||||
.setStartLocation(Location.Builder.newInstance().setId(id)
|
.setStartLocation(Location.Builder.newInstance().setId(id)
|
||||||
.setCoordinate(coords[i]).build())
|
.setCoordinate(coords[i]).setIndex(i).build())
|
||||||
|
|
||||||
.build();
|
.build();
|
||||||
vrpBuilder.addVehicle(vehicle);
|
vrpBuilder.addVehicle(vehicle);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Service service = Service.Builder.newInstance(id)
|
Service service = Service.Builder.newInstance(id)
|
||||||
.setLocation(Location.Builder.newInstance().setId(id).setCoordinate(coords[i]).build())
|
.setLocation(Location.Builder.newInstance().setId(id)
|
||||||
|
.setCoordinate(coords[i]).setIndex(i).build())
|
||||||
.addSizeDimension(0, demands[i]).build();
|
.addSizeDimension(0, demands[i]).build();
|
||||||
vrpBuilder.addJob(service);
|
vrpBuilder.addJob(service);
|
||||||
}
|
}
|
||||||
|
if(edgeType.equals("GEO")){
|
||||||
|
List<Location> locations = new ArrayList<Location>();
|
||||||
|
for(Vehicle v : vrpBuilder.getAddedVehicles()) locations.add(v.getStartLocation());
|
||||||
|
for(Job j : vrpBuilder.getAddedJobs()) locations.add(((Service)j).getLocation());
|
||||||
|
vrpBuilder.setRoutingCost(getGEOMatrix(locations));
|
||||||
|
}
|
||||||
|
else if(edgeType.equals("EXPLICIT")){
|
||||||
|
if(edgeWeightFormat.equals("UPPER_ROW")){
|
||||||
|
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(dimensions,true);
|
||||||
|
int fromIndex = 0;
|
||||||
|
int toIndex = 1;
|
||||||
|
for(int i=0;i<edgeWeights.size();i++){
|
||||||
|
if(toIndex == dimensions){
|
||||||
|
fromIndex++;
|
||||||
|
toIndex = fromIndex + 1;
|
||||||
|
}
|
||||||
|
matrixBuilder.addTransportDistance(fromIndex, toIndex, edgeWeights.get(i));
|
||||||
|
matrixBuilder.addTransportTime(fromIndex,toIndex,edgeWeights.get(i));
|
||||||
|
toIndex++;
|
||||||
|
}
|
||||||
|
vrpBuilder.setRoutingCost(matrixBuilder.build());
|
||||||
|
}
|
||||||
|
else if(edgeWeightFormat.equals("UPPER_DIAG_ROW")){
|
||||||
|
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(dimensions,true);
|
||||||
|
int fromIndex = 0;
|
||||||
|
int toIndex = 0;
|
||||||
|
for(int i=0;i<edgeWeights.size();i++){
|
||||||
|
if(toIndex == dimensions){
|
||||||
|
fromIndex++;
|
||||||
|
toIndex = fromIndex;
|
||||||
|
}
|
||||||
|
matrixBuilder.addTransportDistance(fromIndex,toIndex,edgeWeights.get(i));
|
||||||
|
matrixBuilder.addTransportTime(fromIndex,toIndex,edgeWeights.get(i));
|
||||||
|
toIndex++;
|
||||||
|
}
|
||||||
|
vrpBuilder.setRoutingCost(matrixBuilder.build());
|
||||||
|
}
|
||||||
|
else if(edgeWeightFormat.equals("LOWER_DIAG_ROW")){
|
||||||
|
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(dimensions,true);
|
||||||
|
int fromIndex = 0;
|
||||||
|
int toIndex = 0;
|
||||||
|
for(int i=0;i<edgeWeights.size();i++){
|
||||||
|
if(toIndex > fromIndex){
|
||||||
|
fromIndex++;
|
||||||
|
toIndex = 0;
|
||||||
|
}
|
||||||
|
matrixBuilder.addTransportDistance(fromIndex,toIndex,edgeWeights.get(i));
|
||||||
|
matrixBuilder.addTransportTime(fromIndex,toIndex,edgeWeights.get(i));
|
||||||
|
toIndex++;
|
||||||
|
}
|
||||||
|
vrpBuilder.setRoutingCost(matrixBuilder.build());
|
||||||
|
}
|
||||||
|
else if(edgeWeightFormat.equals("FULL_MATRIX")){
|
||||||
|
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(dimensions,true);
|
||||||
|
int fromIndex = 0;
|
||||||
|
int toIndex = 0;
|
||||||
|
for(int i=0;i<edgeWeights.size();i++){
|
||||||
|
if(toIndex == dimensions){
|
||||||
|
fromIndex++;
|
||||||
|
toIndex = 0;
|
||||||
|
}
|
||||||
|
matrixBuilder.addTransportDistance(fromIndex,toIndex,edgeWeights.get(i));
|
||||||
|
matrixBuilder.addTransportTime(fromIndex,toIndex,edgeWeights.get(i));
|
||||||
|
toIndex++;
|
||||||
|
}
|
||||||
|
vrpBuilder.setRoutingCost(matrixBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private VehicleRoutingTransportCosts getGEOMatrix(List<Location> noLocations) {
|
||||||
|
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(noLocations.size(),true);
|
||||||
|
for(Location i : noLocations){
|
||||||
|
for(Location j : noLocations){
|
||||||
|
matrixBuilder.addTransportDistance(i.getIndex(),j.getIndex(),getDistance(i,j));
|
||||||
|
matrixBuilder.addTransportTime(i.getIndex(), j.getIndex(), getDistance(i, j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matrixBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getDistance(Location from, Location to) {
|
||||||
|
double longitude_from = getLongitude(from);
|
||||||
|
double longitude_to = getLongitude(to);
|
||||||
|
double latitude_from = getLatitude(from);
|
||||||
|
double latitude_to = getLatitude(to);
|
||||||
|
double q1 = Math.cos( longitude_from - longitude_to);
|
||||||
|
double q2 = Math.cos( latitude_from - latitude_to);
|
||||||
|
double q3 = Math.cos( latitude_from + latitude_to);
|
||||||
|
return 6378.388 * Math.acos( .5 * ( ( 1. + q1 ) * q2 - ( 1. - q1 ) * q3 ) ) + 1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getLatitude(Location loc) {
|
||||||
|
int deg = (int) loc.getCoordinate().getX();
|
||||||
|
double min = loc.getCoordinate().getX() - deg;
|
||||||
|
return Math.PI * (deg + 5. * min / 3.) / 180.;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getLongitude(Location loc) {
|
||||||
|
int deg = (int) loc.getCoordinate().getY();
|
||||||
|
double min = loc.getCoordinate().getY() - deg;
|
||||||
|
return Math.PI * (deg + 5. * min / 3.) / 180.;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void close(BufferedReader reader) {
|
private void close(BufferedReader reader) {
|
||||||
try {
|
try {
|
||||||
reader.close();
|
reader.close();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue