I got inspired by this: https://stackoverflow.com/questions/24447451/related-jobs-in-jsprit
Note i am using Jsprit 1.72.
Here is my solution, i will do further testing in the days coming, but initially it seems to be working.
Note that i am randoming the transport times everytime for the matrix.
package com.jspritexample.jspritexample;
import static org.junit.Assert.assertNotNull;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.graphhopper.jsprit.analysis.toolbox.AlgorithmSearchProgressChartListener;
import com.graphhopper.jsprit.analysis.toolbox.GraphStreamViewer;
import com.graphhopper.jsprit.analysis.toolbox.Plotter;
import com.graphhopper.jsprit.analysis.toolbox.Plotter.Label;
import com.graphhopper.jsprit.core.algorithm.AlgorithmUtil;
import com.graphhopper.jsprit.core.algorithm.SearchStrategyManager;
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
import com.graphhopper.jsprit.core.algorithm.box.Jsprit;
import com.graphhopper.jsprit.core.algorithm.box.Jsprit.Builder;
import com.graphhopper.jsprit.core.algorithm.box.Jsprit.Parameter;
import com.graphhopper.jsprit.core.algorithm.state.InternalStates;
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
import com.graphhopper.jsprit.core.algorithm.state.StateUpdater;
import com.graphhopper.jsprit.core.problem.Location;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem.FleetSize;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
import com.graphhopper.jsprit.core.problem.constraint.HardActivityConstraint;
import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager.Priority;
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.job.Service;
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
import com.graphhopper.jsprit.core.problem.solution.SolutionCostCalculator;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.problem.solution.route.activity.ActivityVisitor;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity.JobActivity;
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleType;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl;
import com.graphhopper.jsprit.core.reporting.SolutionPrinter;
import com.graphhopper.jsprit.core.reporting.SolutionPrinter.Print;
import com.graphhopper.jsprit.core.util.Coordinate;
import com.graphhopper.jsprit.core.util.Solutions;
import com.graphhopper.jsprit.core.util.VehicleRoutingTransportCostsMatrix;
import com.graphhopper.jsprit.io.problem.VrpXMLReader;
import com.jspritexample.jspritutils.JsPritUtils;
public class App
{
static class JobsInRouteMemorizer implements StateUpdater, ActivityVisitor {
private StateManager stateManager;
private VehicleRoute route;
public int timesAssigned= 0;
public JobsInRouteMemorizer(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
this.route=route;
}
@Override
public void visit(TourActivity activity) {
if(activity instanceof JobActivity){
String jobId = ((JobActivity) activity).getJob().getId();
// the job was assigned, then put it inside statemanager.
stateManager.putProblemState(stateManager.createStateId(jobId), String.class, jobId);
}
}
@Override
public void finish() {}
}
static class EitherS2OrS3 implements HardActivityConstraint {
private StateManager stateManager;
public EitherS2OrS3(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct,
TourActivity nextAct, double prevActDepTime) {
String currentJobId = iFacts.getJob().getId();
String s2Job = stateManager.getProblemState(stateManager.createStateId("s2"), String.class);
// if job s2 was assigned and we are inserting s3 then we cannot do that.
if( s2Job != null && currentJobId == "s3"){
return ConstraintsStatus.NOT_FULFILLED;
}
String s3Job = stateManager.getProblemState(stateManager.createStateId("s3"), String.class);
//if job s3 was assigned and we are inserting s2 then we cannot do that.
if( s3Job != null && currentJobId == "s2"){
return ConstraintsStatus.NOT_FULFILLED;
}
return ConstraintsStatus.FULFILLED;
}
}
public static void main( String[] args )
{
JsPritUtils.createOutputFolder();
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").build();
Location l0 = Location.Builder.newInstance().setId("0").setName("Local0").setCoordinate(Coordinate.newInstance(23.1, 22.2)).build();
Location l1 = Location.Builder.newInstance().setId("1").setName("Local1").setCoordinate(Coordinate.newInstance(23, 24)).build();
Location l2 = Location.Builder.newInstance().setId("2").setName("Local2").setCoordinate(Coordinate.newInstance(21, 25)).build();
Location l3 = Location.Builder.newInstance().setId("3").setName("Local3").setCoordinate(Coordinate.newInstance(22.5, 23.5)).build();
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("myOwn")
.setStartLocation(l0).setType(type).build();
Service s1 = Service.Builder.newInstance("s1").setLocation(l1).build();
Service s2 = Service.Builder.newInstance("s2").setLocation(l2).addTimeWindow(new TimeWindow(0,20)).build();
Service s3 = Service.Builder.newInstance("s3").setLocation(l3).addTimeWindow(new TimeWindow(20,40)).build();
VehicleRoutingTransportCostsMatrix.Builder costMatrixBuilder = VehicleRoutingTransportCostsMatrix.Builder.newInstance(true);
Random rand = new Random();
int number = rand.nextInt(50) + 1;
costMatrixBuilder.addTransportTime("0", "1", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("0", "2", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("1", "0", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("2", "0", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("1", "0", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("1", "2", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("0", "1", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("2", "1", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("2", "0", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("2", "1", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("0", "2", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("1", "2", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("2", "0", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("2", "1", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("0", "2", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("1", "2", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("0", "3", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("1", "3", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("2", "3", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("3", "1", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("3", "2", rand.nextInt(50) + 1);
costMatrixBuilder.addTransportTime("3", "3", rand.nextInt(50) + 1);
VehicleRoutingTransportCosts costMatrix = costMatrixBuilder.build();
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().setFleetSize(FleetSize.FINITE).setRoutingCost(costMatrix)
.addVehicle(vehicle)
.addJob(s1).addJob(s2).addJob(s3)
.build();
/// OK THE UPPER IS SETUP
final StateManager stateManager = new StateManager(vrp);
JobsInRouteMemorizer jm = new JobsInRouteMemorizer(stateManager);
stateManager.addStateUpdater(jm);
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
constraintManager.addConstraint(new EitherS2OrS3(stateManager), Priority.CRITICAL);
//
//final RewardAndPenaltiesThroughSoftConstraints softConstraintContributionToOverallObjective = new RewardAndPenaltiesThroughSoftConstraints(vrp);
SolutionCostCalculator costCalculator = new SolutionCostCalculator() {
@Override
public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.0;
for (VehicleRoute r : solution.getRoutes()) {
costs += stateManager.getRouteState(r, InternalStates.COSTS, Double.class);
costs += getFixedCosts(r.getVehicle());
// costs +=softConstraintContributionToOverallObjective.getCosts(r);
}
costs += solution.getUnassignedJobs().size() * costs * .1;
return costs;
}
private double getFixedCosts(Vehicle vehicle) {
if (vehicle == null) return 0.0;
if (vehicle.getType() == null) return 0.0;
return vehicle.getType().getVehicleCostParams().fix;
}
};
Builder builder = Jsprit.Builder.newInstance(vrp);
builder.setObjectiveFunction(costCalculator);
builder.setStateAndConstraintManager(stateManager,constraintManager);
builder.setProperty(Parameter.ITERATIONS.toString(), "2000");
VehicleRoutingAlgorithm vra = builder.buildAlgorithm();
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
SolutionPrinter.print(vrp, Solutions.bestOf(solutions), Print.VERBOSE);
new Plotter(vrp,Solutions.bestOf(solutions)).setLabel(Label.ID).plot("output/jsprit_vrpnc1_noConstraints", "jsprit: noConstraints");
System.out.println(jm.timesAssigned);
GraphStreamViewer streamViewer = new GraphStreamViewer(vrp, Solutions.bestOf(solutions));
streamViewer.labelWith(GraphStreamViewer.Label.ID);
streamViewer.setRenderDelay(500).display();
}
public static String getResourceFileAsString(String fileName) {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
InputStream is = classLoader.getResourceAsStream(fileName);
if (is != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
}
return null;
}
}
pom.txt (1.9 KB)
Here is my pom file for future references