diff --git a/jsprit-instances/src/main/java/jsprit/instance/reader/TSPLIB95Reader.java b/jsprit-instances/src/main/java/jsprit/instance/reader/TSPLIB95Reader.java index b667fb09..c18ae829 100644 --- a/jsprit-instances/src/main/java/jsprit/instance/reader/TSPLIB95Reader.java +++ b/jsprit-instances/src/main/java/jsprit/instance/reader/TSPLIB95Reader.java @@ -19,10 +19,14 @@ package jsprit.instance.reader; import jsprit.core.problem.Location; 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.vehicle.Vehicle; import jsprit.core.problem.vehicle.VehicleImpl; import jsprit.core.problem.vehicle.VehicleTypeImpl; import jsprit.core.util.Coordinate; +import jsprit.core.util.FastVehicleRoutingTransportCostsMatrix; import java.io.*; import java.util.ArrayList; @@ -33,6 +37,7 @@ public class TSPLIB95Reader { private VehicleRoutingProblem.Builder vrpBuilder; + public TSPLIB95Reader(VehicleRoutingProblem.Builder vrpBuilder) { this.vrpBuilder = vrpBuilder; } @@ -43,13 +48,18 @@ public class TSPLIB95Reader { Coordinate[] coords = null; int[] demands = null; Integer capacity = null; + String edgeType = null; + String edgeWeightFormat = null; List depotIds = new ArrayList(); boolean isCoordSection = false; boolean isDemandSection = false; boolean isDepotSection = false; + boolean isEdgeWeightSection = false; + List edgeWeights = new ArrayList(); int dimensions = 0; + while( ( line = getLine(reader) ) != null ){ - if(line.startsWith("EOF")){ + if(line.startsWith("EOF") || line.contains("EOF")){ break; } if(line.startsWith("DIMENSION")){ @@ -61,26 +71,53 @@ public class TSPLIB95Reader { continue; } if(line.startsWith("CAPACITY")){ - String[] tokens = line.split(":"); + String[] tokens = line.trim().split(":"); capacity = Integer.parseInt(tokens[1].trim()); 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")){ isCoordSection = true; isDemandSection = false; isDepotSection = false; + isEdgeWeightSection = false; continue; } if(line.startsWith("DEMAND_SECTION")){ isDemandSection = true; isCoordSection = false; isDepotSection = false; + isEdgeWeightSection = false; continue; } if(line.startsWith("DEPOT_SECTION")){ isDepotSection = true; isDemandSection = 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; } if(isCoordSection){ @@ -102,10 +139,16 @@ public class TSPLIB95Reader { else{ 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); - vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.INFINITE); + vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE); for(Integer depotId : depotIds){ VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("typeId").addCapacityDimension(0,capacity).build(); VehicleImpl vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocationId(depotId.toString()) @@ -119,22 +162,130 @@ public class TSPLIB95Reader { if(i==0) { VehicleImpl vehicle = VehicleImpl.Builder.newInstance("start") .setStartLocation(Location.Builder.newInstance().setId(id) - .setCoordinate(coords[i]).build()) + .setCoordinate(coords[i]).setIndex(i).build()) + .build(); vrpBuilder.addVehicle(vehicle); continue; } } 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(); vrpBuilder.addJob(service); } + if(edgeType.equals("GEO")){ + List locations = new ArrayList(); + 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 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 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) { try { reader.close();