mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
add walkthrough
This commit is contained in:
parent
34651437a0
commit
d9a2973e66
2 changed files with 278 additions and 0 deletions
91
docs/Walkthrough Constraints.md
Normal file
91
docs/Walkthrough Constraints.md
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
It is assumed that you know the basics of the [applied algorithm](Meta-Heuristic.md). In the recreation-step each
|
||||
removed job is re-inserted into the ruined solution again (one after another). To actually insert a job, the algorithm
|
||||
calculates its "best" insertion position. This implies also to check the feasibility of the insertion step
|
||||
which is in turn dependent on constraints (such as capacity constraints).
|
||||
jsprit knows hard and soft constraints. Whereas hard constraints must be met and cannot be broken, soft constraints
|
||||
are always fulfilled but uses penalties to express "good" and "bad" insertions.
|
||||
|
||||
jsprit comes with built-in or default constraints (such as capacity and time-window constraints) and allows you to add
|
||||
custom constraints. However, you can also disable the default constraints. To add custom constraints use
|
||||
<code>core.algorithm.VehicleRoutingAlgorithmBuilder</code> to build an algorithm instead of
|
||||
<code>core.algorithm.io.VehicleRoutingAlgorithms</code>.
|
||||
|
||||
Note that
|
||||
|
||||
<pre><code>VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(routingProblem, "yourAlgorithmConfig");
|
||||
vraBuilder.addCoreConstraints();
|
||||
vraBuilder.addDefaultCostCalculators();
|
||||
VehicleRoutingAlgorithm vra = vraBuilder.build();
|
||||
</code></pre>
|
||||
|
||||
is equivalent to
|
||||
|
||||
<pre><code>VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(routingProblem, "yourAlgorithmConfig");;
|
||||
</code></pre>
|
||||
|
||||
To add custom constraints add the following lines:
|
||||
<pre><code>VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(routingProblem, "yourAlgorithmConfig");
|
||||
vraBuilder.addCoreConstraints();
|
||||
vraBuilder.addDefaultCostCalculators();
|
||||
|
||||
//add custom constraint
|
||||
StateManager stateManager = new StateManager(routingProblem.getTransportCosts());
|
||||
ConstraintManager constraintManager = new ConstraintManager(routingProblem, stateManager);
|
||||
constraintManager.addConstraint(customConstraint);
|
||||
vraBuilder.setStateAndConstraintManager(stateManager, constraintManager);
|
||||
|
||||
VehicleRoutingAlgorithm vra = vraBuilder.build();
|
||||
</code></pre>
|
||||
|
||||
|
||||
## Hard constraints
|
||||
|
||||
There are hard constraints at two different levels: at route and activity level.
|
||||
|
||||
A route is basically a sequence of activities. Each route has a start- and an end-activity, and in between other activities of type <code>core.problem.solution.route.activity.TourActivity</code>.
|
||||
|
||||
###<code>core.problem.constraint.HardRouteConstraint</code>
|
||||
A HardRouteConstraint indicates whether a specified job can be inserted into an existing route (along with a specified vehicle). To define it you need to implement the HardRouteConstraint-interface:
|
||||
|
||||
<pre><code>HardRouteConstraint constraint = new HardRouteConstraint(){
|
||||
|
||||
@Override
|
||||
public boolean fulfilled(JobInsertionContext iContext) {
|
||||
return true;
|
||||
};
|
||||
|
||||
};
|
||||
</code></pre>
|
||||
|
||||
The JobInsertionContext tells you the context of the insertion step, i.e. the specified job (<code>iContext.getJob()</code>) to be inserted into
|
||||
a specified route (<code>iContext.getRoute()</code>) as well as the vehicle
|
||||
that should be employed on that route (<code>iContext.getNewVehicle()</code>).
|
||||
|
||||
####Example:
|
||||
Assume a vehicle with id="1" is not allowed to serve a job with id="job1" (since it is for example too big to access the customer location). Such a constraint can be easily defined as follows:
|
||||
|
||||
<pre><code>final Job jobWithAccessConstraint = routingProblem.getJobs().get("job1");
|
||||
HardRouteConstraint accessConstraint = new HardRouteConstraint() {
|
||||
|
||||
@Override
|
||||
public boolean fulfilled(JobInsertionContext iContext) {
|
||||
if(iContext.getNewVehicle().getId().equals("1")){
|
||||
if(iContext.getJob()==jobWithAccessConstraint || iContext.getRoute().getTourActivities().servesJob(jobWithAccessConstraint)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
constraintManager.addConstraint(accessConstraint);
|
||||
</code></pre>
|
||||
|
||||
<strong>Note</strong> that if vehicleSwitches are not allowed, you are done with the first term <code>iContext.getJob()==jobWithAccessConstraint</code> in the above if-clause. If they are, you need to add the second term <code>iContext.getRoute().getTourActivities().servesJob(jobWithAccessConstraint</code> as well to prohibit the vehicle (id=1) to take over a route that already contains job1.
|
||||
|
||||
### core.problem.constraint.HardActivityConstraint
|
||||
to be documented ... (as long as it is not yet documented it might be helpful to see how the [service backhaul constraint](https://github.com/jsprit/jsprit/blob/master/jsprit-core/src/main/java/jsprit/core/problem/constraint/ServiceDeliveriesFirstConstraint.java) is implemented which you can add to the constraintManager much like the above access constraint)
|
||||
|
||||
## Soft constraints
|
||||
to be documented ... (as long as it is not yet documented the following examples might be helpful http://stackoverflow.com/questions/24447451/related-jobs-in-jsprit)
|
||||
187
docs/Walkthrough---Algorithm.md
Normal file
187
docs/Walkthrough---Algorithm.md
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#### Configure and create algorithm
|
||||
##### Per xml
|
||||
Structure of overall algorithm config:
|
||||
|
||||

|
||||
|
||||
Structure of overall (search) strategy:
|
||||
|
||||

|
||||
|
||||
Structure of individual search strategies and modules:
|
||||
|
||||

|
||||
|
||||
<pre><code>VehicleRoutingProblem problem = ...
|
||||
String myAlgorithmConfigXmlFilname = ...
|
||||
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(problem, myAlgorithmConfigXmlFilename);</code></pre>
|
||||
|
||||
##### In code
|
||||
|
||||
<pre><code>AlgorithmConfig myAlgorithmConfig = new AlgorithmConfig();
|
||||
XMLConfiguration xmlConfig = myAlgorithmConfig.getXMLConfiguration();
|
||||
xmlConfig.setProperty("iterations", 2000);
|
||||
xmlConfig.setProperty("construction.insertion[@name]","bestInsertion");
|
||||
|
||||
xmlConfig.setProperty("strategy.memory", 1);
|
||||
String searchStrategy = "strategy.searchStrategies.searchStrategy";
|
||||
|
||||
xmlConfig.setProperty(searchStrategy + "(0).selector[@name]","selectBest");
|
||||
xmlConfig.setProperty(searchStrategy + "(0).acceptor[@name]","schrimpfAcceptance");
|
||||
xmlConfig.setProperty(searchStrategy + "(0).acceptor.alpha","0.4");
|
||||
xmlConfig.setProperty(searchStrategy + "(0).acceptor.warmup","100");
|
||||
|
||||
xmlConfig.setProperty(searchStrategy + "(0).modules.module(0)[@name]","ruin_and_recreate");
|
||||
xmlConfig.setProperty(searchStrategy + "(0).modules.module(0).ruin[@name]","randomRuin");
|
||||
xmlConfig.setProperty(searchStrategy + "(0).modules.module(0).ruin.share","0.5");
|
||||
xmlConfig.setProperty(searchStrategy + "(0).modules.module(0).insertion[@name]","bestInsertion");
|
||||
xmlConfig.setProperty(searchStrategy + "(0).probability","0.5");
|
||||
|
||||
xmlConfig.setProperty(searchStrategy + "(1).selector[@name]","selectBest");
|
||||
xmlConfig.setProperty(searchStrategy + "(1).acceptor[@name]","schrimpfAcceptance");
|
||||
xmlConfig.setProperty(searchStrategy + "(1).modules.module(0)[@name]","ruin_and_recreate");
|
||||
xmlConfig.setProperty(searchStrategy + "(1).modules.module(0).ruin[@name]","radialRuin");
|
||||
xmlConfig.setProperty(searchStrategy + "(1).modules.module(0).ruin.share","0.3");
|
||||
xmlConfig.setProperty(searchStrategy + "(1).modules.module(0).insertion[@name]","bestInsertion");
|
||||
xmlConfig.setProperty(searchStrategy + "(1).probability","0.5");
|
||||
|
||||
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.createAlgorithm(problem,myAlgorithmConfig);
|
||||
</code></pre>
|
||||
|
||||
#### Search solution
|
||||
<pre><code>Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();</code></pre>
|
||||
|
||||
#### Overwrite iterations in code
|
||||
<pre><code>vra.setMaxIterations(nOfIterations);</code></pre>
|
||||
|
||||
#### Premature termination
|
||||
##### Time
|
||||
xml
|
||||
<pre><code><prematureBreak basedOn="time">
|
||||
<time>2.</time>
|
||||
</prematureBreak>
|
||||
</code></pre>
|
||||
in-code
|
||||
<pre><code>TimeTermination prematureTermination = new TimeTermination(2.); //in seconds
|
||||
vra.setPrematureAlgorithmTermination(prematureTermination);
|
||||
vra.addListener(prematureTermination);
|
||||
</code></pre>
|
||||
##### Iterations
|
||||
|
||||
xml
|
||||
<pre><code><prematureBreak basedOn="iterations">
|
||||
<iterations>200</iterations>
|
||||
</prematureBreak>
|
||||
</code></pre>
|
||||
|
||||
in-code
|
||||
<pre><code>vra.setPrematureAlgorithmTermination(new IterationWithoutImprovementTermination(200));
|
||||
</code></pre>
|
||||
|
||||
##### Variation Coefficient
|
||||
xml
|
||||
<pre><code><prematureBreak basedOn="variationCoefficient">
|
||||
<threshold>0.01</threshold>
|
||||
<iterations>50</iterations>
|
||||
</prematureBreak>
|
||||
</code></pre>
|
||||
in-code
|
||||
<pre><code>VariationCoefficientTermination prematureTermination = new VariationCoefficientTermination(50, 0.01);
|
||||
vra.setPrematureAlgorithmTermination(prematureTermination);
|
||||
vra.addListener(prematureTermination);
|
||||
</code></pre>
|
||||
|
||||
#### Add initial solution
|
||||
<pre><code>vra.addInitialSolution(initialSolution);</code></pre>
|
||||
|
||||
#### Add your own code, or listen to the algorithm
|
||||
The following figure shows the various entry points for your implementation.
|
||||
|
||||

|
||||
|
||||
core.algorithm.recreate.listener.InsertionListener in turn is parent to InsertionStartsListener, InsertionEndsListener, JobInsertedListener and VehicleSwitchedListener.
|
||||
|
||||
|
||||
Implement one or many listener(s) and register your implementation in the algorithm like that:
|
||||
<pre><code>IterationStartsListener iterationStartPrinter = new IterationStartsListener() {
|
||||
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
System.out.println("iteration " + i + " starts");
|
||||
}
|
||||
|
||||
};
|
||||
vra.addListener(iterationStartPrinter);
|
||||
</code></pre>
|
||||
Note that - depending on the listener - your implementation should be fast, otherwise it can significantly influence the performance of the algorithm.
|
||||
|
||||
#### Customize your algorithm with <code>core.algorithm.VehicleRoutingAlgorithmBuilder</code>
|
||||
To use the builder, you need to use 1.2.1-SNAPSHOT version.
|
||||
<pre><code>VehicleRoutingAlgorithmBuilder algorithmBuilder = new VehicleRoutingAlgorithmBuilder(problem, "myAlgorithmConfig.xml");</code></pre>
|
||||
|
||||
The basic structure of the meta-heuristic is still configured in the xml-file (myAlgorithmConfig.xml) or in AlgorithmConfig.java. However, you can set your own objective function and define your own constraints.
|
||||
|
||||
##### Set custom objective function
|
||||
By default, the sum of fixed and variable transportation costs are minimized. Thus if you do not set your own objective, the algorithm grabs the costs-parameters you defined in core.problem.vehicle.VehicleTypeImpl.java and calculates total transportation costs accordingly. If you want to define your own, make it like this
|
||||
|
||||
<pre><code>algorithmBuilder.setObjectiveFunction(objectiveFunction);
|
||||
</code></pre>
|
||||
|
||||
Note that if you set your own objective function, your insertion heuristic should insert the jobs according this function. Therefore you need to find appropriate soft constraints to penalyze bad and/or reward good insertion moves.
|
||||
|
||||
##### Use default cost-calculators
|
||||
<pre><code>algorithmBuilder.addDefaultCostCalculators();
|
||||
</code></pre>
|
||||
|
||||
This adds the default objective function and its corresponding insertion costs calculation to penalyze bad and/or reward good insertion moves.
|
||||
|
||||
##### Add default (core) constraints and updater
|
||||
<pre><code>algorithmBuilder.addCoreConstraints();
|
||||
</code></pre>
|
||||
|
||||
This basically adds capacity and time-window constraints.
|
||||
|
||||
##### Set your own <code>core.algorithm.state.StateManager</code>
|
||||
<pre><code>algorithmBuilder.setStateManager(stateManager);
|
||||
</code></pre>
|
||||
|
||||
##### Set your own <code>core.problem.constraint.ConstraintManager</code>
|
||||
<pre><code>algorithmBuilder.setStateAndConstraintManager(stateManager, constraintManager);
|
||||
</code></pre>
|
||||
|
||||
If you want to add your own constraints you need to define your own stateManager as well.
|
||||
|
||||
##### Build the algorithm
|
||||
<pre><code>VehicleRoutingAlgorithm vra = algorithmBuilder.build();
|
||||
</code></pre>
|
||||
|
||||
Note that
|
||||
|
||||
<pre><code>VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(routingProblem, "yourAlgorithmConfig");
|
||||
</code></pre>
|
||||
|
||||
is equivalent to
|
||||
|
||||
<pre><code>VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(routingProblem, "yourAlgorithmConfig");
|
||||
vraBuilder.addCoreConstraints();
|
||||
vraBuilder.addDefaultCostCalculators();
|
||||
VehicleRoutingAlgorithm vra = vraBuilder.build();
|
||||
</code></pre>
|
||||
|
||||
which is in turn equivalent to
|
||||
|
||||
<pre><code>VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(routingProblem, "yourAlgorithmConfig");
|
||||
|
||||
StateManager stateManager = new StateManager(problem.getTransportCosts());
|
||||
stateManager.updateLoadStates();
|
||||
stateManager.updateTimeWindowStates();
|
||||
|
||||
ConstraintManager constraintManager = new ConstraintManager(problem, stateManager);
|
||||
constraintManager.addLoadConstraint();
|
||||
constraintManager.addTimeWindowConstraint();
|
||||
|
||||
vraBuilder.setStateAndConstraintManager(stateManager, constraintManager);
|
||||
|
||||
vraBuilder.addDefaultCostCalculators();
|
||||
VehicleRoutingAlgorithm vra = vraBuilder.build();
|
||||
</code></pre>
|
||||
Loading…
Add table
Add a link
Reference in a new issue