/******************************************************************************* * Copyright (C) 2014 Stefan Schroeder * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ 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; import java.util.HashMap; import java.util.List; import java.util.Map; public class TSPLIB95Reader { private VehicleRoutingProblem.Builder vrpBuilder; public TSPLIB95Reader(VehicleRoutingProblem.Builder vrpBuilder) { this.vrpBuilder = vrpBuilder; } public void read(String filename){ BufferedReader reader = getBufferedReader(filename); String line; 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; int coordIndex = 0; Map indexMap = new HashMap(); while( ( line = getLine(reader) ) != null ){ if(line.startsWith("EOF") || line.contains("EOF")){ break; } if(line.startsWith("DIMENSION")){ String[] tokens = line.split(":"); String dim = tokens[1].trim(); dimensions = Integer.parseInt(dim); coords = new Coordinate[dimensions]; demands = new int[dimensions]; continue; } if(line.startsWith("CAPACITY")){ 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){ if(coords == null) throw new IllegalStateException("DIMENSION tag missing"); String[] tokens = line.trim().split("\\s+"); Integer id = Integer.parseInt(tokens[0]); coords[coordIndex] = Coordinate.newInstance(Double.parseDouble(tokens[1]), Double.parseDouble(tokens[2])); indexMap.put(id,coordIndex); coordIndex++; continue; } if(isDemandSection){ if(demands == null) throw new IllegalStateException("DIMENSION tag missing"); String[] tokens = line.trim().split("\\s+"); Integer id = Integer.parseInt(tokens[0]); int index = indexMap.get(id); demands[index] = Integer.parseInt(tokens[1]); continue; } if(isDepotSection){ if(line.equals("-1")){ isDepotSection = false; } 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.FINITE); for(Integer depotId : depotIds){ VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0,capacity).build(); VehicleImpl vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocationId(depotId.toString()) .setStartLocationCoordinate(coords[depotId - 1]).setType(type).build(); vrpBuilder.addVehicle(vehicle); } for (Integer id_ : indexMap.keySet()) { String id = id_.toString(); int index = indexMap.get(id_); if(depotIds.isEmpty()){ if(index == 0) { VehicleImpl vehicle = VehicleImpl.Builder.newInstance("traveling_salesman") .setStartLocation(Location.Builder.newInstance().setId(id) .setCoordinate(coords[index]).setIndex(index).build()) .build(); vrpBuilder.addVehicle(vehicle); continue; } } Service service = Service.Builder.newInstance(id) .setLocation(Location.Builder.newInstance().setId(id) .setCoordinate(coords[index]).setIndex(index).build()) .addSizeDimension(0, demands[index]).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,false); 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(); } catch (IOException e) { e.printStackTrace(); } ; } private String getLine(BufferedReader reader) { String s = null; try { s = reader.readLine(); } catch (IOException e) { e.printStackTrace(); } return s; } private BufferedReader getBufferedReader(String filename) { BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new FileReader(new File(filename))); } catch (FileNotFoundException e) { e.printStackTrace(); } return bufferedReader; } }