1
0
Fork 0
mirror of https://github.com/graphhopper/jsprit.git synced 2020-01-24 07:45:05 +01:00

prepare release 1.5

This commit is contained in:
oblonski 2014-12-12 10:55:56 +01:00
parent 9938a6a123
commit 1458b03be7
13 changed files with 253 additions and 1502 deletions

View file

@ -1,5 +1,13 @@
Change-log Change-log
========== ==========
**v1.5** @ 2014-12-12
<b>! Break change !</b>
(only if you already build your algorithm from scratch since strategies now need to have unique ids)
new features: see [Whats new](https://github.com/jsprit/jsprit/blob/master/WHATS_NEW.md)
- [detailed changelog](https://github.com/jsprit/misc-rep/blob/master/changelog_1.4.2_to_1.5.txt)
**v1.4.2** @ 2014-10-14 **v1.4.2** @ 2014-10-14
new feature: core.analysis.SolutionAnalyser new feature: core.analysis.SolutionAnalyser

View file

@ -1,5 +1,57 @@
WHATS NEW WHATS NEW
========== ==========
------------------------------
<b>2014-12-14</b> new release **v1.5**
jsprit made a big step towards analysing and designing your own ruin and recreation strategies.
First, it is now possible to record and view each and every algorithm step which allows you to visualize the search, e.g. neighborhoods
and the emergence of new structures. It is as easy as importing the corresponding classes from jsprit-analysis and coding the following lines:
<pre><code>AlgorithmEventsRecorder recorder = new AlgorithmEventsRecorder(vrp,"output/events.dgs.gz");
recorder.setRecordingRange(0,100); //lets you specify the iterations you want to record
vehicleRoutingAlgorithm.addListener(recorder);
</code></pre>
The output consists of many redundant stuff, thus it is best suited for zipping. If you do not want to zip, omit 'gz'. To view
the events, do the following after running the algorithm:
<pre><code>AlgorithmEventsViewer viewer = new AlgorithmEventsViewer();
viewer.setRuinDelay(8); //lets you slow down ruin vis (in ms)
viewer.setRecreationDelay(4); //lets you slow down recreation vis (in ms)
viewer.display("output/events.dgs.gz");
</code></pre>
It is not only beautiful, but it allows you to immediately analyze your own strategies which brings us to the second improvement.
With <code>AbstractRuinStrategy</code> and <code>AbstractInsertionStrategy</code> it is easy to implement your own strategies. The
abstract classes do all the non-intuitive stuff (such as informing listeners that a job has been inserted etc.) for you and you can focus on your strategies.
With the <code>PrettyAlgorithmBuilder</code> you can finally build your algorithm, basically just by adding your strategies. All
other things that needs to be done to wire up the components of your algorithm does the builder for you.
A third improvement in this regards is that you can switch on and off certain strategies or just change their weights in the course of the search (which allow you to adapt your strategies e.g.
according to its recorded success). You do that by informing the strategy manager to change a strategy's weight much like this:
<pre><code>vra.getSearchStrategyManager().informStrategyWeightChanged(strategyId, 0.); //which is basically switching off the strategy
</code></pre>
This comes with two changes. Strategy probabilities are now strategy weights (and do not need to be smaller than 1) and the probability of choosing a strategy is simply a function of
the strategy's weight and all other weights (i.e. prob(i) = weight(i) / sumOfAllWeights). The second change is that strategies
now require a unique id. Latter might break your code if (and only if) you already build your algorithm from scratch.
Another new feature which is worth to mention is a new InsertionStrategy called [RegretInsertion](https://github.com/jsprit/jsprit/blob/master/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/RegretInsertion.java). It is much less myopic than BestInsertion since it scores all jobs before inserting them.
The one with the highest score will be inserted first. The scoring function is based on opportunity costs, i.e. it compares the best insertion alternative with the second best.
If the difference between both is high, the job will be preferred, i.e. it will be inserted earlier than later. The scoring function comes with default parameter. However, you
can replace params or overwrite the whole scoring function with your own (which currently means that you need to build your algorithm from scratch).
Note, that this strategy will have a significant impact on the computational performance. If you run it with the same no. of iterations as you run BestInsertion, you are
likely to wait forever. However, since it is a bit more 'intelligent' you do not need as many iterations. It is also recommended to use the [concurrent mode](https://github.com/jsprit/jsprit/blob/master/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/RegretInsertionConcurrent.java) since RegretInsertion
is best suited for concurrent calculation.
Last, you can use spherical coordinates (i.e. longitude and latitude) since [GreatCircleCosts](https://github.com/jsprit/jsprit/blob/master/jsprit-core/src/main/java/jsprit/core/util/GreatCircleCosts.java) knows how to calculate great circle distance and time. It approximates distance
based on the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula). If you want to approximate real networks, you can set a detour factor and a speed value.
------------------------------ ------------------------------
<b>2014-10-14</b> new release **v1.4.2** <b>2014-10-14</b> new release **v1.4.2**

View file

@ -57,13 +57,6 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
private boolean renderShipments = false; private boolean renderShipments = false;
public static void writeSolution(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution, File outfile){
AlgorithmEventsRecorder rec = new AlgorithmEventsRecorder(vrp,outfile);
rec.initialiseGraph(vrp);
rec.addRoutes(solution.getRoutes());
rec.finish();
}
public static final int BEFORE_RUIN_RENDER_SOLUTION = 2; public static final int BEFORE_RUIN_RENDER_SOLUTION = 2;
public static final int RUIN = 0; public static final int RUIN = 0;
@ -90,10 +83,11 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
private VehicleRoutingProblem vrp; private VehicleRoutingProblem vrp;
public AlgorithmEventsRecorder(VehicleRoutingProblem vrp, File dgsFile) { public AlgorithmEventsRecorder(VehicleRoutingProblem vrp, String dgsFileLocation) {
this.vrp = vrp; this.vrp = vrp;
graph = new MultiGraph("g"); graph = new MultiGraph("g");
try { try {
File dgsFile = new File(dgsFileLocation);
fos = new FileOutputStream(dgsFile); fos = new FileOutputStream(dgsFile);
fileSink = new FileSinkDGS(); fileSink = new FileSinkDGS();
if(dgsFile.getName().endsWith("gz")){ if(dgsFile.getName().endsWith("gz")){
@ -110,9 +104,9 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
initialiseGraph(vrp); initialiseGraph(vrp);
} }
public AlgorithmEventsRecorder(VehicleRoutingProblem vrp, File dgsFile, boolean renderShipments) { public AlgorithmEventsRecorder(VehicleRoutingProblem vrp, String dgsFileLocation, boolean renderShipments) {
this.renderShipments = renderShipments; this.renderShipments = renderShipments;
new AlgorithmEventsRecorder(vrp,dgsFile); new AlgorithmEventsRecorder(vrp, dgsFileLocation);
} }
public void setRecordingRange(int startIteration, int endIteration){ public void setRecordingRange(int startIteration, int endIteration){

View file

@ -1,4 +1,21 @@
<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ 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 <http://www.gnu.org/licenses/>.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent> <parent>
<groupId>jsprit</groupId> <groupId>jsprit</groupId>
@ -65,11 +82,6 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.3</version>
</dependency>
</dependencies> </dependencies>

View file

@ -1,182 +0,0 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.problem.io;
/**
* Created by stefan on 03.11.14.
*/
public class JsonConstants {
public static final String PROBLEM = "vrp";
public static final String SOLUTION = "solution";
public static final String SERVICES = "services";
public static final String FLEET = "fleet_size";
public static final String VEHICLES = "vehicles";
public static final String VEHICLE_TYPES = "vehicle_types";
public static final String META = "meta-info";
public static class MetaInfo {
public static final String DISTANCE_UNIT = "distance-unit";
public static final String TIME_UNIT = "time-unit";
}
public static class Solution {
public static final String COSTS = "costs";
public static final String DISTANCE = "distance";
public static final String TIME = "time";
public static final String ROUTES = "routes";
public static final String NO_ROUTES = "no_routes";
public static final String NO_UNASSIGNED = "no_unassigned_jobs";
public static final String FIXED_COSTS = "fixed_costs";
public static final String VARIABLE_COSTS = "variable_costs";
public static class Route {
public static final String COSTS = "costs";
public static final String DISTANCE = "distance";
public static final String TIME = "time";
public static final String VEHICLE_ID = "vehicle_id";
public static final String START_TIME = "start_time";
public static final String END_TIME = "end_time";
public static final String ACTIVITY = "act";
public static final String FIXED_COSTS = "fixed_costs";
public static final String VARIABLE_COSTS = "variable_costs";
public static final String NO_ACTIVITIES = "no_activities";
public static final String UNASSIGNED = "unassigned_jobs";
public static class Activity {
public static final String TYPE = "type";
public static final String SERVICE_ID = "job_id";
public static final String ARR_TIME = "arr_time";
public static final String END_TIME = "end_time";
}
}
}
public static class Address {
public static String ID = "id";
public static String LON = "lon";
public static String LAT = "lat";
}
public static class TimeWindow {
public static final String START = "start";
public static final String END = "end";
}
public static class Job {
public static final String SIZE = "size";
public static final String ADDRESS = "address";
public static final String ID = "id";
public static final String SERVICE_DURATION = "service_duration";
public static final String NAME = "name";
public static final String SKILLS = "required_skills";
public static final String TIME_WINDOW = "time_window";
public static final String TYPE = "type";
public static final String PICKUP = "pickup";
public static final String DELIVERY = "delivery";
public static final String SERVICE = "service";
}
public static class Vehicle {
public static final String ID = "id";
public static final String START_ADDRESS = "start_address";
public static final String END_ADDRESS = "end_address";
public static final String EARLIEST_START = "earliest_start";
public static final String LATEST_END = "latest_end";
public static final String SKILLS = "skills";
public static final String CAPACITY = "capacity";
public static final String TYPE_ID = "type_id";
public static final String RETURN_TO_DEPOT = "return_to_depot";
public static class Type {
public static final String ID = "id";
public static final String CAPACITY = "capacity";
public static final String FIXED_COSTS = "fixed_costs";
public static final String DISTANCE = "distance_dependent_costs";
public static final String TIME = "time_dependent_costs";
}
}
}

View file

@ -1,277 +0,0 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.problem.io;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Delivery;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl;
import jsprit.core.problem.vehicle.VehicleType;
import jsprit.core.problem.vehicle.VehicleTypeImpl;
import jsprit.core.util.Coordinate;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Reads vehicle routing problem from json file.
*/
public class VrpJsonReader {
private final VehicleRoutingProblem.Builder vrpBuilder;
private final Map<String, VehicleType> vehicle_type_map = new HashMap<String,VehicleType>();
public VrpJsonReader(VehicleRoutingProblem.Builder vrpBuilder) {
this.vrpBuilder = vrpBuilder;
}
/**
* Reads json file.
*
* @param jsonFile to be read
* @throws java.lang.IllegalStateException if there is a service without id and proper location spec OR
* if there is a vehicle without id and proper location spec OR if there is a vehicle type without id
*/
public void read(File jsonFile){
JsonNode root = buildTree_and_getRoot_fromFile(jsonFile);
parse(root);
}
public void read(String jsonContent){
JsonNode root = buildTree_and_getRoot_fromContent(jsonContent);
parse(root);
}
public void parse(JsonNode problemRoot) {
setFleetSize(problemRoot);
parse_and_map_vehicle_types(problemRoot);
parse_vehicles(problemRoot);
parse_services(problemRoot);
}
private JsonNode buildTree_and_getRoot_fromContent(String jsonContent){
JsonNode node = null;
try {
ObjectMapper objectMapper = new ObjectMapper();
node = objectMapper.readTree(jsonContent).path(JsonConstants.PROBLEM);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
return node;
}
private JsonNode buildTree_and_getRoot_fromFile(File jsonFile){
JsonNode node = null;
try {
ObjectMapper objectMapper = new ObjectMapper();
node = objectMapper.readTree(new FileReader(jsonFile)).path(JsonConstants.PROBLEM);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
return node;
}
/**
* @param root node
* @throws java.lang.IllegalStateException if service id is missing OR neither location id nor location coordinate are set
*/
private void parse_services(JsonNode root) {
JsonNode services = root.path(JsonConstants.SERVICES);
for(JsonNode serviceNode : services){
//type
JsonNode typeNode = serviceNode.path(JsonConstants.Job.TYPE);
//service id
JsonNode jobIdNode = serviceNode.path(JsonConstants.Job.ID);
if(jobIdNode.isMissingNode()) throw new IllegalStateException("service-id is missing");
Service.Builder serviceBuilder;
if(typeNode.isMissingNode()) serviceBuilder = Service.Builder.newInstance(jobIdNode.asText());
else if(typeNode.asText().equals(JsonConstants.Job.SERVICE)) serviceBuilder = Service.Builder.newInstance(jobIdNode.asText());
else if(typeNode.asText().equals(JsonConstants.Job.PICKUP)) serviceBuilder = Pickup.Builder.newInstance(jobIdNode.asText());
else if(typeNode.asText().equals(JsonConstants.Job.DELIVERY)) serviceBuilder = Delivery.Builder.newInstance(jobIdNode.asText());
else throw new IllegalStateException("type of service ("+typeNode.asText()+") is not supported");
//service address
JsonNode addressIdNode = serviceNode.path(JsonConstants.Job.ADDRESS).path(JsonConstants.Address.ID);
boolean either_locationId_or_coord = false;
if(!addressIdNode.isMissingNode()){
serviceBuilder.setLocationId(addressIdNode.asText());
either_locationId_or_coord = true;
}
{
JsonNode lonNode = serviceNode.path(JsonConstants.Job.ADDRESS).path(JsonConstants.Address.LON);
JsonNode latNode = serviceNode.path(JsonConstants.Job.ADDRESS).path(JsonConstants.Address.LAT);
if (!lonNode.isMissingNode() && !latNode.isMissingNode()) {
serviceBuilder.setCoord(Coordinate.newInstance(lonNode.asDouble(), latNode.asDouble()));
either_locationId_or_coord = true;
}
}
if(!either_locationId_or_coord) throw new IllegalStateException("location missing. either locationId or locationCoordinate is required");
//service name
JsonNode nameNode = serviceNode.path(JsonConstants.Job.NAME);
if(!nameNode.isMissingNode()) serviceBuilder.setName(nameNode.asText());
//service duration
serviceBuilder.setServiceTime(serviceNode.path(JsonConstants.Job.SERVICE_DURATION).asDouble());
//service tw
JsonNode start_tw_node = serviceNode.path(JsonConstants.Job.TIME_WINDOW).path(JsonConstants.TimeWindow.START);
JsonNode end_tw_node = serviceNode.path(JsonConstants.Job.TIME_WINDOW).path(JsonConstants.TimeWindow.END);
if(!start_tw_node.isMissingNode() && !end_tw_node.isMissingNode()){
serviceBuilder.setTimeWindow(TimeWindow.newInstance(start_tw_node.asDouble(),end_tw_node.asDouble()));
}
//service size
JsonNode sizeNode = serviceNode.path(JsonConstants.Job.SIZE);
int size_index = 0;
for(JsonNode sizeValNode : sizeNode){
int size_value = sizeValNode.intValue();
serviceBuilder.addSizeDimension(size_index,size_value);
size_index++;
}
//service skills
JsonNode reqSkills = serviceNode.path(JsonConstants.Job.SKILLS);
for(JsonNode skillNode : reqSkills){
serviceBuilder.addRequiredSkill(skillNode.asText());
}
//add service
vrpBuilder.addJob(serviceBuilder.build());
}
}
/**
* @param root node
* @throws java.lang.IllegalStateException if vehicle id is missing OR if neither start location id nor start location
* coordinate are set
*/
private void parse_vehicles(JsonNode root) {
JsonNode vehicles = root.path(JsonConstants.VEHICLES);
for(JsonNode vehicleNode : vehicles){
//vehicle id
JsonNode vehicle_id_node = vehicleNode.path(JsonConstants.Vehicle.ID);
if(vehicle_id_node.isMissingNode()) throw new IllegalStateException("vehicle id missing");
VehicleImpl.Builder vehicleBuilder = VehicleImpl.Builder.newInstance(vehicle_id_node.asText());
//vehicle type
VehicleType type = vehicle_type_map.get(vehicleNode.path(JsonConstants.Vehicle.TYPE_ID).asText());
vehicleBuilder.setType(type);
//earliest start
JsonNode earliestStartNode = vehicleNode.path(JsonConstants.Vehicle.EARLIEST_START);
if(!earliestStartNode.isMissingNode()) vehicleBuilder.setEarliestStart(earliestStartNode.asDouble());
//latest end
JsonNode latestEndNode = vehicleNode.path(JsonConstants.Vehicle.LATEST_END);
if(!latestEndNode.isMissingNode()) vehicleBuilder.setLatestArrival(latestEndNode.asDouble());
//start
//location id
boolean either_id_or_coord = false;
JsonNode startAddressId = vehicleNode.path(JsonConstants.Vehicle.START_ADDRESS).path(JsonConstants.Address.ID);
if(!startAddressId.isMissingNode()){
vehicleBuilder.setStartLocationId(startAddressId.asText());
either_id_or_coord = true;
}
//location coordinate
{
JsonNode lonNode = vehicleNode.path(JsonConstants.Vehicle.START_ADDRESS).path(JsonConstants.Address.LON);
JsonNode latNode = vehicleNode.path(JsonConstants.Vehicle.START_ADDRESS).path(JsonConstants.Address.LAT);
if (!lonNode.isMissingNode() && !latNode.isMissingNode()) {
vehicleBuilder.setStartLocationCoordinate(Coordinate.newInstance(lonNode.asDouble(), latNode.asDouble()));
either_id_or_coord = true;
}
}
if(!either_id_or_coord) throw new IllegalStateException("start location of vehicle missing. either id or coordinate required");
//end
//location id
JsonNode endAddressId = vehicleNode.path(JsonConstants.Vehicle.END_ADDRESS).path(JsonConstants.Address.ID);
if(!endAddressId.isMissingNode()){
if(!startAddressId.asText().equals(endAddressId.asText())){
vehicleBuilder.setEndLocationId(endAddressId.asText());
}
}
//location coordinate
{
JsonNode lonNode = vehicleNode.path(JsonConstants.Vehicle.END_ADDRESS).path(JsonConstants.Address.LON);
JsonNode latNode = vehicleNode.path(JsonConstants.Vehicle.END_ADDRESS).path(JsonConstants.Address.LAT);
if (!lonNode.isMissingNode() && !latNode.isMissingNode()) {
vehicleBuilder.setEndLocationCoordinate(Coordinate.newInstance(lonNode.asDouble(), latNode.asDouble()));
}
}
//skills
JsonNode skillsNode = vehicleNode.path(JsonConstants.Vehicle.SKILLS);
for(JsonNode skillNode : skillsNode){
String skill = skillNode.asText();
vehicleBuilder.addSkill(skill);
}
vrpBuilder.addVehicle(vehicleBuilder.build());
}
}
/**
* @param root node
* @throws java.lang.IllegalStateException if type id is missing
*/
private void parse_and_map_vehicle_types(JsonNode root) {
JsonNode types = root.path(JsonConstants.VEHICLE_TYPES);
for(JsonNode typeNode : types){
JsonNode typeIdNode = typeNode.path(JsonConstants.Vehicle.Type.ID);
if(typeIdNode.isMissingNode()) throw new IllegalStateException("type id missing");
VehicleTypeImpl.Builder typeBuilder = VehicleTypeImpl.Builder.newInstance(typeIdNode.asText());
typeBuilder.setFixedCost(typeNode.path(JsonConstants.Vehicle.Type.FIXED_COSTS).asDouble());
typeBuilder.setCostPerDistance(typeNode.path(JsonConstants.Vehicle.Type.DISTANCE).asDouble());
typeBuilder.setCostPerTime(typeNode.path(JsonConstants.Vehicle.Type.TIME).asDouble());
JsonNode capacity = typeNode.path(JsonConstants.Vehicle.Type.CAPACITY);
Iterator<JsonNode> capacity_dimension_iterator = capacity.iterator();
int capacity_index = 0;
while(capacity_dimension_iterator.hasNext()){
JsonNode capacity_value = capacity_dimension_iterator.next();
int capacity_val = capacity_value.asInt();
typeBuilder.addCapacityDimension(capacity_index,capacity_val);
capacity_index++;
}
VehicleTypeImpl type = typeBuilder.build();
vehicle_type_map.put(type.getTypeId(),type);
}
}
private void setFleetSize(JsonNode root) {
String fleetsize = root.path(JsonConstants.FLEET).asText();
if(fleetsize.equals("INFINITE")) vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.INFINITE);
else vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE);
}
public static void main(String[] args) {
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
new VrpJsonReader(vrpBuilder).read(new File("output/vrp.json"));
VehicleRoutingProblem problem = vrpBuilder.build();
for(Job j : problem.getJobs().values()) System.out.println(j);
for(Vehicle v : problem.getVehicles()) System.out.println(v);
}
}

View file

@ -1,360 +0,0 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.problem.io;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.box.GreedySchrimpfFactory;
import jsprit.core.analysis.SolutionAnalyser;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl;
import jsprit.core.problem.vehicle.VehicleType;
import jsprit.core.problem.vehicle.VehicleTypeImpl;
import jsprit.core.util.Coordinate;
import jsprit.core.util.Solutions;
import java.io.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* Created by stefan on 03.11.14.
*/
public class VrpJsonWriter {
private final VehicleRoutingProblem vrp;
private final VehicleRoutingProblemSolution solution;
private SolutionAnalyser solutionAnalyzer;
public VrpJsonWriter(VehicleRoutingProblem vrp) {
this.vrp = vrp;
this.solution = null;
}
public VrpJsonWriter(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution, SolutionAnalyser.DistanceCalculator distanceCalculator){
this.vrp = vrp;
this.solution = solution;
this.solutionAnalyzer = new SolutionAnalyser(vrp,solution,distanceCalculator);
}
public String toString(){
StringWriter stringWriter = new StringWriter();
try {
JsonGenerator jsonGenerator = new JsonFactory().createGenerator(stringWriter);
if(solution == null) writeProblem(jsonGenerator);
else writeSolution(jsonGenerator);
jsonGenerator.flush();
jsonGenerator.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
return stringWriter.toString();
}
public void addTo(JsonGenerator jsonGenerator){
try {
if(solution == null) writeProblem(jsonGenerator);
else writeSolution(jsonGenerator);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
public void write(Writer writer){
try {
JsonGenerator jsonGenerator = new JsonFactory().createGenerator(writer);
jsonGenerator.setPrettyPrinter(new DefaultPrettyPrinter());
jsonGenerator.writeStartObject();
if(solution == null) writeProblem(jsonGenerator);
else writeSolution(jsonGenerator);
jsonGenerator.writeEndObject();
jsonGenerator.flush();
jsonGenerator.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
public void write(File jsonFile){
try {
JsonGenerator jsonGenerator = new JsonFactory().createGenerator(new FileOutputStream(jsonFile), JsonEncoding.UTF8);
jsonGenerator.setPrettyPrinter(new DefaultPrettyPrinter());
jsonGenerator.writeStartObject();
if(solution == null) writeProblem(jsonGenerator);
else writeSolution(jsonGenerator);
jsonGenerator.writeEndObject();
jsonGenerator.flush();
jsonGenerator.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
private void writeSolution(JsonGenerator jsonGenerator) {
try {
jsonGenerator.writeObjectFieldStart(JsonConstants.SOLUTION);
jsonGenerator.writeNumberField(JsonConstants.Solution.COSTS,solution.getCost());
jsonGenerator.writeNumberField(JsonConstants.Solution.FIXED_COSTS,solutionAnalyzer.getFixedCosts());
jsonGenerator.writeNumberField(JsonConstants.Solution.VARIABLE_COSTS, solutionAnalyzer.getVariableTransportCosts());
jsonGenerator.writeNumberField(JsonConstants.Solution.DISTANCE,solutionAnalyzer.getDistance());
jsonGenerator.writeNumberField(JsonConstants.Solution.TIME, solutionAnalyzer.getTransportTime());
jsonGenerator.writeNumberField(JsonConstants.Solution.NO_ROUTES,solution.getRoutes().size());
jsonGenerator.writeNumberField(JsonConstants.Solution.NO_UNASSIGNED,solution.getUnassignedJobs().size());
jsonGenerator.writeArrayFieldStart(JsonConstants.Solution.ROUTES);
for(VehicleRoute route : solution.getRoutes()){
jsonGenerator.writeStartObject();
jsonGenerator.writeNumberField(JsonConstants.Solution.Route.FIXED_COSTS,solutionAnalyzer.getFixedCosts(route));
jsonGenerator.writeNumberField(JsonConstants.Solution.Route.VARIABLE_COSTS,solutionAnalyzer.getVariableTransportCosts(route));
jsonGenerator.writeNumberField(JsonConstants.Solution.Route.NO_ACTIVITIES,route.getActivities().size());
jsonGenerator.writeNumberField(JsonConstants.Solution.Route.START_TIME,route.getStart().getEndTime());
for(TourActivity act : route.getActivities()) {
jsonGenerator.writeObjectFieldStart(JsonConstants.Solution.Route.ACTIVITY);
jsonGenerator.writeStringField(JsonConstants.Solution.Route.Activity.TYPE,act.getName());
if(act instanceof TourActivity.JobActivity){
jsonGenerator.writeStringField(JsonConstants.Solution.Route.Activity.SERVICE_ID,((TourActivity.JobActivity) act).getJob().getId());
}
else throw new IllegalStateException("act of class " + act.getClass().toString() + " not supported.");
jsonGenerator.writeNumberField(JsonConstants.Solution.Route.Activity.ARR_TIME, act.getArrTime());
jsonGenerator.writeNumberField(JsonConstants.Solution.Route.Activity.END_TIME,act.getEndTime());
jsonGenerator.writeEndObject();
}
jsonGenerator.writeNumberField(JsonConstants.Solution.Route.END_TIME, route.getEnd().getArrTime());
jsonGenerator.writeEndObject();
}
jsonGenerator.writeEndArray();
//unassigned jobs
jsonGenerator.writeArrayFieldStart(JsonConstants.Solution.Route.UNASSIGNED);
for(Job j : solution.getUnassignedJobs()){
jsonGenerator.writeString(j.getId());
}
jsonGenerator.writeEndArray();
jsonGenerator.writeEndObject();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeProblem(JsonGenerator jsonGenerator) throws IOException {
jsonGenerator.writeObjectFieldStart(JsonConstants.PROBLEM);
jsonGenerator.writeStringField(JsonConstants.FLEET, vrp.getFleetSize().toString());
writeVehicles(jsonGenerator);
writeVehicleTypes(jsonGenerator);
writeServices(jsonGenerator);
jsonGenerator.writeEndObject();
}
private void writeVehicleTypes(JsonGenerator jsonGenerator) {
try {
jsonGenerator.writeArrayFieldStart(JsonConstants.VEHICLE_TYPES);
Collection<VehicleType> types = getTypes(vrp.getVehicles());
for(VehicleType type : types){
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField(JsonConstants.Vehicle.Type.ID, type.getTypeId());
jsonGenerator.writeArrayFieldStart(JsonConstants.Vehicle.Type.CAPACITY);
for(int i=0;i<type.getCapacityDimensions().getNuOfDimensions();i++){
jsonGenerator.writeNumber(type.getCapacityDimensions().get(i));
}
jsonGenerator.writeEndArray();
jsonGenerator.writeNumberField(JsonConstants.Vehicle.Type.FIXED_COSTS, type.getVehicleCostParams().fix);
jsonGenerator.writeNumberField(JsonConstants.Vehicle.Type.DISTANCE, type.getVehicleCostParams().perDistanceUnit);
jsonGenerator.writeNumberField(JsonConstants.Vehicle.Type.TIME, type.getVehicleCostParams().perTimeUnit);
jsonGenerator.writeEndObject();
}
jsonGenerator.writeEndArray();
} catch (IOException e) {
e.printStackTrace();
}
}
private Collection<VehicleType> getTypes(Collection<Vehicle> vehicles) {
Set<VehicleType> types = new HashSet<VehicleType>();
for(Vehicle v : vehicles) types.add(v.getType());
return types;
}
private void writeVehicles(JsonGenerator jsonGenerator) {
try {
jsonGenerator.writeArrayFieldStart(JsonConstants.VEHICLES);
for(Vehicle vehicle : vrp.getVehicles()){
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField(JsonConstants.Vehicle.ID,vehicle.getId());
jsonGenerator.writeObjectFieldStart(JsonConstants.Vehicle.START_ADDRESS);
jsonGenerator.writeStringField(JsonConstants.Address.ID, vehicle.getStartLocationId());
jsonGenerator.writeNumberField(JsonConstants.Address.LON, vehicle.getStartLocationCoordinate().getX());
jsonGenerator.writeNumberField(JsonConstants.Address.LAT,vehicle.getStartLocationCoordinate().getY());
jsonGenerator.writeEndObject();
jsonGenerator.writeBooleanField(JsonConstants.Vehicle.RETURN_TO_DEPOT,vehicle.isReturnToDepot());
if(!(vehicle.getStartLocationCoordinate().equals(vehicle.getEndLocationCoordinate())
&& vehicle.getStartLocationId().equals(vehicle.getEndLocationId()))){
jsonGenerator.writeObjectFieldStart(JsonConstants.Vehicle.END_ADDRESS);
jsonGenerator.writeStringField(JsonConstants.Address.ID, vehicle.getEndLocationId());
jsonGenerator.writeNumberField(JsonConstants.Address.LON, vehicle.getEndLocationCoordinate().getX());
jsonGenerator.writeNumberField(JsonConstants.Address.LAT,vehicle.getEndLocationCoordinate().getY());
jsonGenerator.writeEndObject();
}
jsonGenerator.writeNumberField(JsonConstants.Vehicle.EARLIEST_START,vehicle.getEarliestDeparture());
jsonGenerator.writeNumberField(JsonConstants.Vehicle.LATEST_END,vehicle.getLatestArrival());
jsonGenerator.writeStringField(JsonConstants.Vehicle.TYPE_ID,vehicle.getType().getTypeId());
jsonGenerator.writeArrayFieldStart(JsonConstants.Vehicle.SKILLS);
for(String skill : vehicle.getSkills().values()){
jsonGenerator.writeString(skill);
}
jsonGenerator.writeEndArray();
jsonGenerator.writeEndObject();
}
jsonGenerator.writeEndArray();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeServices(JsonGenerator jsonGenerator) {
try {
jsonGenerator.writeArrayFieldStart(JsonConstants.SERVICES);
for(Job job : vrp.getJobs().values()){
if(!(job instanceof Service)) continue;
Service service = (Service)job;
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField(JsonConstants.Job.ID, service.getId());
jsonGenerator.writeStringField(JsonConstants.Job.TYPE,service.getType());
jsonGenerator.writeStringField(JsonConstants.Job.NAME,service.getName());
jsonGenerator.writeObjectFieldStart(JsonConstants.Job.ADDRESS);
jsonGenerator.writeStringField(JsonConstants.Address.ID, service.getLocationId());
jsonGenerator.writeNumberField(JsonConstants.Address.LON, service.getCoord().getX());
jsonGenerator.writeNumberField(JsonConstants.Address.LAT,service.getCoord().getY());
jsonGenerator.writeEndObject();
jsonGenerator.writeNumberField(JsonConstants.Job.SERVICE_DURATION, service.getServiceDuration());
jsonGenerator.writeObjectFieldStart(JsonConstants.Job.TIME_WINDOW);
jsonGenerator.writeNumberField(JsonConstants.TimeWindow.START,service.getTimeWindow().getStart());
jsonGenerator.writeNumberField(JsonConstants.TimeWindow.END,service.getTimeWindow().getEnd());
jsonGenerator.writeEndObject();
jsonGenerator.writeArrayFieldStart(JsonConstants.Job.SIZE);
for(int i=0;i<service.getSize().getNuOfDimensions();i++){
jsonGenerator.writeNumber(service.getSize().get(i));
}
jsonGenerator.writeEndArray();
jsonGenerator.writeArrayFieldStart(JsonConstants.Job.SKILLS);
for(String skill : service.getRequiredSkills().values()){
jsonGenerator.writeString(skill);
}
jsonGenerator.writeEndArray();
jsonGenerator.writeEndObject();
}
jsonGenerator.writeEndArray();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
Service service = Service.Builder.newInstance("s1").setLocationId("s1_loc").setCoord(Coordinate.newInstance(40, 10))
.addSizeDimension(0, 20).addSizeDimension(1, 40)
.setServiceTime(1.)
.addRequiredSkill("joo-foo")
.build();
Pickup service2 = (Pickup) Pickup.Builder.newInstance("pickup2").setLocationId("s2_loc").setCoord(Coordinate.newInstance(40, 10))
.addSizeDimension(0, 10).addSizeDimension(1, 30)
.setServiceTime(2.)
.setTimeWindow(TimeWindow.newInstance(10, 200))
.addRequiredSkill("screw-driver").build();
VehicleType type = VehicleTypeImpl.Builder.newInstance("small").addCapacityDimension(0,100).addCapacityDimension(1,400)
.setCostPerTime(20.).build();
VehicleType type2 = VehicleTypeImpl.Builder.newInstance("medium").addCapacityDimension(0,1000).addCapacityDimension(1,4000)
.setCostPerTime(200.).setFixedCost(1000.).build();
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocationId("startLoc").setStartLocationCoordinate(Coordinate.newInstance(0, 0))
.setEndLocationId("endLoc").setEndLocationCoordinate(Coordinate.newInstance(12, 12))
.addSkill("screw-driver")
.setType(type)
.setLatestArrival(1000.)
.build();
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocationId("startLoc").setStartLocationCoordinate(Coordinate.newInstance(0, 0))
.setType(type2)
.setReturnToDepot(false)
.addSkill("joo")
.build();
final VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addJob(service).addJob(service2)
.addVehicle(v1).addVehicle(v2).build();
new VrpJsonWriter(vrp).write(new File("output/vrp.json"));
// System.out.println(new VrpJsonWriter(vrp).toString());
VehicleRoutingProblem.Builder vrpBuilder_ = VehicleRoutingProblem.Builder.newInstance();
new VrpJsonReader(vrpBuilder_).read(new File("output/vrp.json"));
VehicleRoutingProblem vrp_ = vrpBuilder_.build();
VehicleRoutingAlgorithm vra = new GreedySchrimpfFactory().createAlgorithm(vrp_);
VehicleRoutingProblemSolution solutions = Solutions.bestOf(vra.searchSolutions());
FileWriter fileWriter = new FileWriter(new File("output/vrp-solution.json"));
JsonGenerator jsonGenerator = new JsonFactory().createGenerator(fileWriter);
jsonGenerator.setPrettyPrinter(new DefaultPrettyPrinter());
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectFieldStart("meta-info");
jsonGenerator.writeStringField("distance-unit", "m");
jsonGenerator.writeStringField("time-unit","sec");
jsonGenerator.writeEndObject();
new VrpJsonWriter(vrp,solutions,new SolutionAnalyser.DistanceCalculator() {
@Override
public double getDistance(String fromLocationId, String toLocationId) {
return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null);
}
}).addTo(jsonGenerator);
jsonGenerator.writeEndObject();
jsonGenerator.flush();
jsonGenerator.close();
fileWriter.close();
// .write(new File("output/vrp-solution.json"));
}
}

View file

@ -1,185 +0,0 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.problem.io;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.util.DistanceUnit;
import jsprit.core.util.TimeUnit;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
public class VrpJsonReaderTest {
private File jsonFile;
VehicleRoutingProblem vrp;
@Before
public void setup(){
jsonFile = new File("src/test/resources/vrp.json");
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
new VrpJsonReader(vrpBuilder).read(jsonFile);
vrp = vrpBuilder.build();
}
@Test
public void noVehiclesShouldBeCorrect(){
Assert.assertEquals(2,vrp.getVehicles().size());
}
@Test
public void noJobsShouldBeCorrect(){
Assert.assertEquals(2, vrp.getJobs().size());
}
@Test
public void noTypesShouldBeCorrect(){
Assert.assertEquals(2, vrp.getTypes().size());
}
@Test
public void vehicle1ShouldBeOfTypeSmall(){
Assert.assertEquals("small",getVehicle("v1").getType().getTypeId());
}
@Test
public void vehicle2ShouldBeOfTypeMedium(){
Assert.assertEquals("medium",getVehicle("v2").getType().getTypeId());
}
@Test
public void vehicle1ShouldHaveCorrectStartAddress(){
Assert.assertEquals("startLoc", getVehicle("v1").getStartLocationId());
}
@Test
public void vehicle1ShouldHaveCorrectEndAddress(){
Assert.assertEquals("endLoc",getVehicle("v1").getEndLocationId());
}
@Test
public void vehicle1ShouldHaveCorrectEndLocCoordinate(){
Assert.assertEquals(12.,getVehicle("v1").getEndLocationCoordinate().getX(),0.01);
Assert.assertEquals(13.,getVehicle("v1").getEndLocationCoordinate().getY(),0.01);
}
@Test
public void vehicle1ShouldHaveCorrectEarliestStart(){
Assert.assertEquals(0.,getVehicle("v1").getEarliestDeparture());
}
@Test
public void vehicle1ShouldHaveCorrectLatestStart(){
Assert.assertEquals(1000., getVehicle("v1").getLatestArrival());
}
@Test
public void vehicle1ShouldHaveCorrectSkills(){
Assert.assertEquals("screw-driver", getVehicle("v1").getSkills().values().iterator().next());
}
@Test
public void fleetSizeShouldBeCorrect(){
Assert.assertTrue(VehicleRoutingProblem.FleetSize.FINITE.equals(vrp.getFleetSize()));
}
@Test
public void returnToDepotShouldBeCorrect(){
Assert.assertTrue(getVehicle("v1").isReturnToDepot());
}
@Test
public void serviceTypeShouldBeCorrect(){
Assert.assertEquals("pickup", getService("pickup2").getType());
}
@Test
public void serviceNameShouldBeCorrect(){
Assert.assertEquals("no-name", getService("pickup2").getName());
}
@Test
public void startLocShouldBeCorrect(){
Assert.assertEquals("s2_loc", getService("pickup2").getLocationId());
}
@Test
public void coordinateShouldBeCorrect(){
Assert.assertEquals(40., getService("pickup2").getCoord().getX());
Assert.assertEquals(10., getService("pickup2").getCoord().getY());
}
@Test
public void serviceDurationShouldBeCorrect(){
Assert.assertEquals(2., getService("pickup2").getServiceDuration());
}
@Test
public void serviceTWShouldBeCorrect(){
Assert.assertEquals(10., getService("pickup2").getTimeWindow().getStart());
Assert.assertEquals(200., getService("pickup2").getTimeWindow().getEnd());
}
@Test
public void sizeShouldBeCorrect(){
Assert.assertEquals(10, getService("pickup2").getSize().get(0));
Assert.assertEquals(30, getService("pickup2").getSize().get(1));
}
@Test
public void skillsShouldBeCorrect(){
Assert.assertEquals("screw-driver", getService("pickup2").getRequiredSkills().values().iterator().next());
}
private Service getService(String jobId) {
for(Job s : vrp.getJobs().values()){
if(s.getId().equals(jobId)) return (Service)s;
}
return null;
}
@Test
public void readMetaInfo(){
ObjectMapper om = new ObjectMapper();
try {
JsonNode meta = om.readTree(jsonFile).path(JsonConstants.META);
Assert.assertEquals(DistanceUnit.Meter.abbreviation(),meta.path(JsonConstants.MetaInfo.DISTANCE_UNIT).asText());
Assert.assertEquals(TimeUnit.SEC.abbreviation(),meta.path(JsonConstants.MetaInfo.TIME_UNIT).asText());
} catch (IOException e) {
e.printStackTrace();
}
}
private Vehicle getVehicle(String id) {
for(Vehicle v : vrp.getVehicles()){
if(v.getId().equals(id)) return v;
}
return null;
}
}

View file

@ -1,112 +0,0 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.problem.io;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jsprit.core.algorithm.box.GreedySchrimpfFactory;
import jsprit.core.analysis.SolutionAnalyser;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.vehicle.VehicleImpl;
import jsprit.core.problem.vehicle.VehicleType;
import jsprit.core.problem.vehicle.VehicleTypeImpl;
import jsprit.core.util.Coordinate;
import jsprit.core.util.Solutions;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
/**
* Created by schroeder on 04.12.14.
*/
public class VrpJsonWriterTest {
private VehicleRoutingProblem vrp;
private VehicleRoutingProblemSolution solution;
private JsonNode root;
@Before
public void doBefore(){
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0,20).build();
VehicleImpl v = VehicleImpl.Builder.newInstance("v").setStartLocationId("start").setStartLocationCoordinate(Coordinate.newInstance(10,40))
.setEndLocationId("end").setEndLocationCoordinate(Coordinate.newInstance(50,20)).setReturnToDepot(true)
.setType(type)
.build();
Service s = Service.Builder.newInstance("s").setCoord(Coordinate.newInstance(50,60)).addSizeDimension(0,10).build();
vrp = VehicleRoutingProblem.Builder.newInstance().addVehicle(v).addJob(s).build();
solution = Solutions.bestOf(new GreedySchrimpfFactory().createAlgorithm(vrp).searchSolutions());
File out = new File("src/test/resources/vrp-solution.json");
new VrpJsonWriter(vrp,solution,new SolutionAnalyser.DistanceCalculator() {
@Override
public double getDistance(String fromLocationId, String toLocationId) {
return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null);
}
}).write(out);
ObjectMapper om = new ObjectMapper();
try {
root = om.readTree(out).path("solution");
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void solutionValShouldBeCorrect(){
Assert.assertEquals(solution.getCost(),root.path("costs").asDouble(),0.01);
}
@Test
public void fixShouldBeCorrect(){
Assert.assertEquals(0.,root.path("fixed_costs").asDouble(),0.01);
}
@Test
public void varShouldBeCorrect(){
Assert.assertEquals(solution.getCost(),root.path("variable_costs").asDouble(),0.01);
}
@Test
public void timeShouldBeCorrect(){
Assert.assertEquals(solution.getCost(),root.path("time").asDouble(),0.01);
}
@Test
public void distanceShouldBeCorrect(){
Assert.assertEquals(solution.getCost(),root.path("distance").asDouble(),0.01);
}
@Test
public void noRoutesShouldBeCorrect(){
Assert.assertEquals(solution.getRoutes().size(),root.path("no_routes").asDouble(),0.01);
}
@Test
public void noUnassignedShouldBeCorrect(){
Assert.assertEquals(solution.getUnassignedJobs().size(),root.path("no_unassigned").asDouble(),0.01);
}
}

View file

@ -14,196 +14,206 @@
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/ ******************************************************************************/
package jsprit.examples; package jsprit.examples;
import jsprit.core.algorithm.*; import jsprit.analysis.toolbox.AlgorithmEventsRecorder;
import jsprit.analysis.toolbox.AlgorithmEventsViewer;
import jsprit.core.algorithm.PrettyAlgorithmBuilder;
import jsprit.core.algorithm.SearchStrategy;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.acceptor.GreedyAcceptance; import jsprit.core.algorithm.acceptor.GreedyAcceptance;
import jsprit.core.algorithm.listener.IterationStartsListener;
import jsprit.core.algorithm.module.RuinAndRecreateModule; import jsprit.core.algorithm.module.RuinAndRecreateModule;
import jsprit.core.algorithm.recreate.BestInsertionBuilder; import jsprit.core.algorithm.recreate.*;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.algorithm.ruin.RadialRuinStrategyFactory; import jsprit.core.algorithm.ruin.RadialRuinStrategyFactory;
import jsprit.core.algorithm.ruin.RandomRuinStrategyFactory; import jsprit.core.algorithm.ruin.RandomRuinStrategyFactory;
import jsprit.core.algorithm.ruin.RuinStrategy; import jsprit.core.algorithm.ruin.RuinStrategy;
import jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance; import jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance;
import jsprit.core.algorithm.selector.SelectBest; import jsprit.core.algorithm.selector.SelectBest;
import jsprit.core.algorithm.state.StateManager; import jsprit.core.algorithm.state.StateManager;
import jsprit.core.algorithm.state.UpdateVariableCosts; import jsprit.core.analysis.SolutionAnalyser;
import jsprit.core.algorithm.termination.IterationWithoutImprovementTermination;
import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.constraint.ConstraintManager; import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.SolutionCostCalculator; import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.vehicle.InfiniteFleetManagerFactory; import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.FiniteFleetManagerFactory;
import jsprit.core.problem.vehicle.VehicleFleetManager; import jsprit.core.problem.vehicle.VehicleFleetManager;
import jsprit.core.reporting.SolutionPrinter; import jsprit.core.reporting.SolutionPrinter;
import jsprit.core.util.Solutions; import jsprit.core.util.Solutions;
import jsprit.instance.reader.SolomonReader; import jsprit.instance.reader.CordeauReader;
import jsprit.util.Examples; import jsprit.util.Examples;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class BuildAlgorithmFromScratch { public class BuildAlgorithmFromScratch {
public static void main(String[] args) { public static class MyBestStrategy extends AbstractInsertionStrategy {
/*
* some preparation - create output folder private JobInsertionCostsCalculatorLight insertionCalculator;
*/
Examples.createOutputFolder();
public MyBestStrategy(VehicleRoutingProblem vrp, VehicleFleetManager fleetManager, StateManager stateManager, ConstraintManager constraintManager) {
super(vrp);
insertionCalculator = JobInsertionCostsCalculatorLightFactory.createStandardCalculator(vrp, fleetManager, stateManager, constraintManager);
}
@Override
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
List<Job> badJobs = new ArrayList<Job>();
List<Job> unassigned = new ArrayList<Job>(unassignedJobs);
Collections.shuffle(unassigned, random);
for(Job j : unassigned){
InsertionData bestInsertionData = InsertionData.createEmptyInsertionData();
VehicleRoute bestRoute = null;
//look for inserting unassigned job into existing route
for(VehicleRoute r : vehicleRoutes){
InsertionData insertionData = insertionCalculator.getInsertionData(j,r,bestInsertionData.getInsertionCost());
if(insertionData instanceof InsertionData.NoInsertionFound) continue;
if(insertionData.getInsertionCost() < bestInsertionData.getInsertionCost()){
bestInsertionData = insertionData;
bestRoute = r;
}
}
//try whole new route
VehicleRoute empty = VehicleRoute.emptyRoute();
InsertionData insertionData = insertionCalculator.getInsertionData(j, empty, bestInsertionData.getInsertionCost());
if(!(insertionData instanceof InsertionData.NoInsertionFound)) {
if (insertionData.getInsertionCost() < bestInsertionData.getInsertionCost()) {
vehicleRoutes.add(empty);
insertJob(j, insertionData, empty);
}
}
else {
if(bestRoute != null) insertJob(j,bestInsertionData,bestRoute);
else badJobs.add(j);
}
}
return badJobs;
}
}
public static void main(String[] args) {
Examples.createOutputFolder();
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
new CordeauReader(vrpBuilder).read("input/p08");
final VehicleRoutingProblem vrp = vrpBuilder.build();
VehicleRoutingAlgorithm vra = createAlgorithm(vrp);
vra.setMaxIterations(100);
AlgorithmEventsRecorder eventsRecorder = new AlgorithmEventsRecorder(vrp,"output/events.dgs.gz");
eventsRecorder.setRecordingRange(90,100);
vra.addListener(eventsRecorder);
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
SolutionPrinter.print(vrp, solution, SolutionPrinter.Print.VERBOSE);
AlgorithmEventsViewer viewer = new AlgorithmEventsViewer();
viewer.setRuinDelay(3);
viewer.setRecreationDelay(1);
viewer.display("output/events.dgs.gz");
}
public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp){
VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
StateManager stateManager = new StateManager(vrp);
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
/*
* insertion strategies
*/
//my custom best insertion
MyBestStrategy best = new MyBestStrategy(vrp,fleetManager,stateManager,constraintManager);
//regret insertion
InsertionBuilder iBuilder = new InsertionBuilder(vrp, fleetManager, stateManager, constraintManager);
iBuilder.setInsertionStrategy(InsertionBuilder.Strategy.REGRET);
RegretInsertion regret = (RegretInsertion) iBuilder.build();
RegretInsertion.DefaultScorer scoringFunction = new RegretInsertion.DefaultScorer(vrp);
scoringFunction.setDepotDistanceParam(0.2);
scoringFunction.setTimeWindowParam(-.2);
regret.setScoringFunction(scoringFunction);
/* /*
* Build the problem. * ruin strategies
*
* But define a problem-builder first.
*/ */
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); RuinStrategy randomRuin = new RandomRuinStrategyFactory(0.5).createStrategy(vrp);
RuinStrategy radialRuin = new RadialRuinStrategyFactory(0.3, new AvgServiceAndShipmentDistance(vrp.getTransportCosts())).createStrategy(vrp);
/* /*
* A solomonReader reads solomon-instance files, and stores the required information in the builder. * objective function
*/ */
new SolomonReader(vrpBuilder).read("input/C101_solomon.txt"); SolutionCostCalculator objectiveFunction = getObjectiveFunction(vrp);
/* SearchStrategy firstStrategy = new SearchStrategy("firstStrategy", new SelectBest(), new GreedyAcceptance(1), objectiveFunction);
* Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances). firstStrategy.addModule(new RuinAndRecreateModule("randRuinRegretIns", regret, randomRuin));
*/
VehicleRoutingProblem vrp = vrpBuilder.build();
/* SearchStrategy secondStrategy = new SearchStrategy("secondStrategy", new SelectBest(), new GreedyAcceptance(1), objectiveFunction);
* Build algorithm secondStrategy.addModule(new RuinAndRecreateModule("radRuinRegretIns", regret, radialRuin));
*/
VehicleRoutingAlgorithm vra = buildAlgorithmFromScratch(vrp);
/* SearchStrategy thirdStrategy = new SearchStrategy("thirdStrategy", new SelectBest(), new GreedyAcceptance(1), objectiveFunction);
* search solution secondStrategy.addModule(new RuinAndRecreateModule("radRuinBestIns", regret, radialRuin));
*/
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
/* PrettyAlgorithmBuilder prettyAlgorithmBuilder = PrettyAlgorithmBuilder.newInstance(vrp,fleetManager,stateManager,constraintManager);
* print result final VehicleRoutingAlgorithm vra = prettyAlgorithmBuilder
*/ .withStrategy(firstStrategy, 0.5).withStrategy(secondStrategy, 0.5).withStrategy(thirdStrategy, 0.2)
SolutionPrinter.print(Solutions.bestOf(solutions)); .addCoreStateAndConstraintStuff()
.constructInitialSolutionWith(regret, objectiveFunction)
.build();
} //if you want to switch on/off strategies or adapt their weight within the search, you can do the following
//e.g. from iteration 50 on, switch off first strategy
//switch on again at iteration 90 with slightly higher weight
IterationStartsListener strategyAdaptor = new IterationStartsListener() {
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
if(i == 50){
vra.getSearchStrategyManager().informStrategyWeightChanged("firstStrategy",0.0);
System.out.println("switched off firstStrategy");
}
if(i == 90){
vra.getSearchStrategyManager().informStrategyWeightChanged("firstStrategy",0.7);
System.out.println("switched on firstStrategy again with higher weight");
}
}
};
vra.addListener(strategyAdaptor);
return vra;
private static VehicleRoutingAlgorithm buildAlgorithmFromScratch(VehicleRoutingProblem vrp) { }
/* private static SolutionCostCalculator getObjectiveFunction(final VehicleRoutingProblem vrp) {
* manages route and activity states. return new SolutionCostCalculator() {
*/
StateManager stateManager = new StateManager(vrp);
/*
* tells stateManager to update load states
*/
stateManager.updateLoadStates();
/*
* tells stateManager to update time-window states
*/
stateManager.updateTimeWindowStates();
/*
* stateManager.addStateUpdater(updater);
* lets you register your own stateUpdater
*/
/*
* updates variable costs once a vehicleRoute has changed (by removing or adding a customer)
*/
stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
/* @Override
* constructs a constraintManager that manages the various hardConstraints (and soon also softConstraints) public double getCosts(VehicleRoutingProblemSolution solution) {
*/ SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution,new SolutionAnalyser.DistanceCalculator() {
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager); @Override
/* public double getDistance(String fromLocationId, String toLocationId) {
* tells constraintManager to add timeWindowConstraints return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null);
*/ }
constraintManager.addTimeWindowConstraint(); });
/* return analyser.getVariableTransportCosts() + solution.getUnassignedJobs().size() * 500.;
* tells constraintManager to add loadConstraints }
*/
constraintManager.addLoadConstraint();
/*
* add an arbitrary number of hardConstraints by
* constraintManager.addConstraint(...)
*/
/* };
* define a fleetManager, here infinite vehicles can be used }
*/
VehicleFleetManager fleetManager = new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
/*
* define ruin-and-recreate strategies
*
*/
/*
* first, define an insertion-strategy, i.e. bestInsertion
*/
BestInsertionBuilder iBuilder = new BestInsertionBuilder(vrp, fleetManager, stateManager, constraintManager);
/*
* no need to set further options
*/
InsertionStrategy iStrategy = iBuilder.build();
/*
* second, define random-ruin that ruins 50-percent of the selected solution
*/
RuinStrategy randomRuin = new RandomRuinStrategyFactory(0.5).createStrategy(vrp);
/*
* third, define radial-ruin that ruins 30-percent of the selected solution
* the second para defines the distance between two jobs.
*/
RuinStrategy radialRuin = new RadialRuinStrategyFactory(0.3, new AvgServiceAndShipmentDistance(vrp.getTransportCosts())).createStrategy(vrp);
/*
* now define a strategy
*/
/*
* but before define how a generated solution is evaluated
* here: the VariablePlusFixed.... comes out of the box and it does what its name suggests
*/
SolutionCostCalculator solutionCostCalculator = new VariablePlusFixedSolutionCostCalculatorFactory(stateManager).createCalculator();
SearchStrategy firstStrategy = new SearchStrategy("random",new SelectBest(), new GreedyAcceptance(1), solutionCostCalculator);
firstStrategy.addModule(new RuinAndRecreateModule("randomRuinAndBestInsertion", iStrategy, randomRuin));
SearchStrategy secondStrategy = new SearchStrategy("radial",new SelectBest(), new GreedyAcceptance(1), solutionCostCalculator);
secondStrategy.addModule(new RuinAndRecreateModule("radialRuinAndBestInsertion", iStrategy, radialRuin));
/*
* put both strategies together, each with the prob of 0.5 to be selected
*/
SearchStrategyManager searchStrategyManager = new SearchStrategyManager();
searchStrategyManager.addStrategy(firstStrategy, 0.5);
searchStrategyManager.addStrategy(secondStrategy, 0.5);
/*
* construct the algorithm
*/
VehicleRoutingAlgorithm vra = new VehicleRoutingAlgorithm(vrp, searchStrategyManager);
//do not forgett to add the stateManager listening to the algorithm-stages
vra.addListener(stateManager);
//remove empty vehicles after insertion has finished
vra.addListener(new RemoveEmptyVehicles(fleetManager));
/*
* Do not forget to add an initial solution by vra.addInitialSolution(solution);
* or
*/
vra.addInitialSolution(new InsertionInitialSolutionFactory(iStrategy, solutionCostCalculator).createSolution(vrp));
/*
* define the nIterations (by default nIteration=100)
*/
vra.setMaxIterations(1000);
/*
* optionally define a premature termination criterion (by default: not criterion is set)
*/
vra.setPrematureAlgorithmTermination(new IterationWithoutImprovementTermination(100));
return vra;
}
} }

View file

@ -1,208 +0,0 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.examples;
import jsprit.core.algorithm.*;
import jsprit.core.algorithm.acceptor.GreedyAcceptance;
import jsprit.core.algorithm.module.RuinAndRecreateModule;
import jsprit.core.algorithm.recreate.BestInsertionBuilder;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.algorithm.ruin.RadialRuinStrategyFactory;
import jsprit.core.algorithm.ruin.RandomRuinStrategyFactory;
import jsprit.core.algorithm.ruin.RuinStrategy;
import jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance;
import jsprit.core.algorithm.selector.SelectBest;
import jsprit.core.algorithm.state.StateManager;
import jsprit.core.algorithm.state.UpdateVariableCosts;
import jsprit.core.algorithm.termination.IterationWithoutImprovementTermination;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.vehicle.InfiniteFleetManagerFactory;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import jsprit.core.reporting.SolutionPrinter;
import jsprit.core.util.Solutions;
import jsprit.instance.reader.SolomonReader;
import jsprit.util.Examples;
import java.util.Collection;
public class BuildAlgorithmFromScratchWithHardAndSoftConstraints {
public static void main(String[] args) {
/*
* some preparation - create output folder
*/
Examples.createOutputFolder();
/*
* Build the problem.
*
* But define a problem-builder first.
*/
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
/*
* A solomonReader reads solomon-instance files, and stores the required information in the builder.
*/
new SolomonReader(vrpBuilder).read("input/C101_solomon.txt");
/*
* Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances).
*/
VehicleRoutingProblem vrp = vrpBuilder.build();
/*
* Build algorithm
*/
VehicleRoutingAlgorithm vra = buildAlgorithmFromScratch(vrp);
/*
* search solution
*/
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
/*
* print result
*/
SolutionPrinter.print(Solutions.bestOf(solutions));
}
private static VehicleRoutingAlgorithm buildAlgorithmFromScratch(VehicleRoutingProblem vrp) {
/*
* manages route and activity states.
*/
StateManager stateManager = new StateManager(vrp);
/*
* tells stateManager to update load states
*/
stateManager.updateLoadStates();
/*
* tells stateManager to update time-window states
*/
stateManager.updateTimeWindowStates();
/*
* stateManager.addStateUpdater(updater);
* lets you register your own stateUpdater
*/
/*
* updates variable costs once a vehicleRoute has changed (by removing or adding a customer)
*/
stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
/*
* constructs a constraintManager that manages the various hardConstraints (and soon also softConstraints)
*/
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
/*
* tells constraintManager to add timeWindowConstraints
*/
constraintManager.addTimeWindowConstraint();
/*
* tells constraintManager to add loadConstraints
*/
constraintManager.addLoadConstraint();
/*
* add an arbitrary number of hardConstraints by
* constraintManager.addConstraint(...)
*/
/*
* define a fleetManager, here infinite vehicles can be used
*/
VehicleFleetManager fleetManager = new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
/*
* define ruin-and-recreate strategies
*
*/
/*
* first, define an insertion-strategy, i.e. bestInsertion
*/
BestInsertionBuilder iBuilder = new BestInsertionBuilder(vrp, fleetManager, stateManager, constraintManager);
/*
* no need to set further options
*/
InsertionStrategy iStrategy = iBuilder.build();
/*
* second, define random-ruin that ruins 50-percent of the selected solution
*/
RuinStrategy randomRuin = new RandomRuinStrategyFactory(0.5).createStrategy(vrp);
/*
* third, define radial-ruin that ruins 30-percent of the selected solution
* the second para defines the distance between two jobs.
*/
RuinStrategy radialRuin = new RadialRuinStrategyFactory(0.3, new AvgServiceAndShipmentDistance(vrp.getTransportCosts())).createStrategy(vrp);
/*
* now define a strategy
*/
/*
* but before define how a generated solution is evaluated
* here: the VariablePlusFixed.... comes out of the box and it does what its name suggests
*/
SolutionCostCalculator solutionCostCalculator = new VariablePlusFixedSolutionCostCalculatorFactory(stateManager).createCalculator();
SearchStrategy firstStrategy = new SearchStrategy("random",new SelectBest(), new GreedyAcceptance(1), solutionCostCalculator);
firstStrategy.addModule(new RuinAndRecreateModule("randomRuinAndBestInsertion", iStrategy, randomRuin));
SearchStrategy secondStrategy = new SearchStrategy("radial",new SelectBest(), new GreedyAcceptance(1), solutionCostCalculator);
secondStrategy.addModule(new RuinAndRecreateModule("radialRuinAndBestInsertion", iStrategy, radialRuin));
/*
* put both strategies together, each with the prob of 0.5 to be selected
*/
SearchStrategyManager searchStrategyManager = new SearchStrategyManager();
searchStrategyManager.addStrategy(firstStrategy, 0.5);
searchStrategyManager.addStrategy(secondStrategy, 0.5);
/*
* construct the algorithm
*/
VehicleRoutingAlgorithm vra = new VehicleRoutingAlgorithm(vrp, searchStrategyManager);
//do not forgett to add the stateManager listening to the algorithm-stages
vra.addListener(stateManager);
//remove empty vehicles after insertion has finished
vra.addListener(new RemoveEmptyVehicles(fleetManager));
/*
* Do not forget to add an initial solution by vra.addInitialSolution(solution);
* or
*/
vra.addInitialSolution(new InsertionInitialSolutionFactory(iStrategy, solutionCostCalculator).createSolution(vrp));
/*
* define the nIterations (by default nIteration=100)
*/
vra.setMaxIterations(1000);
/*
* optionally define a premature termination criterion (by default: not criterion is set)
*/
vra.setPrematureAlgorithmTermination(new IterationWithoutImprovementTermination(100));
return vra;
}
}

View file

@ -73,7 +73,7 @@ public class CircleExample {
VehicleRoutingProblem vrp = vrpBuilder.build(); VehicleRoutingProblem vrp = vrpBuilder.build();
//only works with latest snapshot: 1.4.3 //only works with latest snapshot: 1.4.3
AlgorithmEventsRecorder eventsRecorder = new AlgorithmEventsRecorder(vrp,new File("output/events.dgs.gz")); AlgorithmEventsRecorder eventsRecorder = new AlgorithmEventsRecorder(vrp,"output/events.dgs.gz");
eventsRecorder.setRecordingRange(0,50); eventsRecorder.setRecordingRange(0,50);
VehicleRoutingAlgorithm vra = new GreedySchrimpfFactory().createAlgorithm(vrp); VehicleRoutingAlgorithm vra = new GreedySchrimpfFactory().createAlgorithm(vrp);

View file

@ -30,7 +30,6 @@ import jsprit.core.reporting.SolutionPrinter;
import jsprit.instance.reader.SolomonReader; import jsprit.instance.reader.SolomonReader;
import jsprit.util.Examples; import jsprit.util.Examples;
import java.io.File;
import java.util.Collection; import java.util.Collection;
@ -70,7 +69,7 @@ public class SolomonWithRegretInsertionExample {
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_greedyWithRegret.xml"); VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_greedyWithRegret.xml");
vra.setMaxIterations(2); vra.setMaxIterations(2);
AlgorithmEventsRecorder eventsRecorder = new AlgorithmEventsRecorder(vrp,new File("output/events.dgs.gz")); AlgorithmEventsRecorder eventsRecorder = new AlgorithmEventsRecorder(vrp,"output/events.dgs.gz");
eventsRecorder.setRecordingRange(0,50); eventsRecorder.setRecordingRange(0,50);
vra.addListener(eventsRecorder); vra.addListener(eventsRecorder);