mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
Merge branch 'master' into max-time-feature
# Conflicts: # jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Service.java # jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Shipment.java # jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/PickupTest.java # jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/ServiceTest.java # jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/ShipmentTest.java
This commit is contained in:
commit
b5998e1d93
100 changed files with 4103 additions and 2386 deletions
27
.travis.settings.xml
Normal file
27
.travis.settings.xml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<!--
|
||||
~ Licensed to GraphHopper GmbH under one or more contributor
|
||||
~ license agreements. See the NOTICE file distributed with this work for
|
||||
~ additional information regarding copyright ownership.
|
||||
~
|
||||
~ GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
~ Version 2.0 (the "License"); you may not use this file except in
|
||||
~ compliance with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||
<servers>
|
||||
<server>
|
||||
<id>packagecloud-graphhopper</id>
|
||||
<password>${env.PACKAGECLOUD_TOKEN}</password>
|
||||
</server>
|
||||
</servers>
|
||||
</settings>
|
||||
17
.travis.yml
17
.travis.yml
|
|
@ -4,3 +4,20 @@ jdk:
|
|||
- oraclejdk7
|
||||
- oraclejdk8
|
||||
|
||||
deploy:
|
||||
provider: script
|
||||
script: "cp .travis.settings.xml $HOME/.m2/settings.xml && mvn deploy"
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
||||
|
||||
# do not install anything instead return true via unix command true
|
||||
install: true
|
||||
script: mvn clean test
|
||||
notifications:
|
||||
email:
|
||||
- github@graphhopper.com
|
||||
|
||||
# enable container-based stack
|
||||
sudo: false
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
Change-log
|
||||
==========
|
||||
|
||||
**v1.7.2** @ 2017-06-08
|
||||
- see [Whats new](https://github.com/graphhopper/jsprit/blob/master/WHATS_NEW.md)
|
||||
|
||||
**v1.7.1** @ 2017-05-11
|
||||
- see [Whats new](https://github.com/graphhopper/jsprit/blob/master/WHATS_NEW.md)
|
||||
|
||||
**v1.7** @ 2017-01-12
|
||||
- see [Whats new](https://github.com/graphhopper/jsprit/blob/master/WHATS_NEW.md)
|
||||
|
||||
**v1.6.2** @ 2016-02-02
|
||||
|
||||
new features:
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
The following people have contributed code, bug fixes and ideas.
|
||||
|
||||
* [Abraham Gausachs](https://github.com/agausachs)
|
||||
* [Balage1551](https://github.com/balage1551)
|
||||
* [Giulio Collura](https://github.com/gcollura)
|
||||
* [Gwénaël Rault](https://github.com/braktar)
|
||||
* [Heinrich Filter](https://github.com/HeinrichFilter)
|
||||
* [jie31best](https://github.com/jie31best)
|
||||
* Josh Pilkington
|
||||
* [Julia Loikova](https://github.com/Jullil)
|
||||
* [muzuro](https://github.com/muzuro)
|
||||
|
|
|
|||
17
README.md
17
README.md
|
|
@ -2,8 +2,9 @@ jsprit
|
|||
======
|
||||
[](https://travis-ci.org/graphhopper/jsprit)
|
||||
|
||||
jsprit is a java based, open source toolkit for solving rich <a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem" target="_blank">traveling salesman</a> (TSP) and <a href="http://neo.lcc.uma.es/vrp/vehicle-routing-problem/" target="_blank">vehicle routing problems</a> (VRP).
|
||||
It is lightweight, flexible and easy-to-use, and based on a single all-purpose <a href="https://github.com/jsprit/jsprit/wiki/Meta-Heuristic" target="_blank">meta-heuristic</a> currently solving
|
||||
jsprit is a java based, open source toolkit for solving rich [Traveling Salesman Problems(TSP)](http://en.wikipedia.org/wiki/Travelling_salesman_problem") and [Vehicle Routing Problems(VRP)](http://neo.lcc.uma.es/vrp/vehicle-routing-problem/).
|
||||
It is lightweight, flexible and easy-to-use, and based on a single all-purpose [meta-heuristic](../docs/Meta-Heuristic.md) currently solving
|
||||
|
||||
- Capacitated VRP
|
||||
- Multiple Depot VRP
|
||||
- VRP with Time Windows
|
||||
|
|
@ -16,10 +17,10 @@ It is lightweight, flexible and easy-to-use, and based on a single all-purpose <
|
|||
- Various combination of these types
|
||||
|
||||
Setting up the problem, defining additional constraints, modifying the algorithms and visualising the discovered solutions is as easy and handy as
|
||||
reading classical VRP instances to benchmark your algorithm. It is fit for change and extension due to a modular design and a comprehensive set of unit and integration-tests. [More features ...](https://github.com/jsprit/jsprit/wiki/features)
|
||||
reading classical VRP instances to benchmark your algorithm. It is fit for change and extension due to a modular design and a comprehensive set of unit and integration-tests. [More features ...](../docs/Features.textile)
|
||||
|
||||
##Getting Started and Documentation
|
||||
Please visit [docs](https://github.com/graphhopper/jsprit/blob/master/docs/Home.md) to learn more. For older versions (<v1.7) use [old-docs](https://github.com/graphhopper/jsprit/blob/%3C1.7/docs/Home.md). The best way to get to know jsprit is by looking at [code examples](https://github.com/graphhopper/jsprit/tree/master/jsprit-examples/src/main/java/com/graphhopper/jsprit/examples).
|
||||
## Getting Started with Documentation
|
||||
Please visit [docs](https://github.com/graphhopper/jsprit/blob/master/docs/Home.md) to learn more.The best way to get to know jsprit is by looking at [code examples](https://github.com/graphhopper/jsprit/tree/master/jsprit-examples/src/main/java/com/graphhopper/jsprit/examples).
|
||||
|
||||
## Modules and Dependencies
|
||||
Please read [Notice.md](https://github.com/graphhopper/jsprit/blob/master/NOTICE.md) to get to know the direct dependencies of each module.
|
||||
|
|
@ -42,7 +43,7 @@ Developing this would be much more difficult without the help of [these companie
|
|||
## Contact
|
||||
|
||||
#### Mailing List:
|
||||
In the [mailing list](https://discuss.graphhopper.com/) ([old mailing list](https://groups.google.com/group/jsprit-mailing-list)) you can discuss jsprit related issues and you will probably get answers to your questions.
|
||||
In the [Graphhopper Forum ](https://discuss.graphhopper.com/) ([Also you can see the old mailing list](https://groups.google.com/group/jsprit-mailing-list)) you can discuss jsprit related issues and you will probably get answers to your questions.
|
||||
|
||||
#### Stackoverflow:
|
||||
You can also use [stackoverflow](http://stackoverflow.com/questions/tagged/jsprit) to discuss your issues. Tag it with <em>jsprit</em> then it is easier to keep track of your topic.
|
||||
|
|
@ -51,9 +52,7 @@ You can also use [stackoverflow](http://stackoverflow.com/questions/tagged/jspri
|
|||
For bugs, feature requests or similar use the [issue tracker](https://github.com/jsprit/jsprit/issues).
|
||||
|
||||
#### Email:
|
||||
If you cannot get help in the mailing list or you just do not want to discuss your topic publicly, send an email to:
|
||||
|
||||
info@graphhopper.com
|
||||
If you cannot get help in the mailing list or you just do not want to discuss your topic publicly, [contact us via mail](https://graphhopper.com/#contact)
|
||||
|
||||
|
||||
## About
|
||||
|
|
|
|||
17
WHATS_NEW.md
17
WHATS_NEW.md
|
|
@ -1,15 +1,30 @@
|
|||
WHATS NEW
|
||||
==========
|
||||
------------------------------
|
||||
<b>??</b> new release **v1.7**
|
||||
<b>2017-06-08</b> new release **v1.7.2**
|
||||
- one can now set custom properties/user defined data (see pr: https://github.com/graphhopper/jsprit/pull/348)
|
||||
|
||||
For example, if one wants to enrich a service with an arbitrary number of custom properties, set a map like this:
|
||||
|
||||
<pre><code>Service one = Service.Builder.newInstance("s").setLocation(Location.newInstance("loc"))
|
||||
.setUserData(new HashMap<String, Object>()).build();</code></pre>
|
||||
|
||||
<b>2017-05-11</b> new release **v1.7.1**
|
||||
- determine [reasons for unassigned jobs](https://github.com/graphhopper/jsprit/issues/180)
|
||||
- extend priority levels from 3 to 10 levels
|
||||
- a number of minor improvements
|
||||
|
||||
<b>2017-01-12</b> new release **v1.7**
|
||||
- move packages to [graphhopper.com](https://graphhopper.com/)
|
||||
- change license from GPLv3 to [Apache v2](https://github.com/graphhopper/jsprit/blob/master/LICENSE.md) to make it even more attractive for other developers and their commercial applications
|
||||
- pushed binaries to maven central, i.e. made it better accessible and we get rid of our own repo
|
||||
- outsourced various io operations, e.g. reading writing problem/algorithm to a new module called [jsprit-io](https://github.com/graphhopper/jsprit/tree/master/jsprit-io). this way the core is even more lightweight and less dependent on other libraries
|
||||
- switched from log4j to the [logger facade slf4j](http://www.slf4j.org/) to allow developers to plugin the logger of their choice
|
||||
- made it [much more memory efficient](https://github.com/graphhopper/jsprit/issues/230) for large problems
|
||||
- fixed [memory leak](https://github.com/graphhopper/jsprit/pull/282)
|
||||
- add [priority feature](https://github.com/graphhopper/jsprit/issues/242)
|
||||
- [refine exceptions](https://github.com/graphhopper/jsprit/issues/251) to get a clear separation of IllegalArgument and [IllegalState](https://stackoverflow.com/questions/12698275/whats-the-intended-use-of-illegalstateexception)
|
||||
- many further improvements (see https://github.com/graphhopper/jsprit/issues?q=is%3Aissue+is%3Aclosed)
|
||||
|
||||
<b>2016-02-02</b> new release **v1.6.2**
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
- Capacitated VRP<a href="https://github.com/jsprit/jsprit/wiki/Simple-Example"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"> </a><a href="https://github.com/jsprit/jsprit/wiki/Network-Based-VRPs"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/network_small.png" title="Code Example - NetworkBased VRP"></a><a href="https://github.com/jsprit/jsprit/wiki/Benchmark-CVRP"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/1372278707_table_chart.png" title="Benchmark"> </a>
|
||||
- Multiple Depot VRP <a href="https://github.com/jsprit/jsprit/wiki/Multiple-Depot-VRP"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a><a href="https://github.com/jsprit/jsprit/wiki/Benchmark-MDVRP"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/1372278707_table_chart.png" title="Benchmark"></a>
|
||||
- VRP with Time Windows<a href="https://github.com/jsprit/jsprit/wiki/VRP-with-time-windows-example"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a><a href="https://github.com/jsprit/jsprit/wiki/Benchmark-VRPTW"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/1372278707_table_chart.png" title="Benchmark"></a>
|
||||
- VRP with Backhauls (Deliveries first)<a href="https://github.com/jsprit/jsprit/wiki/VRP-with-backhauls-example"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a>
|
||||
- VRP with Backhauls (mixed Pickups and Deliveries)<a href="https://github.com/jsprit/jsprit/wiki/VRP-with-depot-bounded-pickups-and-deliveries"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a>
|
||||
- VRP with Pickups and Deliveries<a href="https://github.com/jsprit/jsprit/wiki/VRP-with-pickups-and-deliveries"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a>
|
||||
- VRP with Heterogeneous Fleet<a href="https://github.com/jsprit/jsprit/wiki/Heterogeneous-fleet"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a><a href="https://github.com/jsprit/jsprit/wiki/Benchmark-VRPH"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/1372278707_table_chart.png" title="Benchmark"></a>
|
||||
- Traveling Salesman Problem<a href="https://github.com/jsprit/jsprit/wiki/Traveling-Salesman-Problem"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a>
|
||||
- Dial-a-Ride Problem<a href="https://github.com/jsprit/jsprit/wiki/Dial-a-Ride-Problem"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a>
|
||||
- Capacitated VRP<a href="https://github.com/graphhopper/jsprit/blob/master/docs/Simple-Example.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"> </a><a href="https://github.com/jsprit/jsprit/wiki/Network-Based-VRPs.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/network_small.png" title="Code Example - NetworkBased VRP"></a><a href="https://github.com/jsprit/jsprit/wiki/Benchmark-CVRP.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/1372278707_table_chart.png" title="Benchmark"> </a>
|
||||
- Multiple Depot VRP <a href="https://github.com/graphhopper/jsprit/blob/master/docs/Multiple-Depot-VRP.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a><a href="https://github.com/jsprit/jsprit/wiki/Benchmark-MDVRP.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/1372278707_table_chart.png" title="Benchmark"></a>
|
||||
- VRP with Time Windows<a href="https://github.com/graphhopper/jsprit/blob/master/docs/VRP-with-time-windows-example.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a><a href="https://github.com/jsprit/jsprit/wiki/Benchmark-VRPTW"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/1372278707_table_chart.png" title="Benchmark"></a>
|
||||
- VRP with Backhauls (Deliveries first)<a href="https://github.com/graphhopper/jsprit/blob/master/docs/VRP-with-backhauls-example.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a>
|
||||
- VRP with Backhauls (mixed Pickups and Deliveries)<a href="https://github.com/graphhopper/jsprit/blob/master/docs/VRP-with-depot-bounded-pickups-and-deliveries.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a>
|
||||
- VRP with Pickups and Deliveries<a href="https://github.com/graphhopper/jsprit/blob/master/docs/Vrp-with-pickups-and-deliveries.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a>
|
||||
- VRP with Heterogeneous Fleet<a href="https://github.com/graphhopper/jsprit/blob/master/docs/Heterogeneous-Fleet.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a><a href="https://github.com/jsprit/jsprit/wiki/Benchmark-VRPH"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/1372278707_table_chart.png" title="Benchmark"></a>
|
||||
- Traveling Salesman Problem<a href="https://github.com/jsprit/jsprit/wiki/Traveling-Salesman-Problem.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a>
|
||||
- Dial-a-Ride Problem<a href="https://github.com/jsprit/jsprit/wiki/Dial-a-Ride-Problem.md"><img src="https://github.com/jsprit/misc-rep/raw/master/wiki-images/examples_small.png" title="Code Example"></a>
|
||||
|
|
@ -1 +1 @@
|
|||
You model a dial-a-ride problem much like a vehicle routing problem with pickups and deliveries. The capacity of vehicles can be interpreted as number of seats available. A shipment is here understood as a ride from one location to another (probably you want the shipment to have a capacity-demand of 1). See [VRP with pickups and deliveries](https://github.com/jsprit/jsprit/wiki/VRP-with-pickups-and-deliveries).
|
||||
You model a dial-a-ride problem much like a vehicle routing problem with pickups and deliveries. The capacity of vehicles can be interpreted as number of seats available. A shipment is here understood as a ride from one location to another (probably you want the shipment to have a capacity-demand of 1). See [VRP with pickups and deliveries](../docs/Vrp-with-pickups-and-deliveries.md).
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#### Requirements
|
||||
jsprit requires the Java 2 platform (JDK version 1.7.0 or later).
|
||||
jsprit requires Java 1.7.0 or later.
|
||||
|
||||
#### Modules
|
||||
jsprit is a multi-module project and consists of:
|
||||
|
|
@ -12,12 +12,15 @@ jsprit is a multi-module project and consists of:
|
|||
#### Maven way
|
||||
If you want to use the latest release of jsprit-core, add the following lines to your pom:
|
||||
|
||||
<pre><code><dependency>
|
||||
```
|
||||
<dependency>
|
||||
<groupId>com.graphhopper</groupId>
|
||||
<artifactId>jsprit-core</artifactId>
|
||||
<version>1.7-RC1</version>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
Find the latest versions here: [mvn repository](https://mvnrepository.com/artifact/com.graphhopper/jsprit-core)
|
||||
|
||||
#### Build yourself
|
||||
If you want to build the master branch yourself, do this:
|
||||
|
|
@ -37,6 +40,7 @@ the following documentation is recommended:
|
|||
Here you learn to setup the Java environment and an Integrated Development Environment (IDE). In the subsection <em>Adding Jars to your Project</em> you learn to integrate external libraries in your project. Just copy/paste the above jsprit releases/snapshots to your pom.xml instead of the GeoTools-artifacts.
|
||||
|
||||
#### If you do not want Maven
|
||||
|
||||
to manage your dependencies, go to [maven central](https://search.maven.org/), search for jsprit and download the latest binaries to put them into your classpath.
|
||||
|
||||
Go ahead and show me a [simple example](Simple-Example.md) of how to setup and solve a vehicle routing problem.
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
#### [Multiple Depot VRP](Multiple-Depot-VRP)
|
||||
#### [Multiple Depot VRP](Multiple-Depot-VRP.md)
|
||||
- setting up a VRP with Multiple Depots
|
||||
- defining depots, vehicles and their types
|
||||
- dealing with finite fleet size
|
||||
|
||||
#### [VRP with time windows](VRP-with-time-windows-example)
|
||||
#### [VRP with time windows](VRP-with-time-windows-example.md)
|
||||
- defining and creating vehicles and their types
|
||||
- defining services with time-windows and service times
|
||||
- defining a problem with infinite fleet-size
|
||||
- reading, creating and running an algorithm
|
||||
|
||||
#### [VRP with backhauls](VRP-with-backhauls-example)
|
||||
#### [VRP with backhauls](VRP-with-backhauls-example.md)
|
||||
- defining and creating pickup and deliveries
|
||||
- defining backhaul constraint
|
||||
|
||||
#### [VRP with backhauls (with mixed pickup and deliveries)](VRP-with-depot-bounded-pickups-and-deliveries)
|
||||
#### [VRP with backhauls (with mixed pickup and deliveries)](VRP-with-depot-bounded-pickups-and-deliveries.md)
|
||||
- defining and creating depot-bounded pickups and deliveries
|
||||
|
||||
#### [VRP with pickup and delivieries](VRP-with-pickups-and-deliveries)
|
||||
#### [VRP with pickup and delivieries](Vrp-with-pickups-and-deliveries.md)
|
||||
- defining and creating pickups and deliveries
|
||||
|
||||
#### [VRP with heterogeneous fleet](Heterogeneous-Fleet)
|
||||
#### [VRP with heterogeneous fleet](Heterogeneous-Fleet.md)
|
||||
- illustrating different problem types,
|
||||
- specifying heterogeneous fleet with its vehicles and vehicle-types,
|
||||
- specifying the algorithm,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ First, build a vehicle with its vehicle-type:
|
|||
|
||||
<pre><code>/*
|
||||
* get a vehicle type-builder and build a type with the typeId "vehicleType" and a capacity of 2
|
||||
* you are free to add an arbitrary number of capacity dimensions with .addCacpacityDimension(dimensionIndex,dimensionValue)
|
||||
* you are free to add an arbitrary number of capacity dimensions with .addCapacityDimension(dimensionIndex,dimensionValue)
|
||||
*/
|
||||
final int WEIGHT_INDEX = 0;
|
||||
VehicleTypeImpl.Builder vehicleTypeBuilder = VehicleTypeImpl.Builder.newInstance("vehicleType").addCapacityDimension(WEIGHT_INDEX,2);
|
||||
|
|
|
|||
|
|
@ -108,4 +108,4 @@ Collection<VehicleRoutingProblemSolution> solutions = algorithm.searchSolutions(
|
|||
VehicleRoutingProblemSolution bestSolution = Solutions.bestOf(solutions);
|
||||
</code></pre>
|
||||
|
||||
Please visit <a href="https://github.com/jsprit/jsprit/wiki/Simple-Example">Simple Example</a> to get to know how you can analyse the solution.
|
||||
Please visit [Simple Example](https://github.com/graphhopper/jsprit/blob/master/jsprit-examples/src/main/java/com/graphhopper/jsprit/examples/SimpleExample.java) to get to know how you can analyse the solution.
|
||||
|
|
@ -2,8 +2,11 @@ It is assumed that you know the basics of the [applied algorithm](Meta-Heuristic
|
|||
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 knows hard and soft constraints.
|
||||
|
||||
- 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
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
<parent>
|
||||
<groupId>com.graphhopper</groupId>
|
||||
<artifactId>jsprit</artifactId>
|
||||
<version>1.6.3-SNAPSHOT</version>
|
||||
<version>1.7.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jsprit-analysis</artifactId>
|
||||
|
|
|
|||
|
|
@ -1,475 +0,0 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.graphhopper.jsprit.analysis.toolbox;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithmFactory;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||
import com.graphhopper.jsprit.core.util.BenchmarkInstance;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
public class ComputationalLaboratory {
|
||||
|
||||
public static interface LabListener {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener-interface to listen to calculation.
|
||||
* <p>
|
||||
* <p>Note that calculations are run concurrently, i.e. a unique task that is distributed to an available thread is
|
||||
* {algorithm, instance, run}.
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
public static interface CalculationListener extends LabListener {
|
||||
|
||||
public void calculationStarts(final BenchmarkInstance p, final String algorithmName, final VehicleRoutingAlgorithm algorithm, final int run);
|
||||
|
||||
public void calculationEnds(final BenchmarkInstance p, final String algorithmName, final VehicleRoutingAlgorithm algorithm, final int run, final Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
}
|
||||
|
||||
public static interface LabStartsAndEndsListener extends LabListener {
|
||||
|
||||
public void labStarts(List<BenchmarkInstance> instances, int noAlgorithms, int runs);
|
||||
|
||||
public void labEnds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects whatever indicators you require by algorithmName, instanceName, run and indicator.
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
public static class DataCollector {
|
||||
|
||||
public static class Key {
|
||||
private String instanceName;
|
||||
private String algorithmName;
|
||||
private int run;
|
||||
private String indicatorName;
|
||||
|
||||
public Key(String instanceName, String algorithmName, int run, String indicatorName) {
|
||||
super();
|
||||
this.instanceName = instanceName;
|
||||
this.algorithmName = algorithmName;
|
||||
this.run = run;
|
||||
this.indicatorName = indicatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime
|
||||
* result
|
||||
+ ((algorithmName == null) ? 0 : algorithmName
|
||||
.hashCode());
|
||||
result = prime
|
||||
* result
|
||||
+ ((indicatorName == null) ? 0 : indicatorName
|
||||
.hashCode());
|
||||
result = prime
|
||||
* result
|
||||
+ ((instanceName == null) ? 0 : instanceName.hashCode());
|
||||
result = prime * result + run;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Key other = (Key) obj;
|
||||
if (algorithmName == null) {
|
||||
if (other.algorithmName != null)
|
||||
return false;
|
||||
} else if (!algorithmName.equals(other.algorithmName))
|
||||
return false;
|
||||
if (indicatorName == null) {
|
||||
if (other.indicatorName != null)
|
||||
return false;
|
||||
} else if (!indicatorName.equals(other.indicatorName))
|
||||
return false;
|
||||
if (instanceName == null) {
|
||||
if (other.instanceName != null)
|
||||
return false;
|
||||
} else if (!instanceName.equals(other.instanceName))
|
||||
return false;
|
||||
if (run != other.run)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getInstanceName() {
|
||||
return instanceName;
|
||||
}
|
||||
|
||||
public String getAlgorithmName() {
|
||||
return algorithmName;
|
||||
}
|
||||
|
||||
public int getRun() {
|
||||
return run;
|
||||
}
|
||||
|
||||
public String getIndicatorName() {
|
||||
return indicatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[algorithm=" + algorithmName + "][instance=" + instanceName + "][run=" + run + "][indicator=" + indicatorName + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final static String SOLUTION_INDICATOR_NAME = "vehicle-routing-problem-solution";
|
||||
|
||||
private ConcurrentHashMap<Key, Double> data = new ConcurrentHashMap<ComputationalLaboratory.DataCollector.Key, Double>();
|
||||
|
||||
private ConcurrentHashMap<Key, VehicleRoutingProblemSolution> solutions = new ConcurrentHashMap<ComputationalLaboratory.DataCollector.Key, VehicleRoutingProblemSolution>();
|
||||
|
||||
/**
|
||||
* Adds a single date by instanceName, algorithmName, run and indicatorName.
|
||||
* <p>If there is already an entry for this instance, algorithm, run and indicatorName, it is overwritten.
|
||||
*
|
||||
* @param instanceName
|
||||
* @param algorithmName
|
||||
* @param run
|
||||
* @param indicatorName
|
||||
* @param value
|
||||
*/
|
||||
public void addDate(String instanceName, String algorithmName, int run, String indicatorName, double value) {
|
||||
if (indicatorName.equals(SOLUTION_INDICATOR_NAME))
|
||||
throw new IllegalArgumentException(indicatorName + " is already used internally. please choose another indicator-name.");
|
||||
Key key = new Key(instanceName, algorithmName, run, indicatorName);
|
||||
data.put(key, value);
|
||||
}
|
||||
|
||||
public void addSolution(String instanceName, String algorithmName, int run, VehicleRoutingProblemSolution solution) {
|
||||
Key key = new Key(instanceName, algorithmName, run, SOLUTION_INDICATOR_NAME);
|
||||
solutions.put(key, solution);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collections of indicator values representing the calculated values of individual runs.
|
||||
*
|
||||
* @param instanceName
|
||||
* @param algorithmName
|
||||
* @param indicator
|
||||
* @return
|
||||
*/
|
||||
public Collection<Double> getData(String instanceName, String algorithmName, String indicator) {
|
||||
List<Double> values = new ArrayList<Double>();
|
||||
for (Key key : data.keySet()) {
|
||||
if (key.getAlgorithmName().equals(algorithmName) && key.getInstanceName().equals(instanceName) && key.getIndicatorName().equals(indicator)) {
|
||||
values.add(data.get(key));
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns indicator value.
|
||||
*
|
||||
* @param instanceName
|
||||
* @param algorithmName
|
||||
* @param run
|
||||
* @param indicator
|
||||
* @return
|
||||
*/
|
||||
public Double getDate(String instanceName, String algorithmName, int run, String indicator) {
|
||||
return data.get(new Key(instanceName, algorithmName, run, indicator));
|
||||
}
|
||||
|
||||
public VehicleRoutingProblemSolution getSolution(String instanceName, String algorithmName, int run) {
|
||||
return solutions.get(new Key(instanceName, algorithmName, run, "solution"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all keys that have been created. A key is a unique combination of algorithmName, instanceName, run and indicator.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<Key> getDataKeySet() {
|
||||
return data.keySet();
|
||||
}
|
||||
|
||||
public Set<Key> getSolutionKeySet() {
|
||||
return solutions.keySet();
|
||||
}
|
||||
|
||||
public VehicleRoutingProblemSolution getSolution(Key solutionKey) {
|
||||
return solutions.get(solutionKey);
|
||||
}
|
||||
|
||||
public Collection<VehicleRoutingProblemSolution> getSolutions() {
|
||||
return solutions.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns date associated to specified key.
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Double getData(Key key) {
|
||||
return data.get(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class Algorithm {
|
||||
|
||||
private String name;
|
||||
|
||||
private VehicleRoutingAlgorithmFactory factory;
|
||||
|
||||
public Algorithm(String name, VehicleRoutingAlgorithmFactory factory) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<BenchmarkInstance> benchmarkInstances = new ArrayList<BenchmarkInstance>();
|
||||
|
||||
private int runs = 1;
|
||||
|
||||
private Collection<CalculationListener> listeners = new ArrayList<ComputationalLaboratory.CalculationListener>();
|
||||
|
||||
private Collection<LabStartsAndEndsListener> startsAndEndslisteners = new ArrayList<LabStartsAndEndsListener>();
|
||||
|
||||
private List<Algorithm> algorithms = new ArrayList<ComputationalLaboratory.Algorithm>();
|
||||
|
||||
private Set<String> algorithmNames = new HashSet<String>();
|
||||
|
||||
private Set<String> instanceNames = new HashSet<String>();
|
||||
|
||||
private int threads = 1;
|
||||
|
||||
public ComputationalLaboratory() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds algorithmFactory by name.
|
||||
*
|
||||
* @param name
|
||||
* @param factory
|
||||
* @throws IllegalStateException if there is already an algorithmFactory with the same name
|
||||
*/
|
||||
public void addAlgorithmFactory(String name, VehicleRoutingAlgorithmFactory factory) {
|
||||
if (algorithmNames.contains(name))
|
||||
throw new IllegalStateException("there is already a algorithmFactory with the same name (algorithmName=" + name + "). unique names are required.");
|
||||
algorithms.add(new Algorithm(name, factory));
|
||||
algorithmNames.add(name);
|
||||
}
|
||||
|
||||
public Collection<String> getAlgorithmNames() {
|
||||
return algorithmNames;
|
||||
}
|
||||
|
||||
public Collection<String> getInstanceNames() {
|
||||
return instanceNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds instance by name.
|
||||
*
|
||||
* @param name
|
||||
* @param problem
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addInstance(String name, VehicleRoutingProblem problem) {
|
||||
if (benchmarkInstances.contains(name))
|
||||
throw new IllegalStateException("there is already an instance with the same name (instanceName=" + name + "). unique names are required.");
|
||||
benchmarkInstances.add(new BenchmarkInstance(name, problem, null, null));
|
||||
instanceNames.add(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds instance.
|
||||
*
|
||||
* @param instance the instance to be added
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addInstance(BenchmarkInstance instance) {
|
||||
if (benchmarkInstances.contains(instance.name))
|
||||
throw new IllegalStateException("there is already an instance with the same name (instanceName=" + instance.name + "). unique names are required.");
|
||||
benchmarkInstances.add(instance);
|
||||
instanceNames.add(instance.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds collection of instances.
|
||||
*
|
||||
* @param instances collection of instances to be added
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addAllInstances(Collection<BenchmarkInstance> instances) {
|
||||
for (BenchmarkInstance i : instances) {
|
||||
addInstance(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds instance by name, and with best known results.
|
||||
*
|
||||
* @param name
|
||||
* @param problem
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addInstance(String name, VehicleRoutingProblem problem, Double bestKnownResult, Double bestKnownVehicles) {
|
||||
addInstance(new BenchmarkInstance(name, problem, bestKnownResult, bestKnownVehicles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds listener to listen computational experiments.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void addListener(LabListener listener) {
|
||||
if (listener instanceof CalculationListener) {
|
||||
listeners.add((CalculationListener) listener);
|
||||
}
|
||||
if (listener instanceof LabStartsAndEndsListener) {
|
||||
startsAndEndslisteners.add((LabStartsAndEndsListener) listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets nuOfRuns with same algorithm on same instance.
|
||||
* <p>Default is 1
|
||||
*
|
||||
* @param runs
|
||||
*/
|
||||
public void setNuOfRuns(int runs) {
|
||||
this.runs = runs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs experiments.
|
||||
* <p>
|
||||
* <p>If nuThreads > 1 it runs them concurrently, i.e. individual runs are distributed to available threads. Therefore
|
||||
* a unique task is defined by its algorithmName, instanceName and its runNumber.
|
||||
* <p>If you have one algorithm called "myAlgorithm" and one instance called "myInstance", and you need to run "myAlgorithm" on "myInstance" three times
|
||||
* with three threads then "myAlgorithm","myInstance",run1 runs on the first thread, "myAlgorithm", "myInstance", run2 on the second etc.
|
||||
* <p>You can register whatever analysisTool you require by implementing and registering CalculationListener. Then your tool is informed just
|
||||
* before a calculation starts as well as just after a calculation has been finished.
|
||||
*
|
||||
* @throws IllegalStateException if either no algorithm or no instance has been specified
|
||||
* @see CalculationListener
|
||||
*/
|
||||
public void run() {
|
||||
if (algorithms.isEmpty()) {
|
||||
throw new IllegalStateException("no algorithm specified. at least one algorithm needs to be specified.");
|
||||
}
|
||||
if (benchmarkInstances.isEmpty()) {
|
||||
throw new IllegalStateException("no instance specified. at least one instance needs to be specified.");
|
||||
}
|
||||
informStart();
|
||||
System.out.println("start benchmarking [nuAlgorithms=" + algorithms.size() + "][nuInstances=" + benchmarkInstances.size() + "][runsPerInstance=" + runs + "]");
|
||||
double startTime = System.currentTimeMillis();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(threads);
|
||||
for (final Algorithm algorithm : algorithms) {
|
||||
for (final BenchmarkInstance p : benchmarkInstances) {
|
||||
for (int run = 0; run < runs; run++) {
|
||||
final int r = run;
|
||||
try {
|
||||
executor.submit(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
runAlgorithm(p, algorithm, r + 1);
|
||||
}
|
||||
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println("benchmarking done [time=" + (System.currentTimeMillis() - startTime) / 1000 + "sec]");
|
||||
informEnd();
|
||||
}
|
||||
|
||||
private void informEnd() {
|
||||
for (LabStartsAndEndsListener l : startsAndEndslisteners) {
|
||||
l.labEnds();
|
||||
}
|
||||
}
|
||||
|
||||
private void informStart() {
|
||||
for (LabStartsAndEndsListener l : startsAndEndslisteners) {
|
||||
l.labStarts(benchmarkInstances, algorithms.size(), runs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets number of threads.
|
||||
* <p>By default: <code>nuThreads = Runtime.getRuntime().availableProcessors()+1</code>
|
||||
*
|
||||
* @param threads
|
||||
*/
|
||||
public void setThreads(int threads) {
|
||||
this.threads = threads;
|
||||
}
|
||||
|
||||
private void runAlgorithm(BenchmarkInstance p, Algorithm algorithm, int run) {
|
||||
System.out.println("[algorithm=" + algorithm.name + "][instance=" + p.name + "][run=" + run + "][status=start]");
|
||||
VehicleRoutingAlgorithm vra = algorithm.factory.createAlgorithm(p.vrp);
|
||||
informCalculationStarts(p, algorithm.name, vra, run);
|
||||
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
||||
System.out.println("[algorithm=" + algorithm.name + "][instance=" + p.name + "][run=" + run + "][status=finished]");
|
||||
informCalculationsEnds(p, algorithm.name, vra, run, solutions);
|
||||
}
|
||||
|
||||
private void informCalculationStarts(BenchmarkInstance p, String name, VehicleRoutingAlgorithm vra, int run) {
|
||||
for (CalculationListener l : listeners) l.calculationStarts(p, name, vra, run);
|
||||
}
|
||||
|
||||
private void informCalculationsEnds(BenchmarkInstance p, String name, VehicleRoutingAlgorithm vra, int run,
|
||||
Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for (CalculationListener l : listeners) l.calculationEnds(p, name, vra, run, solutions);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.analysis.toolbox;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.SearchStrategy;
|
||||
import com.graphhopper.jsprit.core.algorithm.listener.AlgorithmEndsListener;
|
||||
import com.graphhopper.jsprit.core.algorithm.listener.IterationStartsListener;
|
||||
import com.graphhopper.jsprit.core.algorithm.listener.StrategySelectedListener;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 27/04/17.
|
||||
*/
|
||||
public class StrategyAnalyser implements AlgorithmEndsListener, StrategySelectedListener, IterationStartsListener {
|
||||
|
||||
|
||||
public static class Strategy {
|
||||
|
||||
private final String id;
|
||||
|
||||
private int selected = 0;
|
||||
|
||||
private int improved = 0;
|
||||
|
||||
private int countNewSolution = 0;
|
||||
|
||||
private List<Double> improvements = new ArrayList<>();
|
||||
|
||||
public Strategy(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void selected() {
|
||||
selected++;
|
||||
}
|
||||
|
||||
public void improvedSolution(double improvement) {
|
||||
improved++;
|
||||
improvements.add(improvement);
|
||||
}
|
||||
|
||||
public void newSolution() {
|
||||
countNewSolution++;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getCountSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
public int getCountImproved() {
|
||||
return improved;
|
||||
}
|
||||
|
||||
public int getCountNewSolution() {
|
||||
return countNewSolution;
|
||||
}
|
||||
|
||||
public List<Double> getImprovements() {
|
||||
return improvements;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Strategy> strategyMap = new HashMap<>();
|
||||
|
||||
private Collection<VehicleRoutingProblemSolution> last;
|
||||
|
||||
private Writer out;
|
||||
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
last = new ArrayList<>(solutions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informSelectedStrategy(SearchStrategy.DiscoveredSolution discoveredSolution, VehicleRoutingProblem vehicleRoutingProblem, Collection<VehicleRoutingProblemSolution> vehicleRoutingProblemSolutions) {
|
||||
String strategyId = discoveredSolution.getStrategyId();
|
||||
if (!strategyMap.containsKey(strategyId)) {
|
||||
strategyMap.put(strategyId, new Strategy(strategyId));
|
||||
}
|
||||
Strategy strategy = strategyMap.get(strategyId);
|
||||
strategy.selected();
|
||||
if (discoveredSolution.isAccepted()) strategy.newSolution();
|
||||
if (isBetter(vehicleRoutingProblemSolutions, last)) {
|
||||
strategy.improvedSolution(getImprovement(vehicleRoutingProblemSolutions, last));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void setOutWriter(Writer out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
if (out == null) out = new PrintWriter(System.out);
|
||||
try {
|
||||
for (String stratId : strategyMap.keySet()) {
|
||||
StrategyAnalyser.Strategy strategy = strategyMap.get(stratId);
|
||||
out.write("id: " + stratId + ", #selected: " + strategy.getCountSelected() + ", #newSolutions: " + strategy.getCountNewSolution()
|
||||
+ ", #improvedSolutions: " + strategy.getCountImproved() + ", improvements: " + strategy.getImprovements().toString() + "\n");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
try {
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private double getImprovement(Collection<VehicleRoutingProblemSolution> vehicleRoutingProblemSolutions, Collection<VehicleRoutingProblemSolution> last) {
|
||||
for (VehicleRoutingProblemSolution solution : vehicleRoutingProblemSolutions) {
|
||||
for (VehicleRoutingProblemSolution lastSolution : last) {
|
||||
if (solution.getCost() < lastSolution.getCost())
|
||||
return Math.round(lastSolution.getCost() - solution.getCost());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private boolean isBetter(Collection<VehicleRoutingProblemSolution> vehicleRoutingProblemSolutions, Collection<VehicleRoutingProblemSolution> last) {
|
||||
for (VehicleRoutingProblemSolution solution : vehicleRoutingProblemSolutions) {
|
||||
for (VehicleRoutingProblemSolution lastSolution : last) {
|
||||
if (solution.getCost() < lastSolution.getCost()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map<String, Strategy> getStrategies() {
|
||||
return strategyMap;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,257 +0,0 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.graphhopper.jsprit.analysis.util;
|
||||
|
||||
import com.graphhopper.jsprit.core.util.BenchmarkResult;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
public class HtmlBenchmarkTableWriter implements BenchmarkWriter {
|
||||
|
||||
private String filename;
|
||||
|
||||
public HtmlBenchmarkTableWriter(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Collection<BenchmarkResult> results) {
|
||||
|
||||
try {
|
||||
BufferedWriter writer = new BufferedWriter(new FileWriter(new File(filename)));
|
||||
writer.write(openTable() + newline());
|
||||
//table head
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(head("inst") + newline());
|
||||
writer.write(head("runs") + newline());
|
||||
writer.write(head("Ø time [sec]") + newline());
|
||||
writer.write(head("results", 4));
|
||||
writer.write(head("vehicles", 4));
|
||||
writer.write(head("res*") + newline());
|
||||
writer.write(head("veh*") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("best") + newline());
|
||||
writer.write(head("avg") + newline());
|
||||
writer.write(head("worst") + newline());
|
||||
writer.write(head("stdev") + newline());
|
||||
writer.write(head("best") + newline());
|
||||
writer.write(head("avg") + newline());
|
||||
writer.write(head("worst") + newline());
|
||||
writer.write(head("stdev") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
//data
|
||||
double sum_avg_time = 0.0;
|
||||
double sum_best_result = 0.0;
|
||||
double sum_avg_result = 0.0;
|
||||
double sum_worst_result = 0.0;
|
||||
double sum_dev_result = 0.0;
|
||||
|
||||
double sum_best_veh = 0.0;
|
||||
double sum_avg_veh = 0.0;
|
||||
double sum_worst_veh = 0.0;
|
||||
double sum_dev_veh = 0.0;
|
||||
|
||||
Integer runs = null;
|
||||
Double sum_res_star = null;
|
||||
Double sum_veh_star = null;
|
||||
|
||||
for (BenchmarkResult result : results) {
|
||||
if (runs == null) runs = result.runs;
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(date(result.instance.name) + newline());
|
||||
writer.write(date(Integer.valueOf(result.runs).toString()) + newline());
|
||||
|
||||
Double avg_time = round(result.getTimesStats().getMean(), 2);
|
||||
writer.write(date(Double.valueOf(avg_time).toString()) + newline());
|
||||
//bestRes
|
||||
Double best_result = round(result.getResultStats().getMin(), 2);
|
||||
writer.write(date(Double.valueOf(best_result).toString()) + newline());
|
||||
//avgRes
|
||||
Double avg_result = round(result.getResultStats().getMean(), 2);
|
||||
writer.write(date(Double.valueOf(avg_result).toString()) + newline());
|
||||
//worstRes
|
||||
Double worst_result = round(result.getResultStats().getMax(), 2);
|
||||
writer.write(date(Double.valueOf(worst_result).toString()) + newline());
|
||||
//stdevRes
|
||||
Double std_result = round(result.getResultStats().getStandardDeviation(), 2);
|
||||
writer.write(date(Double.valueOf(std_result).toString()) + newline());
|
||||
//bestVeh
|
||||
Double best_vehicle = round(result.getVehicleStats().getMin(), 2);
|
||||
writer.write(date(Double.valueOf(best_vehicle).toString()) + newline());
|
||||
//avgVeh
|
||||
Double avg_vehicle = round(result.getVehicleStats().getMean(), 2);
|
||||
writer.write(date(Double.valueOf(avg_vehicle).toString()) + newline());
|
||||
//worstVeh
|
||||
Double worst_vehicle = round(result.getVehicleStats().getMax(), 2);
|
||||
writer.write(date(Double.valueOf(worst_vehicle).toString()) + newline());
|
||||
//stdevVeh
|
||||
Double std_vehicle = round(result.getVehicleStats().getStandardDeviation(), 2);
|
||||
writer.write(date(Double.valueOf(std_vehicle).toString()) + newline());
|
||||
//bestKnownRes
|
||||
writer.write(date("" + result.instance.bestKnownResult + newline()));
|
||||
//bestKnownVeh
|
||||
writer.write(date("" + result.instance.bestKnownVehicles + newline()));
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
sum_avg_time += avg_time;
|
||||
sum_best_result += best_result;
|
||||
sum_avg_result += avg_result;
|
||||
sum_worst_result += worst_result;
|
||||
sum_dev_result += std_result;
|
||||
|
||||
sum_best_veh += best_vehicle;
|
||||
sum_avg_veh += avg_vehicle;
|
||||
sum_worst_veh += worst_vehicle;
|
||||
sum_dev_veh += std_vehicle;
|
||||
|
||||
if (result.instance.bestKnownResult != null) {
|
||||
if (sum_res_star == null) sum_res_star = result.instance.bestKnownResult;
|
||||
else sum_res_star += result.instance.bestKnownResult;
|
||||
}
|
||||
if (result.instance.bestKnownVehicles != null) {
|
||||
if (sum_veh_star == null) sum_veh_star = result.instance.bestKnownVehicles;
|
||||
else sum_veh_star += result.instance.bestKnownVehicles;
|
||||
}
|
||||
|
||||
}
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(date("Ø") + newline());
|
||||
writer.write(date("" + runs) + newline());
|
||||
|
||||
Double average_time = round(sum_avg_time / (double) results.size(), 2);
|
||||
writer.write(date(Double.valueOf(average_time).toString()) + newline());
|
||||
//bestRes
|
||||
writer.write(date(Double.valueOf(round(sum_best_result / (double) results.size(), 2)).toString()) + newline());
|
||||
//avgRes
|
||||
Double average_result = round(sum_avg_result / (double) results.size(), 2);
|
||||
writer.write(date(Double.valueOf(average_result).toString()) + newline());
|
||||
//worstRes
|
||||
writer.write(date(Double.valueOf(round(sum_worst_result / (double) results.size(), 2)).toString()) + newline());
|
||||
//stdevRes
|
||||
writer.write(date(Double.valueOf(round(sum_dev_result / (double) results.size(), 2)).toString()) + newline());
|
||||
//bestVeh
|
||||
writer.write(date(Double.valueOf(round(sum_best_veh / (double) results.size(), 2)).toString()) + newline());
|
||||
//avgVeh
|
||||
Double average_vehicles = round(sum_avg_veh / (double) results.size(), 2);
|
||||
writer.write(date(Double.valueOf(average_vehicles).toString()) + newline());
|
||||
//worstVeh
|
||||
writer.write(date(Double.valueOf(round(sum_worst_veh / (double) results.size(), 2)).toString()) + newline());
|
||||
//stdevVeh
|
||||
writer.write(date(Double.valueOf(round(sum_dev_veh / (double) results.size(), 2)).toString()) + newline());
|
||||
//bestKnownRes
|
||||
Double delta_res = null;
|
||||
if (sum_res_star != null) {
|
||||
writer.write(date(Double.valueOf(round(sum_res_star.doubleValue() / (double) results.size(), 2)).toString()) + newline());
|
||||
delta_res = (sum_avg_result / sum_res_star - 1) * 100;
|
||||
} else writer.write(date("null") + newline());
|
||||
//bestKnownVeh
|
||||
Double delta_veh = null;
|
||||
if (sum_veh_star != null) {
|
||||
writer.write(date(Double.valueOf(round(sum_veh_star.doubleValue() / (double) results.size(), 2)).toString()) + newline());
|
||||
delta_veh = (sum_avg_veh - sum_veh_star) / (double) results.size();
|
||||
} else writer.write(date("null") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
writer.write(closeTable() + newline());
|
||||
|
||||
writer.write("avg. percentage deviation to best-known result: " + round(delta_res, 2) + newline() + newline());
|
||||
writer.write("avg. absolute deviation to best-known vehicles: " + round(delta_veh, 2) + newline());
|
||||
|
||||
writer.write(openTable() + newline());
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date(Double.valueOf(average_time).toString(), "align=\"right\"") + newline());
|
||||
writer.write(date(Double.valueOf(average_result).toString(), "align=\"right\"") + newline());
|
||||
writer.write(date(Double.valueOf(average_vehicles).toString(), "align=\"right\"") + newline());
|
||||
if (delta_res != null) {
|
||||
writer.write(date(Double.valueOf(round(delta_res, 2)).toString(), "align=\"right\"") + newline());
|
||||
} else writer.write(date("n.a.") + newline());
|
||||
if (delta_veh != null) {
|
||||
writer.write(date(Double.valueOf(round(delta_veh, 2)).toString(), "align=\"right\"") + newline());
|
||||
} else writer.write(date("n.a.") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
writer.write(closeTable() + newline());
|
||||
|
||||
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String head(String string, int i) {
|
||||
return "<th colspan=\"" + i + "\">" + string + "</th>";
|
||||
}
|
||||
|
||||
private Double round(Double value, int i) {
|
||||
if (value == null) return null;
|
||||
long roundedVal = Math.round(value * Math.pow(10, i));
|
||||
return (double) roundedVal / (double) (Math.pow(10, i));
|
||||
}
|
||||
|
||||
private String head(String head) {
|
||||
return "<th>" + head + "</th>";
|
||||
}
|
||||
|
||||
private String closeTable() {
|
||||
return "</table>";
|
||||
}
|
||||
|
||||
private String openTable() {
|
||||
return "<table>";
|
||||
}
|
||||
|
||||
private String closeRow() {
|
||||
return "</tr>";
|
||||
}
|
||||
|
||||
private String date(String date) {
|
||||
return "<td>" + date + "</td>";
|
||||
}
|
||||
|
||||
private String date(String date, String metaData) {
|
||||
return "<td " + metaData + ">" + date + "</td>";
|
||||
}
|
||||
|
||||
private String newline() {
|
||||
return "\n";
|
||||
}
|
||||
|
||||
private String openRow() {
|
||||
return "<tr>";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
<parent>
|
||||
<groupId>com.graphhopper</groupId>
|
||||
<artifactId>jsprit</artifactId>
|
||||
<version>1.6.3-SNAPSHOT</version>
|
||||
<version>1.7.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jsprit-core</artifactId>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,14 @@
|
|||
*/
|
||||
package com.graphhopper.jsprit.core.algorithm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.SearchStrategy.DiscoveredSolution;
|
||||
import com.graphhopper.jsprit.core.algorithm.listener.SearchStrategyListener;
|
||||
import com.graphhopper.jsprit.core.algorithm.listener.SearchStrategyModuleListener;
|
||||
|
|
@ -30,11 +38,6 @@ import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolutio
|
|||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
import com.graphhopper.jsprit.core.util.Solutions;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -57,10 +60,9 @@ public class VehicleRoutingAlgorithm {
|
|||
@Override
|
||||
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
|
||||
for (PrematureAlgorithmTermination termination : terminationCriteria) {
|
||||
if (termination.isPrematureBreak(discoveredSolution)) {
|
||||
if (termination.isPrematureBreak(discoveredSolution))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -140,30 +142,36 @@ public class VehicleRoutingAlgorithm {
|
|||
* @param solution the solution to be added
|
||||
*/
|
||||
public void addInitialSolution(VehicleRoutingProblemSolution solution) {
|
||||
// We will make changes so let's make a copy
|
||||
solution = VehicleRoutingProblemSolution.copyOf(solution);
|
||||
verify(solution);
|
||||
initialSolutions.add(solution);
|
||||
}
|
||||
|
||||
private void verify(VehicleRoutingProblemSolution solution) {
|
||||
int nuJobs = 0;
|
||||
Set<Job> allJobs = new HashSet<Job>(problem.getJobs().values());
|
||||
allJobs.removeAll(solution.getUnassignedJobs());
|
||||
for (VehicleRoute route : solution.getRoutes()) {
|
||||
nuJobs += route.getTourActivities().getJobs().size();
|
||||
allJobs.removeAll(route.getTourActivities().getJobs());
|
||||
if (route.getVehicle().getIndex() == 0)
|
||||
throw new IllegalStateException("vehicle used in initial solution has no index. probably a vehicle is used that has not been added to the " +
|
||||
" the VehicleRoutingProblem. only use vehicles that have already been added to the problem.");
|
||||
for (TourActivity act : route.getActivities()) {
|
||||
if (act.getIndex() == 0) {
|
||||
if (act.getIndex() == 0)
|
||||
throw new IllegalStateException("act in initial solution has no index. activities are created and associated to their job in VehicleRoutingProblem\n." +
|
||||
" thus if you build vehicle-routes use the jobActivityFactory from vehicle routing problem like that \n" +
|
||||
" VehicleRoute.Builder.newInstance(knownVehicle).setJobActivityFactory(vrp.getJobActivityFactory).addService(..)....build() \n" +
|
||||
" then the activities that are created to build the route are identical to the ones used in VehicleRoutingProblem");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nuJobs != problem.getJobs().values().size()) {
|
||||
logger.warn("number of jobs in initial solution ({}) is not equal nuJobs in vehicle routing problem ({})" +
|
||||
"\n this might yield unintended effects, e.g. initial solution cannot be improved anymore.", nuJobs, problem.getJobs().values().size());
|
||||
}
|
||||
|
||||
solution.getUnassignedJobs().addAll(allJobs);
|
||||
solution.setCost(getObjectiveFunction().getCosts(solution));
|
||||
|
||||
// if (nuJobs != problem.getJobs().values().size()) {
|
||||
// logger.warn("number of jobs in initial solution ({}) is not equal nuJobs in vehicle routing problem ({})" +
|
||||
// "\n this might yield unintended effects, e.g. initial solution cannot be improved anymore.", nuJobs, problem.getJobs().values().size());
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -214,7 +222,9 @@ public class VehicleRoutingAlgorithm {
|
|||
Collection<VehicleRoutingProblemSolution> solutions = new ArrayList<VehicleRoutingProblemSolution>(initialSolutions);
|
||||
algorithmStarts(problem, solutions);
|
||||
bestEver = Solutions.bestOf(solutions);
|
||||
if (logger.isTraceEnabled()) log(solutions);
|
||||
if (logger.isTraceEnabled()) {
|
||||
log(solutions);
|
||||
}
|
||||
logger.info("iterations start");
|
||||
for (int i = 0; i < maxIterations; i++) {
|
||||
iterationStarts(i + 1, problem, solutions);
|
||||
|
|
@ -222,7 +232,9 @@ public class VehicleRoutingAlgorithm {
|
|||
counter.incCounter();
|
||||
SearchStrategy strategy = searchStrategyManager.getRandomStrategy();
|
||||
DiscoveredSolution discoveredSolution = strategy.run(problem, solutions);
|
||||
if (logger.isTraceEnabled()) log(discoveredSolution);
|
||||
if (logger.isTraceEnabled()) {
|
||||
log(discoveredSolution);
|
||||
}
|
||||
memorizeIfBestEver(discoveredSolution);
|
||||
selectedStrategy(discoveredSolution, problem, solutions);
|
||||
if (terminationManager.isPrematureBreak(discoveredSolution)) {
|
||||
|
|
@ -240,11 +252,15 @@ public class VehicleRoutingAlgorithm {
|
|||
}
|
||||
|
||||
private void addBestEver(Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
if (bestEver != null) solutions.add(bestEver);
|
||||
if (bestEver != null) {
|
||||
solutions.add(bestEver);
|
||||
}
|
||||
}
|
||||
|
||||
private void log(Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for (VehicleRoutingProblemSolution sol : solutions) log(sol);
|
||||
for (VehicleRoutingProblemSolution sol : solutions) {
|
||||
log(sol);
|
||||
}
|
||||
}
|
||||
|
||||
private void log(VehicleRoutingProblemSolution solution) {
|
||||
|
|
@ -277,9 +293,11 @@ public class VehicleRoutingAlgorithm {
|
|||
|
||||
private void memorizeIfBestEver(DiscoveredSolution discoveredSolution) {
|
||||
if (discoveredSolution == null) return;
|
||||
if (bestEver == null) bestEver = discoveredSolution.getSolution();
|
||||
else if (discoveredSolution.getSolution().getCost() < bestEver.getCost())
|
||||
if (bestEver == null) {
|
||||
bestEver = discoveredSolution.getSolution();
|
||||
} else if (discoveredSolution.getSolution().getCost() < bestEver.getCost()) {
|
||||
bestEver = discoveredSolution.getSolution();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -297,11 +315,13 @@ public class VehicleRoutingAlgorithm {
|
|||
|
||||
public void addListener(VehicleRoutingAlgorithmListener l) {
|
||||
algoListeners.addListener(l);
|
||||
if (l instanceof SearchStrategyListener)
|
||||
if (l instanceof SearchStrategyListener) {
|
||||
searchStrategyManager.addSearchStrategyListener((SearchStrategyListener) l);
|
||||
if (l instanceof SearchStrategyModuleListener)
|
||||
}
|
||||
if (l instanceof SearchStrategyModuleListener) {
|
||||
searchStrategyManager.addSearchStrategyModuleListener((SearchStrategyModuleListener) l);
|
||||
}
|
||||
}
|
||||
|
||||
private void iterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
algoListeners.iterationEnds(i, problem, solutions);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolutio
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -78,7 +80,6 @@ public class SchrimpfAcceptance implements SolutionAcceptor, IterationStartsList
|
|||
|
||||
private final int solutionMemory;
|
||||
|
||||
|
||||
public SchrimpfAcceptance(int solutionMemory, double alpha) {
|
||||
this.alpha = alpha;
|
||||
this.solutionMemory = solutionMemory;
|
||||
|
|
@ -110,6 +111,32 @@ public class SchrimpfAcceptance implements SolutionAcceptor, IterationStartsList
|
|||
return solutionAccepted;
|
||||
}
|
||||
|
||||
public boolean acceptSolution(VehicleRoutingProblemSolution solution, VehicleRoutingProblemSolution newSolution) {
|
||||
List<VehicleRoutingProblemSolution> solutions = new ArrayList<>();
|
||||
solutions.add(solution);
|
||||
boolean solutionAccepted = false;
|
||||
if (solutions.size() < solutionMemory) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else {
|
||||
VehicleRoutingProblemSolution worst = null;
|
||||
double threshold = getThreshold(currentIteration);
|
||||
for (VehicleRoutingProblemSolution solutionInMemory : solutions) {
|
||||
if (worst == null) worst = solutionInMemory;
|
||||
else if (solutionInMemory.getCost() > worst.getCost()) worst = solutionInMemory;
|
||||
}
|
||||
if (worst == null) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else if (newSolution.getCost() < worst.getCost() + threshold) {
|
||||
solutions.remove(worst);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
}
|
||||
return solutionAccepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=SchrimpfAcceptance][alpha=" + alpha + "]";
|
||||
|
|
@ -136,6 +163,16 @@ public class SchrimpfAcceptance implements SolutionAcceptor, IterationStartsList
|
|||
this.initialThreshold = initialThreshold;
|
||||
}
|
||||
|
||||
public void setMaxIterations(int maxIteration) {
|
||||
this.maxIterations = maxIteration;
|
||||
}
|
||||
|
||||
public void incIteration() {
|
||||
currentIteration++;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
reset();
|
||||
|
|
|
|||
|
|
@ -46,9 +46,7 @@ import com.graphhopper.jsprit.core.util.NoiseMaker;
|
|||
import com.graphhopper.jsprit.core.util.RandomNumberGeneration;
|
||||
import com.graphhopper.jsprit.core.util.Solutions;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
|
|
@ -82,7 +80,9 @@ public class Jsprit {
|
|||
WORST_BEST("worst_best"),
|
||||
WORST_REGRET("worst_regret"),
|
||||
CLUSTER_BEST("cluster_best"),
|
||||
CLUSTER_REGRET("cluster_regret");
|
||||
CLUSTER_REGRET("cluster_regret"),
|
||||
STRING_BEST("string_best"),
|
||||
STRING_REGRET("string_regret");
|
||||
|
||||
String strategyName;
|
||||
|
||||
|
|
@ -112,6 +112,7 @@ public class Jsprit {
|
|||
WORST_MAX_SHARE("worst.max_share"),
|
||||
THRESHOLD_ALPHA("threshold.alpha"),
|
||||
THRESHOLD_INI("threshold.ini"),
|
||||
THRESHOLD_INI_ABS("threshold.ini_abs"),
|
||||
INSERTION_NOISE_LEVEL("insertion.noise_level"),
|
||||
INSERTION_NOISE_PROB("insertion.noise_prob"),
|
||||
RUIN_WORST_NOISE_LEVEL("worst.noise_level"),
|
||||
|
|
@ -119,7 +120,12 @@ public class Jsprit {
|
|||
FAST_REGRET("regret.fast"),
|
||||
MAX_TRANSPORT_COSTS("max_transport_costs"),
|
||||
CONSTRUCTION("construction"),
|
||||
BREAK_SCHEDULING("break_scheduling");
|
||||
BREAK_SCHEDULING("break_scheduling"),
|
||||
STRING_K_MIN("string_kmin"),
|
||||
STRING_K_MAX("string_kmax"),
|
||||
STRING_L_MIN("string_lmin"),
|
||||
STRING_L_MAX("string_lmax");
|
||||
|
||||
|
||||
String paraName;
|
||||
|
||||
|
|
@ -161,6 +167,12 @@ public class Jsprit {
|
|||
|
||||
private SolutionAcceptor solutionAcceptor;
|
||||
|
||||
private ScoringFunction regretScorer = null;
|
||||
|
||||
private Map<SearchStrategy, Double> customStrategies = new HashMap<>();
|
||||
|
||||
private VehicleFleetManager fleetManager = null;
|
||||
|
||||
public static Builder newInstance(VehicleRoutingProblem vrp) {
|
||||
return new Builder(vrp);
|
||||
}
|
||||
|
|
@ -176,10 +188,21 @@ public class Jsprit {
|
|||
defaults.put(Strategy.RADIAL_REGRET.toString(), ".5");
|
||||
defaults.put(Strategy.RANDOM_BEST.toString(), ".5");
|
||||
defaults.put(Strategy.RANDOM_REGRET.toString(), ".5");
|
||||
|
||||
defaults.put(Strategy.STRING_BEST.toString(), "0.0");
|
||||
defaults.put(Strategy.STRING_REGRET.toString(), "0.0");
|
||||
|
||||
defaults.put(Parameter.STRING_K_MIN.toString(), "1");
|
||||
defaults.put(Parameter.STRING_K_MAX.toString(), "6");
|
||||
defaults.put(Parameter.STRING_L_MIN.toString(), "10");
|
||||
defaults.put(Parameter.STRING_L_MAX.toString(), "30");
|
||||
|
||||
defaults.put(Strategy.WORST_BEST.toString(), "0.");
|
||||
defaults.put(Strategy.WORST_REGRET.toString(), "1.");
|
||||
defaults.put(Strategy.CLUSTER_BEST.toString(), "0.");
|
||||
defaults.put(Strategy.CLUSTER_REGRET.toString(), "1.");
|
||||
|
||||
|
||||
defaults.put(Parameter.FIXED_COST_PARAM.toString(), "0.");
|
||||
defaults.put(Parameter.VEHICLE_SWITCH.toString(), "true");
|
||||
defaults.put(Parameter.ITERATIONS.toString(), "2000");
|
||||
|
|
@ -214,6 +237,16 @@ public class Jsprit {
|
|||
}
|
||||
|
||||
|
||||
public Builder addSearchStrategy(SearchStrategy searchStrategy, double weight) {
|
||||
customStrategies.put(searchStrategy, weight);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setVehicleFleetManager(VehicleFleetManager fleetManager) {
|
||||
this.fleetManager = fleetManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setExecutorService(ExecutorService es, int noThreads) {
|
||||
this.es = es;
|
||||
this.noThreads = noThreads;
|
||||
|
|
@ -266,6 +299,11 @@ public class Jsprit {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegretScorer(ScoringFunction scoringFunction) {
|
||||
this.regretScorer = scoringFunction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VehicleRoutingAlgorithm buildAlgorithm() {
|
||||
return new Jsprit(this).create(vrp);
|
||||
}
|
||||
|
|
@ -328,6 +366,12 @@ public class Jsprit {
|
|||
|
||||
private SolutionAcceptor acceptor;
|
||||
|
||||
private ScoringFunction regretScorer;
|
||||
|
||||
private final Map<SearchStrategy, Double> customStrategies = new HashMap<>();
|
||||
|
||||
private VehicleFleetManager vehicleFleetManager;
|
||||
|
||||
private Jsprit(Builder builder) {
|
||||
this.stateManager = builder.stateManager;
|
||||
this.constraintManager = builder.constraintManager;
|
||||
|
|
@ -339,16 +383,25 @@ public class Jsprit {
|
|||
this.random = builder.random;
|
||||
this.activityInsertion = builder.activityInsertionCalculator;
|
||||
this.acceptor = builder.solutionAcceptor;
|
||||
regretScorer = builder.regretScorer;
|
||||
customStrategies.putAll(builder.customStrategies);
|
||||
vehicleFleetManager = builder.fleetManager;
|
||||
}
|
||||
|
||||
private void ini(VehicleRoutingProblem vrp) {
|
||||
if (regretScorer == null) regretScorer = getRegretScorer(vrp);
|
||||
}
|
||||
|
||||
private VehicleRoutingAlgorithm create(final VehicleRoutingProblem vrp) {
|
||||
VehicleFleetManager fm;
|
||||
ini(vrp);
|
||||
if (vehicleFleetManager == null) {
|
||||
if (vrp.getFleetSize().equals(VehicleRoutingProblem.FleetSize.INFINITE)) {
|
||||
fm = new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
|
||||
vehicleFleetManager = new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
|
||||
} else {
|
||||
FiniteFleetManagerFactory finiteFleetManagerFactory = new FiniteFleetManagerFactory(vrp.getVehicles());
|
||||
finiteFleetManagerFactory.setRandom(random);
|
||||
fm = finiteFleetManagerFactory.createFleetManager();
|
||||
vehicleFleetManager = finiteFleetManagerFactory.createFleetManager();
|
||||
}
|
||||
}
|
||||
|
||||
if (stateManager == null) {
|
||||
|
|
@ -368,6 +421,14 @@ public class Jsprit {
|
|||
}
|
||||
}
|
||||
|
||||
double fixedCostParam = toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString()));
|
||||
IncreasingAbsoluteFixedCosts increasingAbsoluteFixedCosts = null;
|
||||
if (fixedCostParam > 0d) {
|
||||
increasingAbsoluteFixedCosts = new IncreasingAbsoluteFixedCosts(vrp.getJobs().size());
|
||||
increasingAbsoluteFixedCosts.setWeightOfFixCost(fixedCostParam);
|
||||
constraintManager.addConstraint(increasingAbsoluteFixedCosts);
|
||||
}
|
||||
|
||||
double noiseLevel = toDouble(getProperty(Parameter.INSERTION_NOISE_LEVEL.toString()));
|
||||
double noiseProbability = toDouble(getProperty(Parameter.INSERTION_NOISE_PROB.toString()));
|
||||
|
||||
|
|
@ -449,13 +510,23 @@ public class Jsprit {
|
|||
random)
|
||||
);
|
||||
|
||||
int kMin = toInteger(properties.getProperty(Parameter.STRING_K_MIN.toString()));
|
||||
int kMax = toInteger(properties.getProperty(Parameter.STRING_K_MAX.toString()));
|
||||
int lMin = toInteger(properties.getProperty(Parameter.STRING_L_MIN.toString()));
|
||||
int lMax = toInteger(properties.getProperty(Parameter.STRING_L_MAX.toString()));
|
||||
|
||||
final RuinString stringRuin = new RuinString(vrp, jobNeighborhoods);
|
||||
stringRuin.setNoRoutes(kMin, kMax);
|
||||
stringRuin.setStringLength(lMin, lMax);
|
||||
stringRuin.setRandom(random);
|
||||
|
||||
AbstractInsertionStrategy regret;
|
||||
final DefaultScorer scorer;
|
||||
final ScoringFunction scorer;
|
||||
|
||||
boolean fastRegret = Boolean.parseBoolean(getProperty(Parameter.FAST_REGRET.toString()));
|
||||
if (es != null) {
|
||||
if(fastRegret){
|
||||
RegretInsertionConcurrentFast regretInsertion = (RegretInsertionConcurrentFast) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||
RegretInsertionConcurrentFast regretInsertion = (RegretInsertionConcurrentFast) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
|
||||
.setConcurrentMode(es, noThreads)
|
||||
.setFastRegret(true)
|
||||
|
|
@ -463,45 +534,45 @@ public class Jsprit {
|
|||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.setActivityInsertionCostCalculator(activityInsertion)
|
||||
.build();
|
||||
scorer = getRegretScorer(vrp);
|
||||
scorer = regretScorer;
|
||||
regretInsertion.setScoringFunction(scorer);
|
||||
regretInsertion.setDependencyTypes(constraintManager.getDependencyTypes());
|
||||
regret = regretInsertion;
|
||||
}
|
||||
else {
|
||||
RegretInsertionConcurrent regretInsertion = (RegretInsertionConcurrent) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||
RegretInsertionConcurrent regretInsertion = (RegretInsertionConcurrent) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
|
||||
.setConcurrentMode(es, noThreads)
|
||||
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.setActivityInsertionCostCalculator(activityInsertion)
|
||||
.build();
|
||||
scorer = getRegretScorer(vrp);
|
||||
scorer = regretScorer;
|
||||
regretInsertion.setScoringFunction(scorer);
|
||||
regret = regretInsertion;
|
||||
}
|
||||
} else {
|
||||
if(fastRegret) {
|
||||
RegretInsertionFast regretInsertion = (RegretInsertionFast) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||
RegretInsertionFast regretInsertion = (RegretInsertionFast) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
|
||||
.setFastRegret(true)
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setActivityInsertionCostCalculator(activityInsertion)
|
||||
.build();
|
||||
scorer = getRegretScorer(vrp);
|
||||
scorer = regretScorer;
|
||||
regretInsertion.setScoringFunction(scorer);
|
||||
regretInsertion.setDependencyTypes(constraintManager.getDependencyTypes());
|
||||
regret = regretInsertion;
|
||||
}
|
||||
else{
|
||||
RegretInsertion regretInsertion = (RegretInsertion) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||
RegretInsertion regretInsertion = (RegretInsertion) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setActivityInsertionCostCalculator(activityInsertion)
|
||||
.build();
|
||||
scorer = getRegretScorer(vrp);
|
||||
scorer = regretScorer;
|
||||
regretInsertion.setScoringFunction(scorer);
|
||||
regret = regretInsertion;
|
||||
}
|
||||
|
|
@ -510,7 +581,7 @@ public class Jsprit {
|
|||
|
||||
AbstractInsertionStrategy best;
|
||||
if (vrp.getJobs().size() < 250 || es == null) {
|
||||
BestInsertion bestInsertion = (BestInsertion) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||
BestInsertion bestInsertion = (BestInsertion) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.BEST)
|
||||
.considerFixedCosts(Double.valueOf(properties.getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
|
|
@ -518,7 +589,7 @@ public class Jsprit {
|
|||
.build();
|
||||
best = bestInsertion;
|
||||
} else {
|
||||
BestInsertionConcurrent bestInsertion = (BestInsertionConcurrent) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||
BestInsertionConcurrent bestInsertion = (BestInsertionConcurrent) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.BEST)
|
||||
.considerFixedCosts(Double.valueOf(properties.getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
|
|
@ -532,6 +603,9 @@ public class Jsprit {
|
|||
IterationStartsListener schrimpfThreshold = null;
|
||||
if(acceptor == null) {
|
||||
final SchrimpfAcceptance schrimpfAcceptance = new SchrimpfAcceptance(1, toDouble(getProperty(Parameter.THRESHOLD_ALPHA.toString())));
|
||||
if (properties.containsKey(Parameter.THRESHOLD_INI_ABS.toString())) {
|
||||
schrimpfAcceptance.setInitialThreshold(Double.valueOf(properties.getProperty(Parameter.THRESHOLD_INI_ABS.toString())));
|
||||
} else {
|
||||
schrimpfThreshold = new IterationStartsListener() {
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
|
|
@ -541,6 +615,7 @@ public class Jsprit {
|
|||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
acceptor = schrimpfAcceptance;
|
||||
}
|
||||
|
||||
|
|
@ -569,8 +644,13 @@ public class Jsprit {
|
|||
final SearchStrategy clusters_best = new SearchStrategy(Strategy.CLUSTER_BEST.toString(), new SelectBest(), acceptor, objectiveFunction);
|
||||
clusters_best.addModule(new RuinAndRecreateModule(Strategy.CLUSTER_BEST.toString(), best, clusters));
|
||||
|
||||
SearchStrategy stringRegret = new SearchStrategy(Strategy.STRING_REGRET.toString(), new SelectBest(), acceptor, objectiveFunction);
|
||||
stringRegret.addModule(new RuinAndRecreateModule(Strategy.STRING_REGRET.toString(), regret, stringRuin));
|
||||
|
||||
PrettyAlgorithmBuilder prettyBuilder = PrettyAlgorithmBuilder.newInstance(vrp, fm, stateManager, constraintManager);
|
||||
SearchStrategy stringBest = new SearchStrategy(Strategy.STRING_BEST.toString(), new SelectBest(), acceptor, objectiveFunction);
|
||||
stringBest.addModule(new RuinAndRecreateModule(Strategy.STRING_BEST.toString(), best, stringRuin));
|
||||
|
||||
PrettyAlgorithmBuilder prettyBuilder = PrettyAlgorithmBuilder.newInstance(vrp, vehicleFleetManager, stateManager, constraintManager);
|
||||
prettyBuilder.setRandom(random);
|
||||
if (addCoreConstraints) {
|
||||
prettyBuilder.addCoreStateAndConstraintStuff();
|
||||
|
|
@ -582,7 +662,14 @@ public class Jsprit {
|
|||
.withStrategy(worst_best, toDouble(getProperty(Strategy.WORST_BEST.toString())))
|
||||
.withStrategy(worst_regret, toDouble(getProperty(Strategy.WORST_REGRET.toString())))
|
||||
.withStrategy(clusters_regret, toDouble(getProperty(Strategy.CLUSTER_REGRET.toString())))
|
||||
.withStrategy(clusters_best, toDouble(getProperty(Strategy.CLUSTER_BEST.toString())));
|
||||
.withStrategy(clusters_best, toDouble(getProperty(Strategy.CLUSTER_BEST.toString())))
|
||||
.withStrategy(stringBest, toDouble(getProperty(Strategy.STRING_BEST.toString())))
|
||||
.withStrategy(stringRegret, toDouble(getProperty(Strategy.STRING_REGRET.toString())));
|
||||
|
||||
for (SearchStrategy customStrategy : customStrategies.keySet()) {
|
||||
prettyBuilder.withStrategy(customStrategy, customStrategies.get(customStrategy));
|
||||
}
|
||||
|
||||
if (getProperty(Parameter.CONSTRUCTION.toString()).equals(Construction.BEST_INSERTION.toString())) {
|
||||
prettyBuilder.constructInitialSolutionWith(best, objectiveFunction);
|
||||
} else {
|
||||
|
|
@ -598,6 +685,7 @@ public class Jsprit {
|
|||
vra.addListener(noiseConfigurator);
|
||||
vra.addListener(noise);
|
||||
vra.addListener(clusters);
|
||||
if (increasingAbsoluteFixedCosts != null) vra.addListener(increasingAbsoluteFixedCosts);
|
||||
|
||||
if(toBoolean(getProperty(Parameter.BREAK_SCHEDULING.toString()))) {
|
||||
vra.addListener(new BreakScheduling(vrp, stateManager, constraintManager));
|
||||
|
|
@ -619,25 +707,36 @@ public class Jsprit {
|
|||
|
||||
private void handleExecutorShutdown(VehicleRoutingAlgorithm vra) {
|
||||
if (setupExecutorInternally) {
|
||||
final Thread hook = new Thread() {
|
||||
public void run() {
|
||||
if (!es.isShutdown()) {
|
||||
System.err.println("shutdownHook shuts down executorService");
|
||||
es.shutdown();
|
||||
}
|
||||
}
|
||||
};
|
||||
Runtime.getRuntime().addShutdownHook(hook);
|
||||
vra.addListener(new AlgorithmEndsListener() {
|
||||
|
||||
@Override
|
||||
public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
es.shutdown();
|
||||
Runtime.getRuntime().removeShutdownHook(hook);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
if (es != null) {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
public void run() {
|
||||
if (!es.isShutdown()) {
|
||||
System.err.println("shutdowHook shuts down executorService");
|
||||
es.shutdown();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// if (es != null) {
|
||||
//
|
||||
// Runtime.getRuntime().addShutdownHook(hook);
|
||||
// vra.addListener(new AlgorithmEndsListener() {
|
||||
// @Override
|
||||
// public void informAlgorithmEnds(VehicleRoutingProblem aProblem,
|
||||
// Collection<VehicleRoutingProblemSolution> aSolutions) {
|
||||
// Runtime.getRuntime().removeShutdownHook(hook);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
String getProperty(String key) {
|
||||
|
|
@ -685,7 +784,7 @@ public class Jsprit {
|
|||
}
|
||||
}
|
||||
for(Job j : solution.getUnassignedJobs()){
|
||||
costs += maxCosts * 2 * (4 - j.getPriority());
|
||||
costs += maxCosts * 2 * (11 - j.getPriority());
|
||||
}
|
||||
return costs;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.HardActivityConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.HardActivityConstraint.ConstraintsStatus;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.HardRouteConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 06/02/17.
|
||||
*/
|
||||
abstract class AbstractInsertionCalculator implements JobInsertionCostsCalculator {
|
||||
|
||||
InsertionData checkRouteContraints(JobInsertionContext insertionContext, ConstraintManager constraintManager) {
|
||||
for (HardRouteConstraint hardRouteConstraint : constraintManager.getHardRouteConstraints()) {
|
||||
if (!hardRouteConstraint.fulfilled(insertionContext)) {
|
||||
InsertionData emptyInsertionData = new InsertionData.NoInsertionFound();
|
||||
emptyInsertionData.addFailedConstrainName(hardRouteConstraint.getClass().getSimpleName());
|
||||
return emptyInsertionData;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime, Collection<String> failedActivityConstraints, ConstraintManager constraintManager) {
|
||||
ConstraintsStatus notFulfilled = null;
|
||||
List<String> failed = new ArrayList<>();
|
||||
for (HardActivityConstraint c : constraintManager.getCriticalHardActivityConstraints()) {
|
||||
ConstraintsStatus status = c.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
|
||||
if (status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)) {
|
||||
failedActivityConstraints.add(c.getClass().getSimpleName());
|
||||
return status;
|
||||
} else {
|
||||
if (status.equals(ConstraintsStatus.NOT_FULFILLED)) {
|
||||
failed.add(c.getClass().getSimpleName());
|
||||
notFulfilled = status;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (notFulfilled != null) {
|
||||
failedActivityConstraints.addAll(failed);
|
||||
return notFulfilled;
|
||||
}
|
||||
|
||||
for (HardActivityConstraint c : constraintManager.getHighPrioHardActivityConstraints()) {
|
||||
ConstraintsStatus status = c.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
|
||||
if (status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)) {
|
||||
failedActivityConstraints.add(c.getClass().getSimpleName());
|
||||
return status;
|
||||
} else {
|
||||
if (status.equals(ConstraintsStatus.NOT_FULFILLED)) {
|
||||
failed.add(c.getClass().getSimpleName());
|
||||
notFulfilled = status;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (notFulfilled != null) {
|
||||
failedActivityConstraints.addAll(failed);
|
||||
return notFulfilled;
|
||||
}
|
||||
|
||||
for (HardActivityConstraint constraint : constraintManager.getLowPrioHardActivityConstraints()) {
|
||||
ConstraintsStatus status = constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
|
||||
if (status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK) || status.equals(ConstraintsStatus.NOT_FULFILLED)) {
|
||||
failedActivityConstraints.add(constraint.getClass().getSimpleName());
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return ConstraintsStatus.FULFILLED;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public abstract class AbstractInsertionStrategy implements InsertionStrategy {
|
||||
|
|
@ -92,6 +93,10 @@ public abstract class AbstractInsertionStrategy implements InsertionStrategy {
|
|||
return badJobs;
|
||||
}
|
||||
|
||||
public void markUnassigned(Job unassigned, List<String> reasons) {
|
||||
insertionsListeners.informJobUnassignedListeners(unassigned, reasons);
|
||||
}
|
||||
|
||||
public abstract Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 30/06/17.
|
||||
*/
|
||||
class AccordingToPriorities implements Comparator<Job> {
|
||||
|
||||
@Override
|
||||
public int compare(Job o1, Job o2) {
|
||||
return o1.getPriority() - o2.getPriority();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -24,7 +24,10 @@ import com.graphhopper.jsprit.core.util.NoiseMaker;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -63,13 +66,15 @@ public final class BestInsertion extends AbstractInsertionStrategy {
|
|||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||
Collections.shuffle(unassignedJobList, random);
|
||||
sometimesSortPriorities(unassignedJobList);
|
||||
Collections.sort(unassignedJobList, new AccordingToPriorities());
|
||||
for (Job unassignedJob : unassignedJobList) {
|
||||
Insertion bestInsertion = null;
|
||||
InsertionData empty = new InsertionData.NoInsertionFound();
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
for (VehicleRoute vehicleRoute : vehicleRoutes) {
|
||||
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||
if (iData instanceof InsertionData.NoInsertionFound) {
|
||||
empty.getFailedConstraintNames().addAll(iData.getFailedConstraintNames());
|
||||
continue;
|
||||
}
|
||||
if (iData.getInsertionCost() < bestInsertionCost + noiseMaker.makeNoise()) {
|
||||
|
|
@ -84,23 +89,16 @@ public final class BestInsertion extends AbstractInsertionStrategy {
|
|||
bestInsertion = new Insertion(newRoute, newIData);
|
||||
vehicleRoutes.add(newRoute);
|
||||
}
|
||||
} else {
|
||||
empty.getFailedConstraintNames().addAll(newIData.getFailedConstraintNames());
|
||||
}
|
||||
if (bestInsertion == null) {
|
||||
badJobs.add(unassignedJob);
|
||||
markUnassigned(unassignedJob, empty.getFailedConstraintNames());
|
||||
}
|
||||
if (bestInsertion == null) badJobs.add(unassignedJob);
|
||||
else insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||
// nextInsertion();
|
||||
}
|
||||
return badJobs;
|
||||
}
|
||||
|
||||
private void sometimesSortPriorities(List<Job> unassignedJobList) {
|
||||
if(random.nextDouble() < 0.5){
|
||||
Collections.sort(unassignedJobList, new Comparator<Job>() {
|
||||
@Override
|
||||
public int compare(Job o1, Job o2) {
|
||||
return o1.getPriority() - o2.getPriority();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,10 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
|
||||
|
|
@ -99,8 +102,9 @@ public final class BestInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||
Collections.shuffle(unassignedJobList, random);
|
||||
sometimesSortPriorities(unassignedJobList);
|
||||
Collections.sort(unassignedJobList, new AccordingToPriorities());
|
||||
List<Batch> batches = distributeRoutes(vehicleRoutes, nuOfBatches);
|
||||
List<String> failedConstraintNames = new ArrayList<>();
|
||||
for (final Job unassignedJob : unassignedJobList) {
|
||||
Insertion bestInsertion = null;
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
|
|
@ -118,7 +122,10 @@ public final class BestInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
for (int i = 0; i < batches.size(); i++) {
|
||||
Future<Insertion> futureIData = completionService.take();
|
||||
Insertion insertion = futureIData.get();
|
||||
if (insertion == null) continue;
|
||||
if (insertion.insertionData instanceof NoInsertionFound) {
|
||||
failedConstraintNames.addAll(insertion.getInsertionData().getFailedConstraintNames());
|
||||
continue;
|
||||
}
|
||||
if (insertion.getInsertionData().getInsertionCost() < bestInsertionCost) {
|
||||
bestInsertion = insertion;
|
||||
bestInsertionCost = insertion.getInsertionData().getInsertionCost();
|
||||
|
|
@ -136,29 +143,24 @@ public final class BestInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
vehicleRoutes.add(newRoute);
|
||||
batches.get(random.nextInt(batches.size())).routes.add(newRoute);
|
||||
}
|
||||
if (bestInsertion == null) badJobs.add(unassignedJob);
|
||||
if (bestInsertion == null) {
|
||||
badJobs.add(unassignedJob);
|
||||
markUnassigned(unassignedJob, failedConstraintNames);
|
||||
}
|
||||
else insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||
}
|
||||
return badJobs;
|
||||
}
|
||||
|
||||
private void sometimesSortPriorities(List<Job> unassignedJobList) {
|
||||
if(random.nextDouble() < 0.5){
|
||||
Collections.sort(unassignedJobList, new Comparator<Job>() {
|
||||
@Override
|
||||
public int compare(Job o1, Job o2) {
|
||||
return o1.getPriority() - o2.getPriority();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
|
||||
Insertion bestInsertion = null;
|
||||
InsertionData empty = new InsertionData.NoInsertionFound();
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
for (VehicleRoute vehicleRoute : batch.routes) {
|
||||
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||
if (iData instanceof NoInsertionFound) {
|
||||
empty.getFailedConstraintNames().addAll(iData.getFailedConstraintNames());
|
||||
continue;
|
||||
}
|
||||
if (iData.getInsertionCost() < bestInsertionCost) {
|
||||
|
|
@ -166,6 +168,7 @@ public final class BestInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
bestInsertionCost = iData.getInsertionCost();
|
||||
}
|
||||
}
|
||||
if (bestInsertion == null) return new Insertion(null, empty);
|
||||
return bestInsertion;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
@Deprecated
|
||||
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator {
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Deprecated
|
||||
class CalculatesServiceInsertionWithTimeSchedulingInSlices implements JobInsertionCostsCalculator {
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.state.InternalStates;
|
||||
import com.graphhopper.jsprit.core.problem.Capacity;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public final class DecreasingRelativeFixedCosts extends SolutionCompletenessRatio implements SoftRouteConstraint {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DecreasingRelativeFixedCosts.class);
|
||||
|
||||
private double weightDeltaFixCost = 0.5;
|
||||
|
||||
private RouteAndActivityStateGetter stateGetter;
|
||||
|
||||
public DecreasingRelativeFixedCosts(RouteAndActivityStateGetter stateGetter, int noJobs) {
|
||||
super(noJobs);
|
||||
this.stateGetter = stateGetter;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
|
||||
public void setWeightOfFixCost(double weight) {
|
||||
weightDeltaFixCost = weight;
|
||||
logger.debug("set weightOfFixCostSaving to {}", weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=DecreasingRelativeFixedCosts][weightOfFixedCostSavings=" + weightDeltaFixCost + "]";
|
||||
}
|
||||
|
||||
private Capacity getCurrentMaxLoadInRoute(VehicleRoute route) {
|
||||
Capacity maxLoad = stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class);
|
||||
if (maxLoad == null) maxLoad = Capacity.Builder.newInstance().build();
|
||||
return maxLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext insertionContext) {
|
||||
VehicleRoute route = insertionContext.getRoute();
|
||||
Capacity currentLoad = getCurrentMaxLoadInRoute(route);
|
||||
Capacity load = Capacity.addup(currentLoad, insertionContext.getJob().getSize());
|
||||
double currentRelFix = 0d;
|
||||
if (route.getVehicle() != null && !(route.getVehicle() instanceof VehicleImpl.NoVehicle)) {
|
||||
currentRelFix = route.getVehicle().getType().getVehicleCostParams().fix * Capacity.divide(currentLoad, route.getVehicle().getType().getCapacityDimensions());
|
||||
}
|
||||
double newRelFix = insertionContext.getNewVehicle().getType().getVehicleCostParams().fix * (Capacity.divide(load, insertionContext.getNewVehicle().getType().getCapacityDimensions()));
|
||||
double decreasingRelativeFixedCosts = (1 - solutionCompletenessRatio) * (newRelFix - currentRelFix);
|
||||
return weightDeltaFixCost * solutionCompletenessRatio * decreasingRelativeFixedCosts;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -31,14 +31,14 @@ public class DellAmicoFixCostCalculator implements SoftRouteConstraint, Insertio
|
|||
|
||||
private int nuOfJobsToRecreate;
|
||||
|
||||
private final JobInsertionConsideringFixCostsCalculator calculator;
|
||||
private final IncreasingAbsoluteFixedCosts calculator;
|
||||
|
||||
private final int nuOfJobs;
|
||||
|
||||
public DellAmicoFixCostCalculator(final int nuOfJobs, final RouteAndActivityStateGetter stateGetter) {
|
||||
super();
|
||||
this.nuOfJobs = nuOfJobs;
|
||||
calculator = new JobInsertionConsideringFixCostsCalculator(null, stateGetter);
|
||||
calculator = new IncreasingAbsoluteFixedCosts(nuOfJobs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public final class IncreasingAbsoluteFixedCosts extends SolutionCompletenessRatio implements SoftRouteConstraint {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(IncreasingAbsoluteFixedCosts.class);
|
||||
|
||||
private double weightDeltaFixCost = 0.5;
|
||||
|
||||
public IncreasingAbsoluteFixedCosts(int noJobs) {
|
||||
super(noJobs);
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
|
||||
public void setWeightOfFixCost(double weight) {
|
||||
weightDeltaFixCost = weight;
|
||||
logger.debug("set weightOfFixCostSaving to {}", weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=IncreasingAbsoluteFixedCosts][weightOfFixedCostSavings=" + weightDeltaFixCost + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext insertionContext) {
|
||||
final VehicleRoute currentRoute = insertionContext.getRoute();
|
||||
double currentFix = 0d;
|
||||
if (currentRoute.getVehicle() != null && !(currentRoute.getVehicle() instanceof VehicleImpl.NoVehicle)) {
|
||||
currentFix = currentRoute.getVehicle().getType().getVehicleCostParams().fix;
|
||||
}
|
||||
double increasingAbsoluteFixedCosts = solutionCompletenessRatio * (insertionContext.getNewVehicle().getType().getVehicleCostParams().fix - currentFix);
|
||||
return weightDeltaFixCost * solutionCompletenessRatio * increasingAbsoluteFixedCosts;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ import java.util.List;
|
|||
*/
|
||||
public class InsertionData {
|
||||
|
||||
|
||||
public static class NoInsertionFound extends InsertionData {
|
||||
|
||||
public NoInsertionFound() {
|
||||
|
|
@ -75,6 +76,8 @@ public class InsertionData {
|
|||
return events;
|
||||
}
|
||||
|
||||
private List<String> reasons = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* @return the additionalTime
|
||||
*/
|
||||
|
|
@ -82,6 +85,14 @@ public class InsertionData {
|
|||
return additionalTime;
|
||||
}
|
||||
|
||||
public void addFailedConstrainName(String name) {
|
||||
reasons.add(name);
|
||||
}
|
||||
|
||||
public List<String> getFailedConstraintNames() {
|
||||
return reasons;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param additionalTime the additionalTime to set
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class InsertionDataUpdater {
|
|||
|
||||
static boolean update(boolean addAllAvailable, Set<String> initialVehicleIds, VehicleFleetManager fleetManager, JobInsertionCostsCalculator insertionCostsCalculator, TreeSet<VersionedInsertionData> insertionDataSet, int updateRound, Job unassignedJob, Collection<VehicleRoute> routes) {
|
||||
for(VehicleRoute route : routes) {
|
||||
Collection<Vehicle> relevantVehicles = new ArrayList<Vehicle>();
|
||||
Collection<Vehicle> relevantVehicles = new ArrayList<>();
|
||||
if (!(route.getVehicle() instanceof VehicleImpl.NoVehicle)) {
|
||||
relevantVehicles.add(route.getVehicle());
|
||||
if(addAllAvailable && !initialVehicleIds.contains(route.getVehicle().getId())){
|
||||
|
|
@ -71,7 +71,7 @@ class InsertionDataUpdater {
|
|||
};
|
||||
}
|
||||
|
||||
static ScoredJob getBest(boolean switchAllowed, Set<String> initialVehicleIds, VehicleFleetManager fleetManager, JobInsertionCostsCalculator insertionCostsCalculator, ScoringFunction scoringFunction, TreeSet<VersionedInsertionData>[] priorityQueues, Map<VehicleRoute, Integer> updates, List<Job> unassignedJobList, List<Job> badJobs) {
|
||||
static ScoredJob getBest(boolean switchAllowed, Set<String> initialVehicleIds, VehicleFleetManager fleetManager, JobInsertionCostsCalculator insertionCostsCalculator, ScoringFunction scoringFunction, TreeSet<VersionedInsertionData>[] priorityQueues, Map<VehicleRoute, Integer> updates, List<Job> unassignedJobList, List<ScoredJob> badJobs) {
|
||||
ScoredJob bestScoredJob = null;
|
||||
for(Job j : unassignedJobList){
|
||||
VehicleRoute bestRoute = null;
|
||||
|
|
@ -79,6 +79,7 @@ class InsertionDataUpdater {
|
|||
InsertionData secondBest = null;
|
||||
TreeSet<VersionedInsertionData> priorityQueue = priorityQueues[j.getIndex()];
|
||||
Iterator<VersionedInsertionData> iterator = priorityQueue.iterator();
|
||||
List<String> failedConstraintNames = new ArrayList<>();
|
||||
while(iterator.hasNext()){
|
||||
VersionedInsertionData versionedIData = iterator.next();
|
||||
if(bestRoute != null){
|
||||
|
|
@ -86,7 +87,10 @@ class InsertionDataUpdater {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if(versionedIData.getiData() instanceof InsertionData.NoInsertionFound) continue;
|
||||
if (versionedIData.getiData() instanceof InsertionData.NoInsertionFound) {
|
||||
failedConstraintNames.addAll(versionedIData.getiData().getFailedConstraintNames());
|
||||
continue;
|
||||
}
|
||||
if(!(versionedIData.getRoute().getVehicle() instanceof VehicleImpl.NoVehicle)) {
|
||||
if (versionedIData.getiData().getSelectedVehicle() != versionedIData.getRoute().getVehicle()) {
|
||||
if (!switchAllowed) continue;
|
||||
|
|
@ -136,9 +140,9 @@ class InsertionDataUpdater {
|
|||
} else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) {
|
||||
secondBest = iData;
|
||||
}
|
||||
}
|
||||
} else failedConstraintNames.addAll(iData.getFailedConstraintNames());
|
||||
if (best == null) {
|
||||
badJobs.add(j);
|
||||
badJobs.add(new ScoredJob.BadJob(j, failedConstraintNames));
|
||||
continue;
|
||||
}
|
||||
double score = score(j, best, secondBest, scoringFunction);
|
||||
|
|
|
|||
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.state.InternalStates;
|
||||
import com.graphhopper.jsprit.core.problem.Capacity;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.driver.Driver;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
final class JobInsertionConsideringFixCostsCalculator implements JobInsertionCostsCalculator, SoftRouteConstraint {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JobInsertionConsideringFixCostsCalculator.class);
|
||||
|
||||
private final JobInsertionCostsCalculator standardServiceInsertion;
|
||||
|
||||
private double weight_deltaFixCost = 0.5;
|
||||
|
||||
private double solution_completeness_ratio = 0.5;
|
||||
|
||||
private RouteAndActivityStateGetter stateGetter;
|
||||
|
||||
public JobInsertionConsideringFixCostsCalculator(final JobInsertionCostsCalculator standardInsertionCalculator, RouteAndActivityStateGetter stateGetter) {
|
||||
super();
|
||||
this.standardServiceInsertion = standardInsertionCalculator;
|
||||
this.stateGetter = stateGetter;
|
||||
logger.debug("inialise {}", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) {
|
||||
double fixcost_contribution = getFixCostContribution(currentRoute, jobToInsert, newVehicle);
|
||||
if (fixcost_contribution > bestKnownPrice) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
InsertionData iData = standardServiceInsertion.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice);
|
||||
if (iData instanceof InsertionData.NoInsertionFound) {
|
||||
return iData;
|
||||
}
|
||||
double totalInsertionCost = iData.getInsertionCost() + fixcost_contribution;
|
||||
InsertionData insertionData = new InsertionData(totalInsertionCost, iData.getPickupInsertionIndex(), iData.getDeliveryInsertionIndex(), newVehicle, newDriver);
|
||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
insertionData.getEvents().addAll(iData.getEvents());
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
private double getFixCostContribution(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle) {
|
||||
Capacity currentMaxLoadInRoute = getCurrentMaxLoadInRoute(currentRoute);
|
||||
double relFixCost = getDeltaRelativeFixCost(currentRoute, newVehicle, jobToInsert,currentMaxLoadInRoute);
|
||||
double absFixCost = getDeltaAbsoluteFixCost(currentRoute, newVehicle, jobToInsert,currentMaxLoadInRoute);
|
||||
double deltaFixCost = (1 - solution_completeness_ratio) * relFixCost + solution_completeness_ratio * absFixCost;
|
||||
double fixcost_contribution = weight_deltaFixCost * solution_completeness_ratio * deltaFixCost;
|
||||
return fixcost_contribution;
|
||||
}
|
||||
|
||||
public void setWeightOfFixCost(double weight) {
|
||||
weight_deltaFixCost = weight;
|
||||
logger.debug("set weightOfFixCostSaving to {}", weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertionConsideringFixCost][weightOfFixedCostSavings=" + weight_deltaFixCost + "]";
|
||||
}
|
||||
|
||||
public void setSolutionCompletenessRatio(double ratio) {
|
||||
solution_completeness_ratio = ratio;
|
||||
}
|
||||
|
||||
public double getSolutionCompletenessRatio() { return solution_completeness_ratio; }
|
||||
|
||||
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job, Capacity currentMaxLoadInRoute) {
|
||||
Capacity load = Capacity.addup(currentMaxLoadInRoute, job.getSize());
|
||||
double currentFix = 0.0;
|
||||
if (route.getVehicle() != null) {
|
||||
if (!(route.getVehicle() instanceof VehicleImpl.NoVehicle)) {
|
||||
currentFix += route.getVehicle().getType().getVehicleCostParams().fix;
|
||||
}
|
||||
}
|
||||
if (!newVehicle.getType().getCapacityDimensions().isGreaterOrEqual(load)) {
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
return newVehicle.getType().getVehicleCostParams().fix - currentFix;
|
||||
}
|
||||
|
||||
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job, Capacity currentLoad) {
|
||||
Capacity load = Capacity.addup(currentLoad, job.getSize());
|
||||
double currentRelFix = 0.0;
|
||||
if (route.getVehicle() != null) {
|
||||
if (!(route.getVehicle() instanceof VehicleImpl.NoVehicle)) {
|
||||
currentRelFix += route.getVehicle().getType().getVehicleCostParams().fix * Capacity.divide(currentLoad, route.getVehicle().getType().getCapacityDimensions());
|
||||
}
|
||||
}
|
||||
if (!newVehicle.getType().getCapacityDimensions().isGreaterOrEqual(load)) {
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
double relativeFixCost = newVehicle.getType().getVehicleCostParams().fix * (Capacity.divide(load, newVehicle.getType().getCapacityDimensions())) - currentRelFix;
|
||||
return relativeFixCost;
|
||||
}
|
||||
|
||||
private Capacity getCurrentMaxLoadInRoute(VehicleRoute route) {
|
||||
Capacity maxLoad = stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class);
|
||||
if (maxLoad == null) maxLoad = Capacity.Builder.newInstance().build();
|
||||
return maxLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext insertionContext) {
|
||||
return getFixCostContribution(insertionContext.getRoute(), insertionContext.getJob(), insertionContext.getNewVehicle());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -218,10 +218,10 @@ public class JobInsertionCostsCalculatorBuilder {
|
|||
addAlgorithmListeners(standardLocal.getAlgorithmListener());
|
||||
addInsertionListeners(standardLocal.getInsertionListener());
|
||||
if (considerFixedCost) {
|
||||
CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, states, weightOfFixedCost);
|
||||
baseCalculator = withFixed.getCalculator();
|
||||
addAlgorithmListeners(withFixed.getAlgorithmListener());
|
||||
addInsertionListeners(withFixed.getInsertionListener());
|
||||
// CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, states, weightOfFixedCost);
|
||||
// baseCalculator = withFixed.getCalculator();
|
||||
// addAlgorithmListeners(withFixed.getAlgorithmListener());
|
||||
// addInsertionListeners(withFixed.getInsertionListener());
|
||||
}
|
||||
if (timeScheduling) {
|
||||
// baseCalculator = new CalculatesServiceInsertionWithTimeSchedulingInSlices(baseCalculator,timeSlice,neighbors);
|
||||
|
|
@ -309,14 +309,6 @@ public class JobInsertionCostsCalculatorBuilder {
|
|||
return calculatorPlusListeners;
|
||||
}
|
||||
|
||||
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCostsCalculator baseCalculator, RouteAndActivityStateGetter activityStates2, double weightOfFixedCosts) {
|
||||
final JobInsertionConsideringFixCostsCalculator withFixCost = new JobInsertionConsideringFixCostsCalculator(baseCalculator, activityStates2);
|
||||
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
|
||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
|
||||
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
|
||||
return calcPlusListeners;
|
||||
}
|
||||
|
||||
private CalculatorPlusListeners createStandardRoute(final VehicleRoutingProblem vrp, RouteAndActivityStateGetter activityStates2, int forwardLooking, int solutionMemory) {
|
||||
ActivityInsertionCostsCalculator routeLevelCostEstimator;
|
||||
if (activityInsertionCostCalculator == null && addDefaultCostCalc) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.graphhopper.jsprit.core.algorithm.state.InternalStates;
|
|||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.DeliverShipment;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.End;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
|
||||
|
|
@ -77,7 +78,9 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
|
|||
|
||||
double oldCosts = 0.;
|
||||
if (iFacts.getRoute().isEmpty()) {
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double tp_costs_prevAct_nextAct = 0.;
|
||||
if (newAct instanceof DeliverShipment)
|
||||
tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
oldCosts += tp_costs_prevAct_nextAct;
|
||||
} else {
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
|
|
|
|||
|
|
@ -105,10 +105,10 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
List<Job> jobs = new ArrayList<Job>(unassignedJobs);
|
||||
List<Job> jobs = new ArrayList<>(unassignedJobs);
|
||||
while (!jobs.isEmpty()) {
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(jobs);
|
||||
List<Job> badJobList = new ArrayList<Job>();
|
||||
List<Job> unassignedJobList = new ArrayList<>(jobs);
|
||||
List<ScoredJob> badJobList = new ArrayList<>();
|
||||
ScoredJob bestScoredJob = nextJob(routes, unassignedJobList, badJobList);
|
||||
if (bestScoredJob != null) {
|
||||
if (bestScoredJob.isNewRoute()) {
|
||||
|
|
@ -117,9 +117,11 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
|||
insertJob(bestScoredJob.getJob(), bestScoredJob.getInsertionData(), bestScoredJob.getRoute());
|
||||
jobs.remove(bestScoredJob.getJob());
|
||||
}
|
||||
for (Job bad : badJobList) {
|
||||
jobs.remove(bad);
|
||||
badJobs.add(bad);
|
||||
for (ScoredJob bad : badJobList) {
|
||||
Job unassigned = bad.getJob();
|
||||
jobs.remove(unassigned);
|
||||
badJobs.add(unassigned);
|
||||
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraintNames());
|
||||
}
|
||||
}
|
||||
return badJobs;
|
||||
|
|
@ -132,12 +134,12 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
|||
return null;
|
||||
}
|
||||
|
||||
private ScoredJob nextJob(Collection<VehicleRoute> routes, Collection<Job> unassignedJobList, List<Job> badJobs) {
|
||||
private ScoredJob nextJob(Collection<VehicleRoute> routes, Collection<Job> unassignedJobList, List<ScoredJob> badJobs) {
|
||||
ScoredJob bestScoredJob = null;
|
||||
for (Job unassignedJob : unassignedJobList) {
|
||||
ScoredJob scoredJob = getScoredJob(routes, unassignedJob, insertionCostsCalculator, scoringFunction);
|
||||
if (scoredJob instanceof ScoredJob.BadJob) {
|
||||
badJobs.add(unassignedJob);
|
||||
badJobs.add(scoredJob);
|
||||
continue;
|
||||
}
|
||||
if (bestScoredJob == null) bestScoredJob = scoredJob;
|
||||
|
|
@ -158,14 +160,17 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
|||
InsertionData best = null;
|
||||
InsertionData secondBest = null;
|
||||
VehicleRoute bestRoute = null;
|
||||
|
||||
List<String> failedConstraintNames = new ArrayList<>();
|
||||
double benchmark = Double.MAX_VALUE;
|
||||
for (VehicleRoute route : routes) {
|
||||
if (secondBest != null) {
|
||||
benchmark = secondBest.getInsertionCost();
|
||||
}
|
||||
InsertionData iData = insertionCostsCalculator.getInsertionData(route, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, benchmark);
|
||||
if (iData instanceof InsertionData.NoInsertionFound) continue;
|
||||
if (iData instanceof InsertionData.NoInsertionFound) {
|
||||
failedConstraintNames.addAll(iData.getFailedConstraintNames());
|
||||
continue;
|
||||
}
|
||||
if (best == null) {
|
||||
best = iData;
|
||||
bestRoute = route;
|
||||
|
|
@ -191,9 +196,10 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
|||
} else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) {
|
||||
secondBest = iData;
|
||||
}
|
||||
}
|
||||
} else failedConstraintNames.addAll(iData.getFailedConstraintNames());
|
||||
if (best == null) {
|
||||
return new ScoredJob.BadJob(unassignedJob);
|
||||
ScoredJob.BadJob badJob = new ScoredJob.BadJob(unassignedJob, failedConstraintNames);
|
||||
return badJob;
|
||||
}
|
||||
double score = score(unassignedJob, best, secondBest, scoringFunction);
|
||||
ScoredJob scoredJob;
|
||||
|
|
|
|||
|
|
@ -109,10 +109,10 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
List<Job> jobs = new ArrayList<Job>(unassignedJobs);
|
||||
List<Job> jobs = new ArrayList<>(unassignedJobs);
|
||||
while (!jobs.isEmpty()) {
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(jobs);
|
||||
List<Job> badJobList = new ArrayList<Job>();
|
||||
List<Job> unassignedJobList = new ArrayList<>(jobs);
|
||||
List<ScoredJob> badJobList = new ArrayList<>();
|
||||
ScoredJob bestScoredJob = nextJob(routes, unassignedJobList, badJobList);
|
||||
if (bestScoredJob != null) {
|
||||
if (bestScoredJob.isNewRoute()) {
|
||||
|
|
@ -121,15 +121,17 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
insertJob(bestScoredJob.getJob(), bestScoredJob.getInsertionData(), bestScoredJob.getRoute());
|
||||
jobs.remove(bestScoredJob.getJob());
|
||||
}
|
||||
for (Job j : badJobList) {
|
||||
jobs.remove(j);
|
||||
badJobs.add(j);
|
||||
for (ScoredJob bad : badJobList) {
|
||||
Job unassigned = bad.getJob();
|
||||
jobs.remove(unassigned);
|
||||
badJobs.add(unassigned);
|
||||
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraintNames());
|
||||
}
|
||||
}
|
||||
return badJobs;
|
||||
}
|
||||
|
||||
private ScoredJob nextJob(final Collection<VehicleRoute> routes, List<Job> unassignedJobList, List<Job> badJobList) {
|
||||
private ScoredJob nextJob(final Collection<VehicleRoute> routes, List<Job> unassignedJobList, List<ScoredJob> badJobList) {
|
||||
ScoredJob bestScoredJob = null;
|
||||
|
||||
for (final Job unassignedJob : unassignedJobList) {
|
||||
|
|
@ -148,7 +150,7 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
Future<ScoredJob> fsj = completionService.take();
|
||||
ScoredJob sJob = fsj.get();
|
||||
if (sJob instanceof ScoredJob.BadJob) {
|
||||
badJobList.add(sJob.getJob());
|
||||
badJobList.add(sJob);
|
||||
continue;
|
||||
}
|
||||
if (bestScoredJob == null) {
|
||||
|
|
|
|||
|
|
@ -143,8 +143,8 @@ public class RegretInsertionConcurrentFast extends AbstractInsertionStrategy {
|
|||
int updateRound = 0;
|
||||
Map<VehicleRoute,Integer> updates = new HashMap<VehicleRoute, Integer>();
|
||||
while (!jobs.isEmpty()) {
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(jobs);
|
||||
List<Job> badJobList = new ArrayList<Job>();
|
||||
List<Job> unassignedJobList = new ArrayList<>(jobs);
|
||||
List<ScoredJob> badJobList = new ArrayList<>();
|
||||
if(!firstRun && lastModified == null) throw new IllegalStateException("ho. this must not be.");
|
||||
updateInsertionData(priorityQueues, routes, unassignedJobList, updateRound,firstRun,lastModified,updates);
|
||||
if(firstRun) firstRun = false;
|
||||
|
|
@ -159,9 +159,11 @@ public class RegretInsertionConcurrentFast extends AbstractInsertionStrategy {
|
|||
lastModified = bestScoredJob.getRoute();
|
||||
}
|
||||
else lastModified = null;
|
||||
for (Job bad : badJobList) {
|
||||
jobs.remove(bad);
|
||||
badJobs.add(bad);
|
||||
for (ScoredJob bad : badJobList) {
|
||||
Job unassigned = bad.getJob();
|
||||
jobs.remove(unassigned);
|
||||
badJobs.add(unassigned);
|
||||
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraintNames());
|
||||
}
|
||||
}
|
||||
return badJobs;
|
||||
|
|
@ -172,7 +174,7 @@ public class RegretInsertionConcurrentFast extends AbstractInsertionStrategy {
|
|||
boolean updatedAllRoutes = false;
|
||||
for (final Job unassignedJob : unassignedJobList) {
|
||||
if(priorityQueues[unassignedJob.getIndex()] == null){
|
||||
priorityQueues[unassignedJob.getIndex()] = new TreeSet<VersionedInsertionData>(InsertionDataUpdater.getComparator());
|
||||
priorityQueues[unassignedJob.getIndex()] = new TreeSet<>(InsertionDataUpdater.getComparator());
|
||||
}
|
||||
if(firstRun) {
|
||||
updatedAllRoutes = true;
|
||||
|
|
|
|||
|
|
@ -131,10 +131,10 @@ public class RegretInsertionFast extends AbstractInsertionStrategy {
|
|||
VehicleRoute lastModified = null;
|
||||
boolean firstRun = true;
|
||||
int updateRound = 0;
|
||||
Map<VehicleRoute,Integer> updates = new HashMap<VehicleRoute, Integer>();
|
||||
Map<VehicleRoute, Integer> updates = new HashMap<>();
|
||||
while (!jobs.isEmpty()) {
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(jobs);
|
||||
List<Job> badJobList = new ArrayList<Job>();
|
||||
List<Job> unassignedJobList = new ArrayList<>(jobs);
|
||||
List<ScoredJob> badJobList = new ArrayList<>();
|
||||
if(!firstRun && lastModified == null) throw new IllegalStateException("last modified route is null. this should not be.");
|
||||
if(firstRun){
|
||||
updateInsertionData(priorityQueues, routes, unassignedJobList, updateRound, firstRun, lastModified, updates);
|
||||
|
|
@ -156,9 +156,11 @@ public class RegretInsertionFast extends AbstractInsertionStrategy {
|
|||
lastModified = bestScoredJob.getRoute();
|
||||
}
|
||||
else lastModified = null;
|
||||
for (Job bad : badJobList) {
|
||||
jobs.remove(bad);
|
||||
badJobs.add(bad);
|
||||
for (ScoredJob bad : badJobList) {
|
||||
Job unassigned = bad.getJob();
|
||||
jobs.remove(unassigned);
|
||||
badJobs.add(unassigned);
|
||||
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraintNames());
|
||||
}
|
||||
}
|
||||
return badJobs;
|
||||
|
|
@ -167,7 +169,7 @@ public class RegretInsertionFast extends AbstractInsertionStrategy {
|
|||
private void updateInsertionData(TreeSet<VersionedInsertionData>[] priorityQueues, Collection<VehicleRoute> routes, List<Job> unassignedJobList, int updateRound, boolean firstRun, VehicleRoute lastModified, Map<VehicleRoute, Integer> updates) {
|
||||
for (Job unassignedJob : unassignedJobList) {
|
||||
if(priorityQueues[unassignedJob.getIndex()] == null){
|
||||
priorityQueues[unassignedJob.getIndex()] = new TreeSet<VersionedInsertionData>(InsertionDataUpdater.getComparator());
|
||||
priorityQueues[unassignedJob.getIndex()] = new TreeSet<>(InsertionDataUpdater.getComparator());
|
||||
}
|
||||
if(firstRun) {
|
||||
InsertionDataUpdater.update(switchAllowed, initialVehicleIds, fleetManager, insertionCostsCalculator, priorityQueues[unassignedJob.getIndex()], updateRound, unassignedJob, routes);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivity
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Deprecated
|
||||
class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCostsCalculator {
|
||||
|
||||
private VehicleRoutingActivityCosts activityCosts;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ package com.graphhopper.jsprit.core.algorithm.recreate;
|
|||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 15/10/15.
|
||||
*/
|
||||
|
|
@ -28,8 +30,14 @@ class ScoredJob {
|
|||
|
||||
static class BadJob extends ScoredJob {
|
||||
|
||||
BadJob(Job job) {
|
||||
super(job, 0., null, null, false);
|
||||
BadJob(Job job, List<String> failedConstraintNames) {
|
||||
super(job, 0., getEmptyInsertion(failedConstraintNames), null, false);
|
||||
}
|
||||
|
||||
private static InsertionData getEmptyInsertion(List<String> failedConstraintNames) {
|
||||
InsertionData empty = new InsertionData.NoInsertionFound();
|
||||
empty.getFailedConstraintNames().addAll(failedConstraintNames);
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ class Scorer {
|
|||
if (secondBest == null) { //either there is only one vehicle or there are more vehicles, but they cannot load unassignedJob
|
||||
//if only one vehicle, I want the job to be inserted with min iCosts
|
||||
//if there are more vehicles, I want this job to be prioritized since there are no alternatives
|
||||
score = (4 - unassignedJob.getPriority()) * (Integer.MAX_VALUE - best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||
score = (11 - unassignedJob.getPriority()) * (Integer.MAX_VALUE - best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||
} else {
|
||||
score = (4 - unassignedJob.getPriority()) * (secondBest.getInsertionCost() - best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||
score = (11 - unassignedJob.getPriority()) * (secondBest.getInsertionCost() - best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,6 @@ import com.graphhopper.jsprit.core.problem.job.Job;
|
|||
*/
|
||||
public interface ScoringFunction {
|
||||
|
||||
public double score(InsertionData best, Job job);
|
||||
double score(InsertionData best, Job job);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@
|
|||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.*;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.HardActivityConstraint.ConstraintsStatus;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.SoftActivityConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||
import com.graphhopper.jsprit.core.problem.driver.Driver;
|
||||
|
|
@ -36,6 +38,8 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
|
|
@ -43,13 +47,13 @@ import java.util.Iterator;
|
|||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
final class ServiceInsertionCalculator implements JobInsertionCostsCalculator {
|
||||
final class ServiceInsertionCalculator extends AbstractInsertionCalculator {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ServiceInsertionCalculator.class);
|
||||
|
||||
private HardRouteConstraint hardRouteLevelConstraint;
|
||||
// private HardRouteConstraint hardRouteLevelConstraint;
|
||||
|
||||
private HardActivityConstraint hardActivityLevelConstraint;
|
||||
// private HardActivityConstraint hardActivityLevelConstraint;
|
||||
|
||||
private SoftRouteConstraint softRouteConstraint;
|
||||
|
||||
|
|
@ -65,12 +69,13 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
|
||||
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
|
||||
|
||||
private ConstraintManager constraintManager;
|
||||
|
||||
public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager) {
|
||||
super();
|
||||
this.transportCosts = routingCosts;
|
||||
this.activityCosts = activityCosts;
|
||||
hardRouteLevelConstraint = constraintManager;
|
||||
hardActivityLevelConstraint = constraintManager;
|
||||
this.constraintManager = constraintManager;
|
||||
softActivityConstraint = constraintManager;
|
||||
softRouteConstraint = constraintManager;
|
||||
this.additionalTransportCostsCalculator = additionalTransportCostsCalculator;
|
||||
|
|
@ -103,9 +108,10 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
/*
|
||||
check hard constraints at route level
|
||||
*/
|
||||
if (!hardRouteLevelConstraint.fulfilled(insertionContext)) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
InsertionData noInsertion = checkRouteContraints(insertionContext, constraintManager);
|
||||
if (noInsertion != null) return noInsertion;
|
||||
|
||||
Collection<String> failedActivityConstraints = new ArrayList<>();
|
||||
|
||||
/*
|
||||
check soft constraints at route level
|
||||
|
|
@ -142,7 +148,7 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
ActivityContext activityContext = new ActivityContext();
|
||||
activityContext.setInsertionIndex(actIndex);
|
||||
insertionContext.setActivityContext(activityContext);
|
||||
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
|
||||
ConstraintsStatus status = fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime, failedActivityConstraints, constraintManager);
|
||||
if (status.equals(ConstraintsStatus.FULFILLED)) {
|
||||
double additionalICostsAtActLevel = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
|
||||
double additionalTransportationCosts = additionalTransportCostsCalculator.getCosts(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
|
||||
|
|
@ -163,7 +169,9 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
actIndex++;
|
||||
}
|
||||
if(insertionIndex == InsertionData.NO_INDEX) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
InsertionData emptyInsertionData = new InsertionData.NoInsertionFound();
|
||||
emptyInsertionData.getFailedConstraintNames().addAll(failedActivityConstraints);
|
||||
return emptyInsertionData;
|
||||
}
|
||||
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
|
||||
deliveryAct2Insert.setTheoreticalEarliestOperationStartTime(bestTimeWindow.getStart());
|
||||
|
|
@ -173,4 +181,6 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import java.util.Comparator;
|
|||
import java.util.List;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
|
||||
@Deprecated
|
||||
final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsCalculator {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ServiceInsertionOnRouteLevelCalculator.class);
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@
|
|||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.*;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.HardActivityConstraint.ConstraintsStatus;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.SoftActivityConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||
import com.graphhopper.jsprit.core.problem.driver.Driver;
|
||||
|
|
@ -36,16 +38,19 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator {
|
||||
final class ShipmentInsertionCalculator extends AbstractInsertionCalculator {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ShipmentInsertionCalculator.class);
|
||||
|
||||
private HardRouteConstraint hardRouteLevelConstraint;
|
||||
private final ConstraintManager constraintManager;
|
||||
|
||||
private HardActivityConstraint hardActivityLevelConstraint;
|
||||
// private HardRouteConstraint hardRouteLevelConstraint;
|
||||
//
|
||||
// private HardActivityConstraint hardActivityLevelConstraint;
|
||||
|
||||
private SoftRouteConstraint softRouteConstraint;
|
||||
|
||||
|
|
@ -64,8 +69,7 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, ConstraintManager constraintManager) {
|
||||
super();
|
||||
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||
this.hardRouteLevelConstraint = constraintManager;
|
||||
this.hardActivityLevelConstraint = constraintManager;
|
||||
this.constraintManager = constraintManager;
|
||||
this.softActivityConstraint = constraintManager;
|
||||
this.softRouteConstraint = constraintManager;
|
||||
this.transportCosts = routingCosts;
|
||||
|
|
@ -99,9 +103,8 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
/*
|
||||
check hard route constraints
|
||||
*/
|
||||
if (!hardRouteLevelConstraint.fulfilled(insertionContext)) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
InsertionData noInsertion = checkRouteContraints(insertionContext, constraintManager);
|
||||
if (noInsertion != null) return noInsertion;
|
||||
/*
|
||||
check soft route constraints
|
||||
*/
|
||||
|
|
@ -132,6 +135,7 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
//pickupShipmentLoop
|
||||
List<TourActivity> activities = currentRoute.getTourActivities().getActivities();
|
||||
|
||||
List<String> failedActivityConstraints = new ArrayList<>();
|
||||
while (!tourEnd) {
|
||||
TourActivity nextAct;
|
||||
if (i < activities.size()) {
|
||||
|
|
@ -148,7 +152,7 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
ActivityContext activityContext = new ActivityContext();
|
||||
activityContext.setInsertionIndex(i);
|
||||
insertionContext.setActivityContext(activityContext);
|
||||
ConstraintsStatus pickupShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime);
|
||||
ConstraintsStatus pickupShipmentConstraintStatus = fulfilled(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime, failedActivityConstraints, constraintManager);
|
||||
if (pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED)) {
|
||||
pickupInsertionNotFulfilledBreak = false;
|
||||
continue;
|
||||
|
|
@ -194,7 +198,7 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
ActivityContext activityContext_ = new ActivityContext();
|
||||
activityContext_.setInsertionIndex(j);
|
||||
insertionContext.setActivityContext(activityContext_);
|
||||
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop);
|
||||
ConstraintsStatus deliverShipmentConstraintStatus = fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop, failedActivityConstraints, constraintManager);
|
||||
if (deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)) {
|
||||
double additionalDeliveryICosts = softActivityConstraint.getCosts(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop);
|
||||
double deliveryAIC = calculate(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop);
|
||||
|
|
@ -230,7 +234,9 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator {
|
|||
i++;
|
||||
}
|
||||
if (pickupInsertionIndex == InsertionData.NO_INDEX) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
InsertionData emptyInsertionData = new InsertionData.NoInsertionFound();
|
||||
emptyInsertionData.getFailedConstraintNames().addAll(failedActivityConstraints);
|
||||
return emptyInsertionData;
|
||||
}
|
||||
InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver);
|
||||
pickupShipment.setTheoreticalEarliestOperationStartTime(bestPickupTimeWindow.getStart());
|
||||
|
|
|
|||
|
|
@ -15,50 +15,48 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
|
||||
import com.graphhopper.jsprit.core.algorithm.recreate.listener.JobInsertedListener;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 11/01/17.
|
||||
*/
|
||||
class SolutionCompletenessRatio implements InsertionStartsListener, JobInsertedListener {
|
||||
|
||||
final class ConfigureFixCostCalculator implements InsertionStartsListener, JobInsertedListener {
|
||||
protected double solutionCompletenessRatio = 0.5;
|
||||
|
||||
private final VehicleRoutingProblem vrp;
|
||||
|
||||
private final JobInsertionConsideringFixCostsCalculator calcConsideringFix;
|
||||
|
||||
private final double minRatio = 0.5;
|
||||
private final int nuOfJobs;
|
||||
|
||||
private int nuOfJobsToRecreate;
|
||||
|
||||
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, JobInsertionConsideringFixCostsCalculator calcConsideringFix) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
this.calcConsideringFix = calcConsideringFix;
|
||||
public SolutionCompletenessRatio(int nuOfJobs) {
|
||||
this.nuOfJobs = nuOfJobs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=configureFixCostCalculator]";
|
||||
public void setSolutionCompletenessRatio(double ratio) {
|
||||
solutionCompletenessRatio = ratio;
|
||||
}
|
||||
|
||||
public double getSolutionCompletenessRatio() {
|
||||
return solutionCompletenessRatio;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||
this.nuOfJobsToRecreate = unassignedJobs.size();
|
||||
double completenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) vrp.getJobs().values().size()));
|
||||
calcConsideringFix.setSolutionCompletenessRatio(Math.max(minRatio,completenessRatio));
|
||||
solutionCompletenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) nuOfJobs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||
nuOfJobsToRecreate--;
|
||||
double completenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) vrp.getJobs().values().size()));
|
||||
calcConsideringFix.setSolutionCompletenessRatio(Math.max(minRatio,completenessRatio));
|
||||
solutionCompletenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) nuOfJobs));
|
||||
}
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCo
|
|||
}
|
||||
Vehicle selectedVehicle = currentRoute.getVehicle();
|
||||
Driver selectedDriver = currentRoute.getDriver();
|
||||
InsertionData bestIData = InsertionData.createEmptyInsertionData();
|
||||
InsertionData bestIData = new InsertionData.NoInsertionFound();
|
||||
double bestKnownCost_ = bestKnownCost;
|
||||
Collection<Vehicle> relevantVehicles = new ArrayList<Vehicle>();
|
||||
if (!(selectedVehicle instanceof VehicleImpl.NoVehicle)) {
|
||||
|
|
@ -115,6 +115,7 @@ final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCo
|
|||
else depTime = v.getEarliestDeparture();
|
||||
InsertionData iData = insertionCalculator.getInsertionData(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
|
||||
if (iData instanceof InsertionData.NoInsertionFound) {
|
||||
bestIData.getFailedConstraintNames().addAll(iData.getFailedConstraintNames());
|
||||
continue;
|
||||
}
|
||||
if (iData.getInsertionCost() < bestKnownCost_) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class InsertionListeners {
|
||||
|
|
@ -74,6 +75,14 @@ public class InsertionListeners {
|
|||
}
|
||||
}
|
||||
|
||||
public void informJobUnassignedListeners(Job unassigned, List<String> reasons) {
|
||||
for (InsertionListener l : listeners) {
|
||||
if (l instanceof JobUnassignedListener) {
|
||||
((JobUnassignedListener) l).informJobUnassigned(unassigned, reasons);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(InsertionListener insertionListener) {
|
||||
listeners.add(insertionListener);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,12 +15,18 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.graphhopper.jsprit.analysis.util;
|
||||
|
||||
import com.graphhopper.jsprit.core.util.BenchmarkResult;
|
||||
package com.graphhopper.jsprit.core.algorithm.recreate.listener;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface BenchmarkWriter {
|
||||
public void write(Collection<BenchmarkResult> results);
|
||||
/**
|
||||
* Created by schroeder on 06/02/17.
|
||||
*/
|
||||
public interface JobUnassignedListener extends InsertionListener {
|
||||
|
||||
void informJobUnassigned(Job unassigned, Collection<String> failedConstraintNames);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.graphhopper.jsprit.core.algorithm.ruin;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.AbstractActivity;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
import com.graphhopper.jsprit.core.util.RandomUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* RuinString is adopted from
|
||||
* <p>
|
||||
* Technical report 7.11.2016
|
||||
* A Fresh Ruin & Recreate Implementation for the Capacitated Vehicle Routing Problem
|
||||
* Jan Christiaens, Greet Vanden Berghe
|
||||
* KU Leuven, Department of Computer Science, CODeS & iMinds-ITEC
|
||||
* Gebr. De Smetstraat 1, 9000 Gent, Belgium, jan.christiaens@cs.kuleuven.be, greet.vandenberghe@cs.kuleuven.be
|
||||
* <p>
|
||||
* https://lirias.kuleuven.be/bitstream/123456789/556398/1/asb_rr_2016.pdf
|
||||
*
|
||||
* @author stefan
|
||||
*/
|
||||
public final class RuinString extends AbstractRuinStrategy {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(RuinString.class);
|
||||
|
||||
private final VehicleRoutingProblem vrp;
|
||||
|
||||
private final JobNeighborhoods jobNeighborhoods;
|
||||
|
||||
private int kMin = 1;
|
||||
|
||||
private int kMax = 6;
|
||||
|
||||
private int lMin = 30;
|
||||
|
||||
private int lMax = 60;
|
||||
|
||||
public RuinString(VehicleRoutingProblem vrp, JobNeighborhoods jobNeighborhoods) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
this.jobNeighborhoods = jobNeighborhoods;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
public void setNoRoutes(int kMin, int kMax) {
|
||||
this.kMin = kMin;
|
||||
this.kMax = kMax;
|
||||
}
|
||||
|
||||
public void setStringLength(int lMin, int lMax) {
|
||||
this.lMin = lMin;
|
||||
this.lMax = lMax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=splitRuin]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Ruins the collection of vehicleRoutes, i.e. removes a share of jobs. First, it selects a job randomly. Second, it identifies its neighborhood. And finally, it removes
|
||||
* the neighborhood plus the randomly selected job from the number of vehicleRoutes. All removed jobs are then returned as a collection.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
if (vehicleRoutes.isEmpty() || vrp.getJobs().isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
int noStrings;
|
||||
if (kMin == kMax) noStrings = kMax;
|
||||
else noStrings = kMin + random.nextInt((kMax - kMin));
|
||||
noStrings = Math.min(noStrings, vehicleRoutes.size());
|
||||
Set<Job> unassignedJobs = new HashSet<>();
|
||||
Set<VehicleRoute> ruinedRoutes = new HashSet<>();
|
||||
Job prevJob = RandomUtils.nextJob(vrp.getJobs().values(), random);
|
||||
Iterator<Job> neighborhoodIterator = jobNeighborhoods.getNearestNeighborsIterator(kMax * lMax, prevJob);
|
||||
while (neighborhoodIterator.hasNext() && ruinedRoutes.size() <= noStrings) {
|
||||
if (!unassignedJobs.contains(prevJob)) {
|
||||
VehicleRoute route = getRouteOf(prevJob, vehicleRoutes);
|
||||
if (route != null && !ruinedRoutes.contains(route)) {
|
||||
if (random.nextDouble() < .5) {
|
||||
ruinRouteWithStringRuin(route, prevJob, unassignedJobs);
|
||||
} else {
|
||||
ruinRouteWithSplitStringRuin(route, prevJob, unassignedJobs);
|
||||
}
|
||||
ruinedRoutes.add(route);
|
||||
}
|
||||
}
|
||||
prevJob = neighborhoodIterator.next();
|
||||
}
|
||||
return unassignedJobs;
|
||||
}
|
||||
|
||||
private VehicleRoute getRouteOf(Job job, Collection<VehicleRoute> vehicleRoutes) {
|
||||
for (VehicleRoute route : vehicleRoutes) {
|
||||
if (route.getTourActivities().servesJob(job)) return route;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ruinRouteWithSplitStringRuin(VehicleRoute seedRoute, Job prevJob, Set<Job> unassignedJobs) {
|
||||
int noActivities = seedRoute.getActivities().size();
|
||||
int stringLength;
|
||||
if (lMin == lMax) stringLength = lMin;
|
||||
else stringLength = lMin + random.nextInt(lMax - lMin);
|
||||
stringLength = Math.min(stringLength, seedRoute.getActivities().size());
|
||||
|
||||
int preservedSubstringLength = StringUtil.determineSubstringLength(stringLength, noActivities, random);
|
||||
|
||||
List<AbstractActivity> acts = vrp.getActivities(prevJob);
|
||||
AbstractActivity randomSeedAct = RandomUtils.nextItem(acts, random);
|
||||
int seedIndex = 0;
|
||||
|
||||
int index = 0;
|
||||
for (TourActivity act : seedRoute.getActivities()) {
|
||||
if (act.getIndex() == randomSeedAct.getIndex()) {
|
||||
seedIndex = index;
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
int totalStringLength = stringLength + preservedSubstringLength;
|
||||
List<Integer> stringBounds = StringUtil.getLowerBoundsOfAllStrings(totalStringLength, seedIndex, noActivities);
|
||||
if (stringBounds.isEmpty()) return;
|
||||
int lowerBound = RandomUtils.nextItem(stringBounds, random);
|
||||
|
||||
List<Job> jobs2Remove = new ArrayList<>();
|
||||
int startIndexOfPreservedSubstring = random.nextInt(stringLength);
|
||||
int position = 0;
|
||||
int noStringsInPreservedSubstring = 0;
|
||||
boolean isPreservedSubstring = false;
|
||||
for (int i = lowerBound; i < (lowerBound + totalStringLength); i++) {
|
||||
if (position == startIndexOfPreservedSubstring) {
|
||||
isPreservedSubstring = true;
|
||||
}
|
||||
if (noStringsInPreservedSubstring >= preservedSubstringLength) {
|
||||
isPreservedSubstring = false;
|
||||
}
|
||||
if (!isPreservedSubstring) {
|
||||
TourActivity act = seedRoute.getActivities().get(i);
|
||||
if (act instanceof TourActivity.JobActivity) {
|
||||
Job job = ((TourActivity.JobActivity) act).getJob();
|
||||
if (vrp.getJobs().containsKey(job.getId())) {
|
||||
jobs2Remove.add(job);
|
||||
}
|
||||
}
|
||||
} else noStringsInPreservedSubstring++;
|
||||
position++;
|
||||
}
|
||||
for (Job job : jobs2Remove) {
|
||||
removeJob(job, seedRoute);
|
||||
unassignedJobs.add(job);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void ruinRouteWithStringRuin(VehicleRoute seedRoute, Job prevJob, Set<Job> unassignedJobs) {
|
||||
int stringLength = lMin + random.nextInt(lMax - lMin);
|
||||
stringLength = Math.min(stringLength, seedRoute.getActivities().size());
|
||||
List<AbstractActivity> acts = vrp.getActivities(prevJob);
|
||||
AbstractActivity randomSeedAct = RandomUtils.nextItem(acts, random);
|
||||
int seedIndex = 0;
|
||||
int noActivities = seedRoute.getActivities().size();
|
||||
int index = 0;
|
||||
for (TourActivity act : seedRoute.getActivities()) {
|
||||
if (act.getIndex() == randomSeedAct.getIndex()) {
|
||||
seedIndex = index;
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
List<Integer> stringBounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities);
|
||||
if (stringBounds.isEmpty()) return;
|
||||
int lowerBound = RandomUtils.nextItem(stringBounds, random);
|
||||
List<Job> jobs2Remove = new ArrayList<>();
|
||||
for (int i = lowerBound; i < (lowerBound + stringLength); i++) {
|
||||
TourActivity act = seedRoute.getActivities().get(i);
|
||||
if (act instanceof TourActivity.JobActivity) {
|
||||
Job job = ((TourActivity.JobActivity) act).getJob();
|
||||
if (vrp.getJobs().containsKey(job.getId())) {
|
||||
jobs2Remove.add(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Job job : jobs2Remove) {
|
||||
removeJob(job, seedRoute);
|
||||
unassignedJobs.add(job);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.algorithm.ruin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 13/01/17.
|
||||
*/
|
||||
class StringUtil {
|
||||
|
||||
static List<Integer> getLowerBoundsOfAllStrings(int length, int seedIndex, int routeLength) {
|
||||
List<Integer> lowerBounds = new ArrayList<>();
|
||||
for (int i = 1; i <= length; i++) {
|
||||
int lower = seedIndex - (length - i);
|
||||
int upper = seedIndex + (i - 1);
|
||||
if (lower >= 0 && upper < routeLength) {
|
||||
lowerBounds.add(lower);
|
||||
}
|
||||
}
|
||||
return lowerBounds;
|
||||
}
|
||||
|
||||
static int determineSubstringLength(int baseLength, int routeLength, Random random) {
|
||||
if (baseLength == routeLength) return 0;
|
||||
int substringLength = 1;
|
||||
while (baseLength + substringLength < routeLength) {
|
||||
if (random.nextDouble() < 0.01) {
|
||||
return substringLength;
|
||||
} else substringLength++;
|
||||
}
|
||||
return substringLength;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.algorithm.state;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.cost.TransportDistance;
|
||||
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.TourActivity;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeKey;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 17/05/16.
|
||||
*/
|
||||
public class VehicleDependentTraveledDistance implements StateUpdater, ActivityVisitor {
|
||||
|
||||
static class State {
|
||||
|
||||
Location prevLocation;
|
||||
|
||||
double distance;
|
||||
|
||||
public State(Location prevLocation, double distance) {
|
||||
this.prevLocation = prevLocation;
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
public Location getPrevLocation() {
|
||||
return prevLocation;
|
||||
}
|
||||
|
||||
public double getDistance() {
|
||||
return distance;
|
||||
}
|
||||
}
|
||||
|
||||
private final TransportDistance transportDistance;
|
||||
|
||||
private final StateManager stateManager;
|
||||
|
||||
private final StateId traveledDistanceId;
|
||||
|
||||
private VehicleRoute route;
|
||||
|
||||
private List<Vehicle> uniqueVehicles;
|
||||
|
||||
private Map<VehicleTypeKey,State> states;
|
||||
|
||||
public VehicleDependentTraveledDistance(TransportDistance transportCostMatrices, StateManager stateManager, StateId distanceInRouteId, Collection<Vehicle> vehicles) {
|
||||
this.transportDistance = transportCostMatrices;
|
||||
this.stateManager = stateManager;
|
||||
this.traveledDistanceId = distanceInRouteId;
|
||||
uniqueVehicles = getUniqueVehicles(vehicles);
|
||||
}
|
||||
|
||||
private List<Vehicle> getUniqueVehicles(Collection<Vehicle> vehicles) {
|
||||
Set<VehicleTypeKey> types = new HashSet<>();
|
||||
List<Vehicle> uniqueVehicles = new ArrayList<>();
|
||||
for(Vehicle v : vehicles){
|
||||
if(!types.contains(v.getVehicleTypeIdentifier())){
|
||||
types.add(v.getVehicleTypeIdentifier());
|
||||
uniqueVehicles.add(v);
|
||||
}
|
||||
}
|
||||
return uniqueVehicles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void begin(VehicleRoute route) {
|
||||
this.route = route;
|
||||
states = new HashMap<>();
|
||||
for(Vehicle v : uniqueVehicles){
|
||||
State state = new State(v.getStartLocation(),0);
|
||||
states.put(v.getVehicleTypeIdentifier(),state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(TourActivity activity) {
|
||||
for(Vehicle v : uniqueVehicles){
|
||||
State old = states.get(v.getVehicleTypeIdentifier());
|
||||
double distance = old.getDistance();
|
||||
distance += transportDistance.getDistance(old.getPrevLocation(),activity.getLocation(),0,v);
|
||||
stateManager.putActivityState(activity,v,traveledDistanceId,distance);
|
||||
states.put(v.getVehicleTypeIdentifier(),new State(activity.getLocation(),distance));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
for(Vehicle v : uniqueVehicles){
|
||||
State old = states.get(v.getVehicleTypeIdentifier());
|
||||
double distance = old.getDistance();
|
||||
if(v.isReturnToDepot()) {
|
||||
distance += transportDistance.getDistance(old.getPrevLocation(), v.getEndLocation(), 0, v);
|
||||
}
|
||||
stateManager.putRouteState(route,v,traveledDistanceId, distance);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -30,7 +30,9 @@ import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -119,9 +121,22 @@ public class VariationCoefficientTermination implements PrematureAlgorithmTermin
|
|||
}
|
||||
}
|
||||
|
||||
public void informIterationEnds(int i, VehicleRoutingProblem problem, VehicleRoutingProblemSolution solution) {
|
||||
informIterationEnds(i, problem, toList(solution));
|
||||
}
|
||||
|
||||
private List<VehicleRoutingProblemSolution> toList(VehicleRoutingProblemSolution solution) {
|
||||
List<VehicleRoutingProblemSolution> solutions = new ArrayList<>();
|
||||
solutions.add(solution);
|
||||
return solutions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
if (lastAccepted == null) lastAccepted = Solutions.bestOf(solutions);
|
||||
}
|
||||
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, VehicleRoutingProblemSolution solution) {
|
||||
informIterationStarts(i, problem, toList(solution));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ import com.graphhopper.jsprit.core.problem.job.Job;
|
|||
public abstract class AbstractJob implements Job {
|
||||
|
||||
private int index;
|
||||
private Object userData;
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
|
@ -35,4 +37,15 @@ public abstract class AbstractJob implements Job {
|
|||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User-specific domain data associated by the job
|
||||
*/
|
||||
public Object getUserData() {
|
||||
return userData;
|
||||
}
|
||||
|
||||
protected void setUserData(Object userData) {
|
||||
this.userData = userData;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public abstract class AbstractVehicle implements Vehicle {
|
|||
|
||||
private int index;
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
|
@ -44,6 +45,21 @@ public abstract class AbstractVehicle implements Vehicle {
|
|||
|
||||
private VehicleTypeKey vehicleIdentifier;
|
||||
|
||||
private Object userData;
|
||||
|
||||
/**
|
||||
* @return User-specific domain data associated with the vehicle
|
||||
*/
|
||||
@Override
|
||||
public Object getUserData() {
|
||||
return userData;
|
||||
}
|
||||
|
||||
protected void setUserData(Object userData) {
|
||||
this.userData = userData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
|
@ -52,6 +68,7 @@ public abstract class AbstractVehicle implements Vehicle {
|
|||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VehicleTypeKey getVehicleTypeIdentifier() {
|
||||
return vehicleIdentifier;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,26 +64,77 @@ public final class Location implements HasIndex, HasId {
|
|||
|
||||
private Coordinate coordinate;
|
||||
|
||||
private String name = "";
|
||||
|
||||
private Object userData;
|
||||
|
||||
public static Builder newInstance() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets user specific domain data associated with the object.
|
||||
*
|
||||
* <p>
|
||||
* The user data is a black box for the framework, it only stores it,
|
||||
* but never interacts with it in any way.
|
||||
* </p>
|
||||
*
|
||||
* @param userData
|
||||
* any object holding the domain specific user data
|
||||
* associated with the object.
|
||||
* @return builder
|
||||
*/
|
||||
public Builder setUserData(Object userData) {
|
||||
this.userData = userData;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets location index
|
||||
*
|
||||
* @param index
|
||||
* @return the builder
|
||||
*/
|
||||
public Builder setIndex(int index) {
|
||||
if (index < 0) throw new IllegalArgumentException("index must be >= 0");
|
||||
this.index = index;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets coordinate of location
|
||||
*
|
||||
* @param coordinate
|
||||
* @return
|
||||
*/
|
||||
public Builder setCoordinate(Coordinate coordinate) {
|
||||
this.coordinate = coordinate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets location id
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public Builder setId(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds name, e.g. street name, to location
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public Builder setName(String name){
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Location build() {
|
||||
if (id == null && coordinate == null) {
|
||||
if (index == -1) throw new IllegalArgumentException("either id or coordinate or index must be set");
|
||||
|
|
@ -107,10 +158,23 @@ public final class Location implements HasIndex, HasId {
|
|||
|
||||
private final String id;
|
||||
|
||||
private final String name;
|
||||
|
||||
private Object userData;
|
||||
|
||||
private Location(Builder builder) {
|
||||
this.userData = builder.userData;
|
||||
this.index = builder.index;
|
||||
this.coordinate = builder.coordinate;
|
||||
this.id = builder.id;
|
||||
this.name = builder.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User-specific domain data associated by the job
|
||||
*/
|
||||
public Object getUserData() {
|
||||
return userData;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -127,6 +191,8 @@ public final class Location implements HasIndex, HasId {
|
|||
return coordinate;
|
||||
}
|
||||
|
||||
public String getName() { return name; }
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
|||
|
|
@ -568,8 +568,6 @@ public class VehicleRoutingProblem {
|
|||
*/
|
||||
private final FleetSize fleetSize;
|
||||
|
||||
private final Locations locations;
|
||||
|
||||
private Map<Job, List<AbstractActivity>> activityMap;
|
||||
|
||||
private int nuActivities;
|
||||
|
|
@ -591,7 +589,6 @@ public class VehicleRoutingProblem {
|
|||
this.initialVehicleRoutes = builder.initialRoutes;
|
||||
this.transportCosts = builder.transportCosts;
|
||||
this.activityCosts = builder.activityCosts;
|
||||
this.locations = builder.getLocations();
|
||||
this.activityMap = builder.activityMap;
|
||||
this.nuActivities = builder.activityIndexCounter;
|
||||
this.allLocations = builder.allLocations;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import java.util.List;
|
|||
*/
|
||||
public class ConstraintManager implements HardActivityConstraint, HardRouteConstraint, SoftActivityConstraint, SoftRouteConstraint {
|
||||
|
||||
|
||||
public static enum Priority {
|
||||
CRITICAL, HIGH, LOW
|
||||
}
|
||||
|
|
@ -45,7 +46,7 @@ public class ConstraintManager implements HardActivityConstraint, HardRouteConst
|
|||
|
||||
private HardActivityLevelConstraintManager actLevelConstraintManager = new HardActivityLevelConstraintManager();
|
||||
|
||||
private HardRouteLevelConstraintManager routeLevelConstraintManager = new HardRouteLevelConstraintManager();
|
||||
private HardRouteLevelConstraintManager hardRouteConstraintManager = new HardRouteLevelConstraintManager();
|
||||
|
||||
private SoftActivityConstraintManager softActivityConstraintManager = new SoftActivityConstraintManager();
|
||||
|
||||
|
|
@ -76,6 +77,25 @@ public class ConstraintManager implements HardActivityConstraint, HardRouteConst
|
|||
resolveConstraints(constraints);
|
||||
}
|
||||
|
||||
public Collection<HardRouteConstraint> getHardRouteConstraints() {
|
||||
return hardRouteConstraintManager.getConstraints();
|
||||
}
|
||||
|
||||
public Collection<HardActivityConstraint> getCriticalHardActivityConstraints() {
|
||||
return actLevelConstraintManager.getCriticalConstraints();
|
||||
}
|
||||
|
||||
public Collection<HardActivityConstraint> getHighPrioHardActivityConstraints() {
|
||||
return actLevelConstraintManager.getHighPrioConstraints();
|
||||
}
|
||||
|
||||
public Collection<HardActivityConstraint> getLowPrioHardActivityConstraints() {
|
||||
return actLevelConstraintManager.getLowPrioConstraints();
|
||||
}
|
||||
// public Collection<HardActivityConstraint> getHardActivityConstraints() {
|
||||
// return actLevelConstraintManager.g;
|
||||
// }
|
||||
|
||||
public DependencyType[] getDependencyTypes() {
|
||||
return dependencyTypes;
|
||||
}
|
||||
|
|
@ -103,7 +123,7 @@ public class ConstraintManager implements HardActivityConstraint, HardRouteConst
|
|||
constraintTypeKnown = true;
|
||||
}
|
||||
if (c instanceof HardRouteConstraint) {
|
||||
routeLevelConstraintManager.addConstraint((HardRouteConstraint) c);
|
||||
hardRouteConstraintManager.addConstraint((HardRouteConstraint) c);
|
||||
constraintTypeKnown = true;
|
||||
}
|
||||
if (c instanceof SoftRouteConstraint) {
|
||||
|
|
@ -152,7 +172,7 @@ public class ConstraintManager implements HardActivityConstraint, HardRouteConst
|
|||
}
|
||||
|
||||
public void addConstraint(HardRouteConstraint routeLevelConstraint) {
|
||||
routeLevelConstraintManager.addConstraint(routeLevelConstraint);
|
||||
hardRouteConstraintManager.addConstraint(routeLevelConstraint);
|
||||
}
|
||||
|
||||
public void addConstraint(SoftActivityConstraint softActivityConstraint) {
|
||||
|
|
@ -165,7 +185,7 @@ public class ConstraintManager implements HardActivityConstraint, HardRouteConst
|
|||
|
||||
@Override
|
||||
public boolean fulfilled(JobInsertionContext insertionContext) {
|
||||
return routeLevelConstraintManager.fulfilled(insertionContext);
|
||||
return hardRouteConstraintManager.fulfilled(insertionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -176,7 +196,7 @@ public class ConstraintManager implements HardActivityConstraint, HardRouteConst
|
|||
public Collection<Constraint> getConstraints() {
|
||||
List<Constraint> constraints = new ArrayList<Constraint>();
|
||||
constraints.addAll(actLevelConstraintManager.getAllConstraints());
|
||||
constraints.addAll(routeLevelConstraintManager.getConstraints());
|
||||
constraints.addAll(hardRouteConstraintManager.getConstraints());
|
||||
constraints.addAll(softActivityConstraintManager.getConstraints());
|
||||
constraints.addAll(softRouteConstraintManager.getConstraints());
|
||||
return Collections.unmodifiableCollection(constraints);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.problem.constraint;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateId;
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
|
||||
import com.graphhopper.jsprit.core.problem.cost.TransportDistance;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.DeliverShipment;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.End;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.Start;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 11/10/16.
|
||||
*/
|
||||
public class MaxDistanceConstraint implements HardActivityConstraint{
|
||||
|
||||
private StateManager stateManager;
|
||||
|
||||
private StateId distanceId;
|
||||
|
||||
private TransportDistance distanceCalculator;
|
||||
|
||||
private Double[] maxDistances;
|
||||
|
||||
public MaxDistanceConstraint(StateManager stateManager, StateId distanceId, TransportDistance distanceCalculator, Map<Vehicle,Double> maxDistancePerVehicleMap) {
|
||||
this.stateManager = stateManager;
|
||||
this.distanceId = distanceId;
|
||||
this.distanceCalculator = distanceCalculator;
|
||||
makeArray(maxDistancePerVehicleMap);
|
||||
}
|
||||
|
||||
private void makeArray(Map<Vehicle, Double> maxDistances) {
|
||||
int maxIndex = getMaxIndex(maxDistances.keySet());
|
||||
this.maxDistances = new Double[maxIndex+1];
|
||||
for(Vehicle v : maxDistances.keySet()){
|
||||
this.maxDistances[v.getIndex()]=maxDistances.get(v);
|
||||
}
|
||||
}
|
||||
|
||||
private int getMaxIndex(Collection<Vehicle> vehicles) {
|
||||
int index = 0;
|
||||
for(Vehicle v : vehicles){
|
||||
if(v.getIndex() > index) index = v.getIndex();
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
||||
if(!hasMaxDistance(iFacts.getNewVehicle())) return ConstraintsStatus.FULFILLED;
|
||||
Double currentDistance = 0d;
|
||||
boolean routeIsEmpty = iFacts.getRoute().isEmpty();
|
||||
if(!routeIsEmpty){
|
||||
currentDistance = stateManager.getRouteState(iFacts.getRoute(),iFacts.getNewVehicle(), distanceId,Double.class);
|
||||
}
|
||||
double maxDistance = getMaxDistance(iFacts.getNewVehicle());
|
||||
if(currentDistance > maxDistance) return ConstraintsStatus.NOT_FULFILLED_BREAK;
|
||||
|
||||
double distancePrevAct2NewAct = distanceCalculator.getDistance(prevAct.getLocation(), newAct.getLocation(), iFacts.getNewDepTime(), iFacts.getNewVehicle());
|
||||
double distanceNewAct2nextAct = distanceCalculator.getDistance(newAct.getLocation(), nextAct.getLocation(), iFacts.getNewDepTime(), iFacts.getNewVehicle());
|
||||
double distancePrevAct2NextAct = distanceCalculator.getDistance(prevAct.getLocation(), nextAct.getLocation(), prevActDepTime, iFacts.getNewVehicle());
|
||||
if(prevAct instanceof Start && nextAct instanceof End) distancePrevAct2NextAct = 0;
|
||||
if(nextAct instanceof End && !iFacts.getNewVehicle().isReturnToDepot()){
|
||||
distanceNewAct2nextAct = 0;
|
||||
distancePrevAct2NextAct = 0;
|
||||
}
|
||||
double additionalDistance = distancePrevAct2NewAct + distanceNewAct2nextAct - distancePrevAct2NextAct;
|
||||
if(currentDistance + additionalDistance > maxDistance) return ConstraintsStatus.NOT_FULFILLED;
|
||||
|
||||
|
||||
double additionalDistanceOfPickup = 0;
|
||||
if(newAct instanceof DeliverShipment){
|
||||
int iIndexOfPickup = iFacts.getRelatedActivityContext().getInsertionIndex();
|
||||
TourActivity pickup = iFacts.getAssociatedActivities().get(0);
|
||||
TourActivity actBeforePickup;
|
||||
if(iIndexOfPickup > 0) actBeforePickup = iFacts.getRoute().getActivities().get(iIndexOfPickup-1);
|
||||
else actBeforePickup = new Start(iFacts.getNewVehicle().getStartLocation(),0,Double.MAX_VALUE);
|
||||
TourActivity actAfterPickup;
|
||||
if (iIndexOfPickup < iFacts.getRoute().getActivities().size())
|
||||
actAfterPickup = iFacts.getRoute().getActivities().get(iIndexOfPickup);
|
||||
else
|
||||
actAfterPickup = nextAct;
|
||||
double distanceActBeforePickup2Pickup = distanceCalculator.getDistance(actBeforePickup.getLocation(), pickup.getLocation(), actBeforePickup.getEndTime(), iFacts.getNewVehicle());
|
||||
double distancePickup2ActAfterPickup = distanceCalculator.getDistance(pickup.getLocation(), actAfterPickup.getLocation(), iFacts.getRelatedActivityContext().getEndTime(), iFacts.getNewVehicle());
|
||||
double distanceBeforePickup2AfterPickup = distanceCalculator.getDistance(actBeforePickup.getLocation(), actAfterPickup.getLocation(), actBeforePickup.getEndTime(), iFacts.getNewVehicle());
|
||||
if (routeIsEmpty) distanceBeforePickup2AfterPickup = 0;
|
||||
if (actAfterPickup instanceof End && !iFacts.getNewVehicle().isReturnToDepot()) {
|
||||
distancePickup2ActAfterPickup = 0;
|
||||
distanceBeforePickup2AfterPickup = 0;
|
||||
}
|
||||
additionalDistanceOfPickup = distanceActBeforePickup2Pickup + distancePickup2ActAfterPickup - distanceBeforePickup2AfterPickup;
|
||||
}
|
||||
|
||||
|
||||
if(currentDistance + additionalDistance + additionalDistanceOfPickup > maxDistance){
|
||||
return ConstraintsStatus.NOT_FULFILLED;
|
||||
}
|
||||
|
||||
return ConstraintsStatus.FULFILLED;
|
||||
}
|
||||
|
||||
private boolean hasMaxDistance(Vehicle newVehicle){
|
||||
if(newVehicle.getIndex() >= this.maxDistances.length) return false;
|
||||
return this.maxDistances[newVehicle.getIndex()] != null;
|
||||
}
|
||||
|
||||
private double getMaxDistance(Vehicle newVehicle) {
|
||||
Double maxDistance = this.maxDistances[newVehicle.getIndex()];
|
||||
if(maxDistance == null) return Double.MAX_VALUE;
|
||||
return maxDistance;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,21 +20,32 @@ package com.graphhopper.jsprit.core.problem.constraint;
|
|||
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateId;
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
|
||||
import com.graphhopper.jsprit.core.algorithm.state.UpdateMaxTimeInVehicle;
|
||||
import com.graphhopper.jsprit.core.algorithm.state.UpdateVehicleDependentPracticalTimeWindows;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.cost.TransportTime;
|
||||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||
import com.graphhopper.jsprit.core.problem.job.Shipment;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.DeliveryActivity;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.End;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.PickupActivity;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 15/09/16.
|
||||
*/
|
||||
public class MaxTimeInVehicleConstraint implements HardActivityConstraint {
|
||||
|
||||
private final VehicleRoutingProblem vrp;
|
||||
|
||||
private final TransportTime transportTime;
|
||||
|
||||
private final VehicleRoutingActivityCosts activityCosts;
|
||||
|
|
@ -43,15 +54,19 @@ public class MaxTimeInVehicleConstraint implements HardActivityConstraint {
|
|||
|
||||
private final StateManager stateManager;
|
||||
|
||||
public MaxTimeInVehicleConstraint(TransportTime transportTime, VehicleRoutingActivityCosts activityCosts, StateId latestStartId, StateManager stateManager) {
|
||||
public MaxTimeInVehicleConstraint(TransportTime transportTime, VehicleRoutingActivityCosts activityCosts, StateId latestStartId, StateManager stateManager, VehicleRoutingProblem vrp) {
|
||||
this.transportTime = transportTime;
|
||||
this.latestStartId = latestStartId;
|
||||
this.stateManager = stateManager;
|
||||
this.activityCosts = activityCosts;
|
||||
this.vrp = vrp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
||||
public ConstraintsStatus fulfilled(final JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
||||
boolean newActIsPickup = newAct instanceof PickupActivity;
|
||||
boolean newActIsDelivery = newAct instanceof DeliveryActivity;
|
||||
boolean isShipment = iFacts.getJob() instanceof Shipment;
|
||||
/*
|
||||
1. check whether insertion of new shipment satisfies own max-in-vehicle-constraint
|
||||
2. check whether insertion of new shipment satisfies all other max-in-vehicle-constraints
|
||||
|
|
@ -75,7 +90,7 @@ public class MaxTimeInVehicleConstraint implements HardActivityConstraint {
|
|||
if(timeInVehicle > maxTimeInVehicle) return ConstraintsStatus.NOT_FULFILLED;
|
||||
|
||||
}
|
||||
else if(newAct instanceof PickupActivity){
|
||||
else if(newActIsPickup){
|
||||
if(iFacts.getAssociatedActivities().size() == 1){
|
||||
double maxTimeInVehicle = ((TourActivity.JobActivity)newAct).getJob().getMaxTimeInVehicle();
|
||||
//ToDo - estimate in vehicle time of pickups here - This seems to trickier than I thought
|
||||
|
|
@ -88,16 +103,47 @@ public class MaxTimeInVehicleConstraint implements HardActivityConstraint {
|
|||
|
||||
//************ 2. check whether insertion of new shipment satisfies all other max-in-vehicle-constraints
|
||||
|
||||
if(newActIsPickup || iFacts.getAssociatedActivities().size() == 1) {
|
||||
double latest;
|
||||
if (iFacts.getRoute().isEmpty()) latest = Double.MAX_VALUE;
|
||||
else if (nextAct instanceof End) {
|
||||
latest = stateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), latestStartId, Double.class);
|
||||
}
|
||||
else latest = stateManager.getActivityState(nextAct, iFacts.getNewVehicle(), latestStartId, Double.class);
|
||||
} else latest = stateManager.getActivityState(nextAct, iFacts.getNewVehicle(), latestStartId, Double.class);
|
||||
|
||||
if (nextActStart > latest) {
|
||||
return ConstraintsStatus.NOT_FULFILLED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(newActIsDelivery && iFacts.getAssociatedActivities().size() == 2){
|
||||
StateManager localStateManager = new StateManager(vrp);
|
||||
StateId stateId = localStateManager.createStateId("local-slack");
|
||||
UpdateMaxTimeInVehicle updateMaxTimeInVehicle = new UpdateMaxTimeInVehicle(localStateManager,stateId,transportTime,activityCosts);
|
||||
updateMaxTimeInVehicle.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() {
|
||||
@Override
|
||||
public Collection<Vehicle> get(VehicleRoute route) {
|
||||
return Arrays.asList(iFacts.getNewVehicle());
|
||||
}
|
||||
});
|
||||
updateMaxTimeInVehicle.begin(iFacts.getRoute());
|
||||
List<TourActivity> tourActivities = new ArrayList<>(iFacts.getRoute().getActivities());
|
||||
tourActivities.add(iFacts.getRelatedActivityContext().getInsertionIndex(),iFacts.getAssociatedActivities().get(0));
|
||||
for(TourActivity act : tourActivities){
|
||||
updateMaxTimeInVehicle.visit(act);
|
||||
}
|
||||
updateMaxTimeInVehicle.finish(tourActivities,iFacts.getJob());
|
||||
|
||||
double latest;
|
||||
if (iFacts.getRoute().isEmpty()) latest = Double.MAX_VALUE;
|
||||
else if (nextAct instanceof End) {
|
||||
latest = localStateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), stateId, Double.class);
|
||||
} else latest = localStateManager.getActivityState(nextAct, iFacts.getNewVehicle(), stateId, Double.class);
|
||||
|
||||
if (nextActStart > latest) {
|
||||
return ConstraintsStatus.NOT_FULFILLED;
|
||||
}
|
||||
|
||||
}
|
||||
return ConstraintsStatus.FULFILLED;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
*/
|
||||
package com.graphhopper.jsprit.core.problem.job;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.AbstractJob;
|
||||
import com.graphhopper.jsprit.core.problem.Capacity;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
|
|
@ -26,8 +28,6 @@ import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindows;
|
|||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindowsImpl;
|
||||
import com.graphhopper.jsprit.core.util.Coordinate;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Service implementation of a job.
|
||||
* <p>
|
||||
|
|
@ -91,10 +91,9 @@ public class Service extends AbstractJob {
|
|||
private boolean twAdded = false;
|
||||
|
||||
private int priority = 2;
|
||||
protected Object userData;
|
||||
|
||||
protected double maxTimeInVehicle = Double.MAX_VALUE;
|
||||
|
||||
Builder(String id){
|
||||
protected double maxTimeInVehicle = Double.MAX_VALUE;Builder(String id){
|
||||
this.id = id;
|
||||
timeWindows = new TimeWindowsImpl();
|
||||
timeWindows.add(timeWindow);
|
||||
|
|
@ -141,6 +140,24 @@ public class Service extends AbstractJob {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets user specific domain data associated with the object.
|
||||
*
|
||||
* <p>
|
||||
* The user data is a black box for the framework, it only stores it,
|
||||
* but never interacts with it in any way.
|
||||
* </p>
|
||||
*
|
||||
* @param userData
|
||||
* any object holding the domain specific user data
|
||||
* associated with the object.
|
||||
* @return builder
|
||||
*/
|
||||
public Builder<T> setUserData(Object userData) {
|
||||
this.userData = userData;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds capacity dimension.
|
||||
*
|
||||
|
|
@ -216,15 +233,16 @@ public class Service extends AbstractJob {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set priority to service. Only 1 = high priority, 2 = medium and 3 = low are allowed.
|
||||
* Set priority to service. Only 1 (very high) to 10 (very low) are allowed.
|
||||
* <p>
|
||||
* Default is 2 = medium.
|
||||
* Default is 2.
|
||||
*
|
||||
* @param priority
|
||||
* @return builder
|
||||
*/
|
||||
public Builder<T> setPriority(int priority) {
|
||||
if(priority < 1 || priority > 3) throw new IllegalArgumentException("incorrect priority. only 1 = high, 2 = medium and 3 = low is allowed");
|
||||
if (priority < 1 || priority > 10)
|
||||
throw new IllegalArgumentException("incorrect priority. only priority values from 1 to 10 are allowed where 1 = high and 10 is low");
|
||||
this.priority = priority;
|
||||
return this;
|
||||
}
|
||||
|
|
@ -259,7 +277,8 @@ public class Service extends AbstractJob {
|
|||
|
||||
private final double maxTimeInVehicle;
|
||||
|
||||
Service(Builder builder) {
|
||||
Service(Builder<?> builder) {
|
||||
setUserData(builder.userData);
|
||||
id = builder.id;
|
||||
serviceTime = builder.serviceTime;
|
||||
timeWindow = builder.timeWindow;
|
||||
|
|
@ -270,8 +289,7 @@ public class Service extends AbstractJob {
|
|||
location = builder.location;
|
||||
timeWindowManager = builder.timeWindows;
|
||||
priority = builder.priority;
|
||||
maxTimeInVehicle = builder.maxTimeInVehicle;
|
||||
}
|
||||
maxTimeInVehicle = builder.maxTimeInVehicle;}
|
||||
|
||||
public Collection<TimeWindow> getTimeWindows(){
|
||||
return timeWindowManager.getTimeWindows();
|
||||
|
|
@ -380,6 +398,7 @@ public class Service extends AbstractJob {
|
|||
*
|
||||
* @return priority
|
||||
*/
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
*/
|
||||
package com.graphhopper.jsprit.core.problem.job;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.AbstractJob;
|
||||
import com.graphhopper.jsprit.core.problem.Capacity;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
|
|
@ -24,8 +26,6 @@ import com.graphhopper.jsprit.core.problem.Skills;
|
|||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindowsImpl;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
/**
|
||||
* Shipment is an implementation of Job and consists of a pickup and a delivery of something.
|
||||
|
|
@ -89,6 +89,8 @@ public class Shipment extends AbstractJob {
|
|||
|
||||
private int priority = 2;
|
||||
|
||||
public Object userData;
|
||||
|
||||
public double maxTimeInVehicle = Double.MAX_VALUE;
|
||||
|
||||
/**
|
||||
|
|
@ -110,10 +112,29 @@ public class Shipment extends AbstractJob {
|
|||
deliveryTimeWindows.add(deliveryTimeWindow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets user specific domain data associated with the object.
|
||||
*
|
||||
* <p>
|
||||
* The user data is a black box for the framework, it only stores it,
|
||||
* but never interacts with it in any way.
|
||||
* </p>
|
||||
*
|
||||
* @param userData
|
||||
* any object holding the domain specific user data
|
||||
* associated with the object.
|
||||
* @return builder
|
||||
*/
|
||||
public Builder setUserData(Object userData) {
|
||||
this.userData = userData;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets pickup location.
|
||||
*
|
||||
* @param pickupLocation pickup location
|
||||
* @param pickupLocation
|
||||
* pickup location
|
||||
* @return builder
|
||||
*/
|
||||
public Builder setPickupLocation(Location pickupLocation) {
|
||||
|
|
@ -271,7 +292,7 @@ public class Shipment extends AbstractJob {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set priority to shipment. Only 1 = high priority, 2 = medium and 3 = low are allowed.
|
||||
* Set priority to shipment. Only 1 (high) to 10 (low) are allowed.
|
||||
* <p>
|
||||
* Default is 2 = medium.
|
||||
*
|
||||
|
|
@ -279,7 +300,8 @@ public class Shipment extends AbstractJob {
|
|||
* @return builder
|
||||
*/
|
||||
public Builder setPriority(int priority) {
|
||||
if(priority < 1 || priority > 3) throw new IllegalArgumentException("incorrect priority. only 1 = high, 2 = medium and 3 = low is allowed");
|
||||
if (priority < 1 || priority > 10)
|
||||
throw new IllegalArgumentException("incorrect priority. only 1 (very high) to 10 (very low) are allowed");
|
||||
this.priority = priority;
|
||||
return this;
|
||||
}
|
||||
|
|
@ -326,6 +348,7 @@ public class Shipment extends AbstractJob {
|
|||
private final double maxTimeInVehicle;
|
||||
|
||||
Shipment(Builder builder) {
|
||||
setUserData(builder.userData);
|
||||
this.id = builder.id;
|
||||
this.pickupServiceTime = builder.pickupServiceTime;
|
||||
this.pickupTimeWindow = builder.pickupTimeWindow;
|
||||
|
|
@ -454,6 +477,7 @@ public class Shipment extends AbstractJob {
|
|||
*
|
||||
* @return priority
|
||||
*/
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package com.graphhopper.jsprit.core.problem.solution.route;
|
|||
|
||||
import com.graphhopper.jsprit.core.problem.AbstractActivity;
|
||||
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.driver.Driver;
|
||||
import com.graphhopper.jsprit.core.problem.driver.DriverImpl;
|
||||
import com.graphhopper.jsprit.core.problem.job.*;
|
||||
|
|
@ -196,16 +197,33 @@ public class VehicleRoute {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Builder addBreak(Break currentbreak) {
|
||||
if (currentbreak == null) throw new IllegalArgumentException("break must not be null");
|
||||
return addBreak(currentbreak, currentbreak.getTimeWindow());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Builder addBreak(Break currentbreak, TimeWindow timeWindow) {
|
||||
if (currentbreak == null) throw new IllegalArgumentException("break must not be null");
|
||||
return addService(currentbreak,timeWindow);
|
||||
}
|
||||
|
||||
public Builder addBreak(Break currentbreak, TimeWindow timeWindow, Location location) {
|
||||
if (currentbreak == null) throw new IllegalArgumentException("break must not be null");
|
||||
return addBreakInternally(currentbreak, timeWindow, location);
|
||||
}
|
||||
|
||||
private Builder addBreakInternally(Break currentBreak, TimeWindow timeWindow, Location breakLocation) {
|
||||
List<AbstractActivity> acts = jobActivityFactory.createActivities(currentBreak);
|
||||
BreakActivity act = (BreakActivity) acts.get(0);
|
||||
act.setTheoreticalEarliestOperationStartTime(timeWindow.getStart());
|
||||
act.setTheoreticalLatestOperationStartTime(timeWindow.getEnd());
|
||||
act.setLocation(breakLocation);
|
||||
tourActivities.addActivity(act);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a pickup to this route.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -72,6 +72,14 @@ public interface Vehicle extends HasId, HasIndex {
|
|||
public abstract VehicleTypeKey getVehicleTypeIdentifier();
|
||||
|
||||
public abstract Skills getSkills();
|
||||
/**
|
||||
* @return User-specific domain data associated with the vehicle
|
||||
*/
|
||||
public Object getUserData();
|
||||
|
||||
public abstract Break getBreak();
|
||||
// Switch to this as soon as we switct to Java 8:
|
||||
// default Object getUserData() {
|
||||
// return null;
|
||||
// };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@
|
|||
*/
|
||||
package com.graphhopper.jsprit.core.problem.vehicle;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.AbstractVehicle;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.Skills;
|
||||
import com.graphhopper.jsprit.core.problem.job.Break;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -130,6 +131,8 @@ public class VehicleImpl extends AbstractVehicle {
|
|||
|
||||
private Break aBreak;
|
||||
|
||||
private Object userData;
|
||||
|
||||
private Builder(String id) {
|
||||
super();
|
||||
this.id = id;
|
||||
|
|
@ -148,16 +151,39 @@ public class VehicleImpl extends AbstractVehicle {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets user specific domain data associated with the object.
|
||||
*
|
||||
* <p>
|
||||
* The user data is a black box for the framework, it only stores it,
|
||||
* but never interacts with it in any way.
|
||||
* </p>
|
||||
*
|
||||
* @param userData
|
||||
* any object holding the domain specific user data
|
||||
* associated with the object.
|
||||
* @return builder
|
||||
*/
|
||||
public Builder setUserData(Object userData) {
|
||||
this.userData = userData;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flag whether the vehicle must return to depot or not.
|
||||
* <p>
|
||||
* <p>If returnToDepot is true, the vehicle must return to specified end-location. If you
|
||||
* omit specifying the end-location, vehicle returns to start-location (that must to be set). If
|
||||
* you specify it, it returns to specified end-location.
|
||||
* <p>
|
||||
* <p>If returnToDepot is false, the end-location of the vehicle is endogenous.
|
||||
* If returnToDepot is true, the vehicle must return to specified
|
||||
* end-location. If you omit specifying the end-location, vehicle
|
||||
* returns to start-location (that must to be set). If you specify it,
|
||||
* it returns to specified end-location.
|
||||
* <p>
|
||||
* <p>
|
||||
* If returnToDepot is false, the end-location of the vehicle is
|
||||
* endogenous.
|
||||
*
|
||||
* @param returnToDepot true if vehicle need to return to depot, otherwise false
|
||||
* @param returnToDepot
|
||||
* true if vehicle need to return to depot, otherwise false
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder setReturnToDepot(boolean returnToDepot) {
|
||||
|
|
@ -239,9 +265,8 @@ public class VehicleImpl extends AbstractVehicle {
|
|||
if (startLocation != null && endLocation == null) {
|
||||
endLocation = startLocation;
|
||||
}
|
||||
if (startLocation == null && endLocation == null) {
|
||||
if (startLocation == null && endLocation == null)
|
||||
throw new IllegalArgumentException("vehicle requires startLocation. but neither locationId nor locationCoord nor startLocationId nor startLocationCoord has been set");
|
||||
}
|
||||
skills = skillBuilder.build();
|
||||
return new VehicleImpl(this);
|
||||
}
|
||||
|
|
@ -297,6 +322,7 @@ public class VehicleImpl extends AbstractVehicle {
|
|||
private final Break aBreak;
|
||||
|
||||
private VehicleImpl(Builder builder) {
|
||||
setUserData(builder.userData);
|
||||
id = builder.id;
|
||||
type = builder.type;
|
||||
earliestDeparture = builder.earliestStart;
|
||||
|
|
@ -346,6 +372,7 @@ public class VehicleImpl extends AbstractVehicle {
|
|||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReturnToDepot() {
|
||||
return returnToDepot;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,4 +56,13 @@ public interface VehicleType {
|
|||
|
||||
public String getProfile();
|
||||
|
||||
/**
|
||||
* @return User-specific domain data associated with the vehicle type
|
||||
*/
|
||||
public Object getUserData();
|
||||
|
||||
// Switch to this as soon as we switct to Java 8:
|
||||
// default Object getUserData() {
|
||||
// return null;
|
||||
// };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,16 +116,39 @@ public class VehicleTypeImpl implements VehicleType {
|
|||
|
||||
private boolean dimensionAdded = false;
|
||||
|
||||
private Object userData;
|
||||
|
||||
private Builder(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the maximum velocity this vehicle-type can go [in meter per seconds].
|
||||
* Sets user specific domain data associated with the object.
|
||||
*
|
||||
* <p>
|
||||
* The user data is a black box for the framework, it only stores it,
|
||||
* but never interacts with it in any way.
|
||||
* </p>
|
||||
*
|
||||
* @param userData
|
||||
* any object holding the domain specific user data
|
||||
* associated with the object.
|
||||
* @return builder
|
||||
*/
|
||||
public Builder setUserData(Object userData) {
|
||||
this.userData = userData;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum velocity this vehicle-type can go [in meter per
|
||||
* seconds].
|
||||
*
|
||||
* @param inMeterPerSeconds
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if velocity is smaller than zero
|
||||
* @throws IllegalArgumentException
|
||||
* if velocity is smaller than zero
|
||||
*/
|
||||
public VehicleTypeImpl.Builder setMaxVelocity(double inMeterPerSeconds) {
|
||||
if (inMeterPerSeconds < 0.0) throw new IllegalArgumentException("velocity cannot be smaller than zero");
|
||||
|
|
@ -314,12 +337,15 @@ public class VehicleTypeImpl implements VehicleType {
|
|||
|
||||
private final double maxVelocity;
|
||||
|
||||
private Object userData;
|
||||
|
||||
/**
|
||||
* priv constructor constructing vehicle-type
|
||||
*
|
||||
* @param builder
|
||||
*/
|
||||
private VehicleTypeImpl(VehicleTypeImpl.Builder builder) {
|
||||
this.userData = builder.userData;
|
||||
typeId = builder.id;
|
||||
capacity = builder.capacity;
|
||||
maxVelocity = builder.maxVelo;
|
||||
|
|
@ -328,6 +354,14 @@ public class VehicleTypeImpl implements VehicleType {
|
|||
profile = builder.profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User-specific domain data associated with the vehicle
|
||||
*/
|
||||
@Override
|
||||
public Object getUserData() {
|
||||
return userData;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see basics.route.VehicleType#getTypeId()
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ public class FastVehicleRoutingTransportCostsMatrix extends AbstractForwardVehic
|
|||
|
||||
private double[][][] matrix;
|
||||
|
||||
private final int noLocations;
|
||||
|
||||
/**
|
||||
* Creates a new builder returning the matrix-builder.
|
||||
* <p>If you want to consider symmetric matrices, set isSymmetric to true.
|
||||
|
|
@ -59,6 +61,7 @@ public class FastVehicleRoutingTransportCostsMatrix extends AbstractForwardVehic
|
|||
private Builder(int noLocations, boolean isSymmetric) {
|
||||
this.isSymmetric = isSymmetric;
|
||||
matrix = new double[noLocations][noLocations][2];
|
||||
this.noLocations = noLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -74,11 +77,11 @@ public class FastVehicleRoutingTransportCostsMatrix extends AbstractForwardVehic
|
|||
return this;
|
||||
}
|
||||
|
||||
private void add(int fromIndex, int toIndex, int indicatorIndex, double distance) {
|
||||
private void add(int fromIndex, int toIndex, int indicatorIndex, double value) {
|
||||
if (isSymmetric) {
|
||||
if (fromIndex < toIndex) matrix[fromIndex][toIndex][indicatorIndex] = distance;
|
||||
else matrix[toIndex][fromIndex][indicatorIndex] = distance;
|
||||
} else matrix[fromIndex][toIndex][indicatorIndex] = distance;
|
||||
if (fromIndex < toIndex) matrix[fromIndex][toIndex][indicatorIndex] = value;
|
||||
else matrix[toIndex][fromIndex][indicatorIndex] = value;
|
||||
} else matrix[fromIndex][toIndex][indicatorIndex] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -94,6 +97,11 @@ public class FastVehicleRoutingTransportCostsMatrix extends AbstractForwardVehic
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder addTransportTimeAndDistance(int fromIndex, int toIndex, double time, double distance){
|
||||
addTransportTime(fromIndex, toIndex, time);
|
||||
addTransportDistance(fromIndex,toIndex,distance);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Builds the matrix.
|
||||
*
|
||||
|
|
@ -110,9 +118,12 @@ public class FastVehicleRoutingTransportCostsMatrix extends AbstractForwardVehic
|
|||
|
||||
private final double[][][] matrix;
|
||||
|
||||
private int noLocations;
|
||||
|
||||
private FastVehicleRoutingTransportCostsMatrix(Builder builder) {
|
||||
this.isSymmetric = builder.isSymmetric;
|
||||
matrix = builder.matrix;
|
||||
noLocations = builder.noLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -169,4 +180,9 @@ public class FastVehicleRoutingTransportCostsMatrix extends AbstractForwardVehic
|
|||
return costParams.perDistanceUnit * getDistance(from.getIndex(), to.getIndex()) + costParams.perTransportTimeUnit * getTransportTime(from, to, departureTime, driver, vehicle);
|
||||
}
|
||||
|
||||
public int getNoLocations() {
|
||||
return noLocations;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.util;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.recreate.listener.JobUnassignedListener;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import org.apache.commons.math3.stat.Frequency;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 06/02/17.
|
||||
*/
|
||||
public class UnassignedJobReasonTracker implements JobUnassignedListener {
|
||||
|
||||
public static String getMostLikelyFailedConstraintName(Frequency failedConstraintNamesFrequency) {
|
||||
if (failedConstraintNamesFrequency == null) return "no reason found";
|
||||
Iterator<Map.Entry<Comparable<?>, Long>> entryIterator = failedConstraintNamesFrequency.entrySetIterator();
|
||||
int maxCount = 0;
|
||||
String mostLikely = null;
|
||||
while (entryIterator.hasNext()) {
|
||||
Map.Entry<Comparable<?>, Long> entry = entryIterator.next();
|
||||
if (entry.getValue() > maxCount) {
|
||||
Comparable<?> key = entry.getKey();
|
||||
mostLikely = key.toString();
|
||||
}
|
||||
}
|
||||
return mostLikely;
|
||||
}
|
||||
|
||||
Map<String, Frequency> failedConstraintNamesFrequencyMapping = new HashMap<>();
|
||||
|
||||
Map<Integer, String> codesToHumanReadableReason = new HashMap<>();
|
||||
|
||||
Map<String, Integer> failedConstraintNamesToCode = new HashMap<>();
|
||||
|
||||
Set<String> failedConstraintNamesToBeIgnored = new HashSet<>();
|
||||
|
||||
public UnassignedJobReasonTracker() {
|
||||
codesToHumanReadableReason.put(1, "cannot serve required skill");
|
||||
codesToHumanReadableReason.put(2, "cannot be visited within time window");
|
||||
codesToHumanReadableReason.put(3, "does not fit into any vehicle due to capacity");
|
||||
codesToHumanReadableReason.put(4, "cannot be assigned due to max distance constraint of vehicle");
|
||||
|
||||
failedConstraintNamesToCode.put("HardSkillConstraint", 1);
|
||||
failedConstraintNamesToCode.put("VehicleDependentTimeWindowConstraints", 2);
|
||||
failedConstraintNamesToCode.put("ServiceLoadRouteLevelConstraint", 3);
|
||||
failedConstraintNamesToCode.put("PickupAndDeliverShipmentLoadActivityLevelConstraint", 3);
|
||||
failedConstraintNamesToCode.put("ServiceLoadActivityLevelConstraint", 3);
|
||||
failedConstraintNamesToCode.put("MaxDistanceConstraint", 4);
|
||||
}
|
||||
|
||||
public void ignore(String simpleNameOfConstraint) {
|
||||
failedConstraintNamesToBeIgnored.add(simpleNameOfConstraint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informJobUnassigned(Job unassigned, Collection<String> failedConstraintNames) {
|
||||
if (!this.failedConstraintNamesFrequencyMapping.containsKey(unassigned.getId())) {
|
||||
this.failedConstraintNamesFrequencyMapping.put(unassigned.getId(), new Frequency());
|
||||
}
|
||||
for (String r : failedConstraintNames) {
|
||||
if (failedConstraintNamesToBeIgnored.contains(r)) continue;
|
||||
this.failedConstraintNamesFrequencyMapping.get(unassigned.getId()).addValue(r);
|
||||
}
|
||||
}
|
||||
|
||||
public void put(String simpleNameOfFailedConstraint, int code, String reason) {
|
||||
if (code <= 20)
|
||||
throw new IllegalArgumentException("first 20 codes are reserved internally. choose a code > 20");
|
||||
codesToHumanReadableReason.put(code, reason);
|
||||
if (failedConstraintNamesToCode.containsKey(simpleNameOfFailedConstraint)) {
|
||||
throw new IllegalArgumentException(simpleNameOfFailedConstraint + " already assigned to code and reason");
|
||||
} else failedConstraintNamesToCode.put(simpleNameOfFailedConstraint, code);
|
||||
}
|
||||
|
||||
/**
|
||||
* For each job id, it returns frequency distribution of failed constraints (simple name of constraint) in an unmodifiable map.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public Map<String, Frequency> getReasons() {
|
||||
return Collections.unmodifiableMap(failedConstraintNamesFrequencyMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* For each job id, it returns frequency distribution of failed constraints (simple name of constraint) in an unmodifiable map.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Frequency> getFailedConstraintNamesFrequencyMapping() {
|
||||
return Collections.unmodifiableMap(failedConstraintNamesFrequencyMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable map of codes and reason pairs.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Map<Integer, String> getCodesToReason() {
|
||||
return Collections.unmodifiableMap(codesToHumanReadableReason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable map of constraint names (simple name of constraint) and reason code pairs.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Integer> getFailedConstraintNamesToCode() {
|
||||
return Collections.unmodifiableMap(failedConstraintNamesToCode);
|
||||
}
|
||||
|
||||
public int getCode(String failedConstraintName) {
|
||||
return toCode(failedConstraintName);
|
||||
}
|
||||
|
||||
public String getHumanReadableReason(int code) {
|
||||
return getCodesToReason().get(code);
|
||||
}
|
||||
|
||||
public String getHumanReadableReason(String failedConstraintName) {
|
||||
return getCodesToReason().get(getCode(failedConstraintName));
|
||||
}
|
||||
/**
|
||||
* Returns the most likely reason code i.e. the reason (failed constraint) being observed most often.
|
||||
*
|
||||
* 1 --> "cannot serve required skill
|
||||
* 2 --> "cannot be visited within time window"
|
||||
* 3 --> "does not fit into any vehicle due to capacity"
|
||||
* 4 --> "cannot be assigned due to max distance constraint of vehicle"
|
||||
*
|
||||
* @param jobId
|
||||
* @return
|
||||
*/
|
||||
public int getMostLikelyReasonCode(String jobId) {
|
||||
if (!this.failedConstraintNamesFrequencyMapping.containsKey(jobId)) return -1;
|
||||
Frequency reasons = this.failedConstraintNamesFrequencyMapping.get(jobId);
|
||||
String mostLikelyReason = getMostLikelyFailedConstraintName(reasons);
|
||||
return toCode(mostLikelyReason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the most likely reason i.e. the reason (failed constraint) being observed most often.
|
||||
*
|
||||
* @param jobId
|
||||
* @return
|
||||
*/
|
||||
public String getMostLikelyReason(String jobId) {
|
||||
if (!this.failedConstraintNamesFrequencyMapping.containsKey(jobId)) return "no reason found";
|
||||
Frequency reasons = this.failedConstraintNamesFrequencyMapping.get(jobId);
|
||||
String mostLikelyReason = getMostLikelyFailedConstraintName(reasons);
|
||||
int code = toCode(mostLikelyReason);
|
||||
if (code == -1) return mostLikelyReason;
|
||||
else return codesToHumanReadableReason.get(code);
|
||||
}
|
||||
|
||||
private int toCode(String mostLikelyReason) {
|
||||
if (failedConstraintNamesToCode.containsKey(mostLikelyReason))
|
||||
return failedConstraintNamesToCode.get(mostLikelyReason);
|
||||
else return -1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -31,7 +31,6 @@ import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolutio
|
|||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||
import com.graphhopper.jsprit.core.reporting.SolutionPrinter;
|
||||
import com.graphhopper.jsprit.core.util.Solutions;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
|
|
@ -43,10 +42,10 @@ public class MaxTimeInVehicle_IT {
|
|||
public void test(){
|
||||
|
||||
Shipment s1 = Shipment.Builder.newInstance("s1").setPickupLocation(Location.newInstance(0,0)).setDeliveryLocation(Location.newInstance(100,0)).setDeliveryServiceTime(10)
|
||||
.setMaxTimeInVehicle(90d)
|
||||
.setMaxTimeInVehicle(100d)
|
||||
.build();
|
||||
Shipment s2 = Shipment.Builder.newInstance("s2").setPickupLocation(Location.newInstance(0,0)).setDeliveryLocation(Location.newInstance(100,0)).setDeliveryServiceTime(10)
|
||||
.setMaxTimeInVehicle(90d)
|
||||
.setMaxTimeInVehicle(100d)
|
||||
.build();
|
||||
|
||||
VehicleImpl v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0)).build();
|
||||
|
|
@ -58,12 +57,12 @@ public class MaxTimeInVehicle_IT {
|
|||
stateManager.addStateUpdater(new UpdateMaxTimeInVehicle(stateManager,id,vrp.getTransportCosts(),vrp.getActivityCosts()));
|
||||
|
||||
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
|
||||
constraintManager.addConstraint(new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts(),id,stateManager), ConstraintManager.Priority.CRITICAL);
|
||||
constraintManager.addConstraint(new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts(),id,stateManager, vrp), ConstraintManager.Priority.CRITICAL);
|
||||
|
||||
VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp).setStateAndConstraintManager(stateManager,constraintManager).buildAlgorithm();
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
|
||||
|
||||
Assert.assertEquals(400, solution.getCost(), 0.001);
|
||||
// SolutionPrinter.print(vrp,solution, SolutionPrinter.Print.VERBOSE);
|
||||
// Assert.assertEquals(400, solution.getCost(), 0.001);
|
||||
SolutionPrinter.print(vrp,solution, SolutionPrinter.Print.VERBOSE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,14 +26,17 @@ import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolutio
|
|||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||
import com.graphhopper.jsprit.core.util.Solutions;
|
||||
import com.graphhopper.jsprit.core.util.UnassignedJobReasonTracker;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class UnassignedJobListTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void job2ShouldBeInBadJobList_dueToTimeWindow() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
|
@ -46,11 +49,17 @@ public class UnassignedJobListTest {
|
|||
VehicleRoutingProblem vrp = builder.build();
|
||||
VehicleRoutingAlgorithm algorithm = new GreedySchrimpfFactory().createAlgorithm(vrp);
|
||||
algorithm.setMaxIterations(10);
|
||||
|
||||
UnassignedJobReasonTracker reasonTracker = new UnassignedJobReasonTracker();
|
||||
algorithm.addListener(reasonTracker);
|
||||
|
||||
Collection<VehicleRoutingProblemSolution> solutions = algorithm.searchSolutions();
|
||||
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions);
|
||||
|
||||
assertTrue(!solution.getUnassignedJobs().contains(job1));
|
||||
assertTrue(solution.getUnassignedJobs().contains(job2));
|
||||
assertEquals(2, reasonTracker.getMostLikelyReasonCode("job2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -63,13 +72,19 @@ public class UnassignedJobListTest {
|
|||
builder.addJob(job2);
|
||||
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
|
||||
VehicleRoutingAlgorithm algorithm = new GreedySchrimpfFactory().createAlgorithm(vrp);
|
||||
algorithm.setMaxIterations(10);
|
||||
|
||||
UnassignedJobReasonTracker reasonTracker = new UnassignedJobReasonTracker();
|
||||
algorithm.addListener(reasonTracker);
|
||||
|
||||
Collection<VehicleRoutingProblemSolution> solutions = algorithm.searchSolutions();
|
||||
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions);
|
||||
assertTrue(!solution.getUnassignedJobs().contains(job1));
|
||||
assertTrue(solution.getUnassignedJobs().contains(job2));
|
||||
assertEquals(3, reasonTracker.getMostLikelyReasonCode("job2"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
|
||||
import com.graphhopper.jsprit.core.problem.AbstractJob;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 15/08/16.
|
||||
*/
|
||||
public class ConfigureFixCostCalculatorTest {
|
||||
|
||||
VehicleRoutingProblem vrp;
|
||||
|
||||
@Before
|
||||
public void before(){
|
||||
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
for(int i=0;i<100;i++){
|
||||
Service service = Service.Builder.newInstance("" + i).setLocation(Location.newInstance(0)).build();
|
||||
vrpBuilder.addJob(service);
|
||||
}
|
||||
vrp = vrpBuilder.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCalculateCorrectly(){
|
||||
List<Job> unassigned = new ArrayList<>();
|
||||
int count = 1;
|
||||
for(String key : vrp.getJobs().keySet()) {
|
||||
if(count <= 25) {
|
||||
unassigned.add(vrp.getJobs().get(key));
|
||||
}
|
||||
count++;
|
||||
}
|
||||
JobInsertionConsideringFixCostsCalculator jicc = new JobInsertionConsideringFixCostsCalculator(mock(JobInsertionCostsCalculator.class),mock(StateManager.class));
|
||||
ConfigureFixCostCalculator c = new ConfigureFixCostCalculator(vrp,jicc);
|
||||
c.informInsertionStarts(new ArrayList<VehicleRoute>(), unassigned);
|
||||
Assert.assertEquals(0.75, jicc.getSolutionCompletenessRatio(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeMinRatio(){
|
||||
List<Job> unassigned = new ArrayList<>();
|
||||
int count = 1;
|
||||
for(String key : vrp.getJobs().keySet()) {
|
||||
if(count <= 75) {
|
||||
unassigned.add(vrp.getJobs().get(key));
|
||||
}
|
||||
count++;
|
||||
}
|
||||
JobInsertionConsideringFixCostsCalculator jicc = new JobInsertionConsideringFixCostsCalculator(mock(JobInsertionCostsCalculator.class),mock(StateManager.class));
|
||||
ConfigureFixCostCalculator c = new ConfigureFixCostCalculator(vrp,jicc);
|
||||
c.informInsertionStarts(new ArrayList<VehicleRoute>(), unassigned);
|
||||
Assert.assertEquals(0.5, jicc.getSolutionCompletenessRatio(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeOne(){
|
||||
List<Job> unassigned = new ArrayList<>();
|
||||
JobInsertionConsideringFixCostsCalculator jicc = new JobInsertionConsideringFixCostsCalculator(mock(JobInsertionCostsCalculator.class),mock(StateManager.class));
|
||||
ConfigureFixCostCalculator c = new ConfigureFixCostCalculator(vrp,jicc);
|
||||
c.informInsertionStarts(new ArrayList<VehicleRoute>(), unassigned);
|
||||
Assert.assertEquals(1.0, jicc.getSolutionCompletenessRatio(), 0.001);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ package com.graphhopper.jsprit.core.algorithm.recreate;
|
|||
import com.graphhopper.jsprit.core.algorithm.state.InternalStates;
|
||||
import com.graphhopper.jsprit.core.problem.Capacity;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
|
|
@ -34,11 +35,15 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
public class JobInsertionConsideringFixCostsCalculatorTest {
|
||||
|
||||
private JobInsertionConsideringFixCostsCalculator calc;
|
||||
private IncreasingAbsoluteFixedCosts absFixedCosts;
|
||||
|
||||
private Vehicle oVehicle;
|
||||
private DecreasingRelativeFixedCosts relFixedCosts;
|
||||
|
||||
private Vehicle nVehicle;
|
||||
private Vehicle small;
|
||||
|
||||
private Vehicle medium;
|
||||
|
||||
private Vehicle large;
|
||||
|
||||
private Job job;
|
||||
|
||||
|
|
@ -52,194 +57,333 @@ public class JobInsertionConsideringFixCostsCalculatorTest {
|
|||
job = mock(Job.class);
|
||||
when(job.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 50).build());
|
||||
|
||||
oVehicle = mock(Vehicle.class);
|
||||
VehicleType oType = VehicleTypeImpl.Builder.newInstance("otype").addCapacityDimension(0, 50).setFixedCost(50.0).build();
|
||||
when(oVehicle.getType()).thenReturn(oType);
|
||||
small = mock(Vehicle.class);
|
||||
VehicleType smallType = VehicleTypeImpl.Builder.newInstance("smallType").addCapacityDimension(0, 50).setFixedCost(50.0).build();
|
||||
when(small.getType()).thenReturn(smallType);
|
||||
|
||||
nVehicle = mock(Vehicle.class);
|
||||
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 100).setFixedCost(100.0).build();
|
||||
when(nVehicle.getType()).thenReturn(type);
|
||||
medium = mock(Vehicle.class);
|
||||
VehicleType mediumType = VehicleTypeImpl.Builder.newInstance("mediumType").addCapacityDimension(0, 100).setFixedCost(100.0).build();
|
||||
when(medium.getType()).thenReturn(mediumType);
|
||||
|
||||
InsertionData iData = new InsertionData(0.0, 1, 1, nVehicle, null);
|
||||
large = mock(Vehicle.class);
|
||||
VehicleType largeType = VehicleTypeImpl.Builder.newInstance("largeType").addCapacityDimension(0, 400).setFixedCost(200.0).build();
|
||||
when(large.getType()).thenReturn(largeType);
|
||||
|
||||
InsertionData iData = new InsertionData(0.0, 1, 1, medium, null);
|
||||
route = mock(VehicleRoute.class);
|
||||
|
||||
when(jobInsertionCosts.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE)).thenReturn(iData);
|
||||
when(jobInsertionCosts.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE)).thenReturn(iData);
|
||||
when(jobInsertionCosts.getInsertionData(route, job, large, 0.0, null, Double.MAX_VALUE)).thenReturn(new InsertionData(0.0, 1, 1, large, null));
|
||||
|
||||
stateGetter = mock(RouteAndActivityStateGetter.class);
|
||||
when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().build());
|
||||
|
||||
calc = new JobInsertionConsideringFixCostsCalculator(jobInsertionCosts, stateGetter);
|
||||
absFixedCosts = new IncreasingAbsoluteFixedCosts(10);
|
||||
relFixedCosts = new DecreasingRelativeFixedCosts(stateGetter, 10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNullAndSolutionComplete_itShouldReturnFixedCostsOfNewVehicle() {
|
||||
calc.setSolutionCompletenessRatio(1.0);
|
||||
calc.setWeightOfFixCost(1.0);
|
||||
absFixedCosts.setSolutionCompletenessRatio(1.0);
|
||||
absFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(1.0);
|
||||
relFixedCosts.setWeightOfFixCost(1.0);
|
||||
//(1.*absFix + 0.*relFix) * completeness * weight = (1.*100. + 0.*50.) * 1. * 1. = 100.
|
||||
assertEquals(100., calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
assertEquals(100., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNullAndSolutionIs0PercentComplete_itShouldReturnNoFixedCosts() {
|
||||
calc.setSolutionCompletenessRatio(0.0);
|
||||
calc.setWeightOfFixCost(1.0);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.0);
|
||||
absFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.0);
|
||||
relFixedCosts.setWeightOfFixCost(1.0);
|
||||
//(0.*absFix + 1.*relFix) * completeness * weight = 0.
|
||||
assertEquals(0., calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
|
||||
assertEquals(0., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNullAndSolutionIs50PercentComplete_itShouldReturnAvgOfRelFixedAndAbsFixedCostOfNewVehicle() {
|
||||
calc.setSolutionCompletenessRatio(0.5);
|
||||
calc.setWeightOfFixCost(1.0);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.5);
|
||||
absFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.5);
|
||||
relFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.5*absFix + 0.5*relFix) * 0.5 * 1. = (0.5*100+0.5*50)*0.5*1. = 37.5
|
||||
assertEquals(37.5, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(37.5, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNullAndSolutionIs75PercentComplete_itShouldReturnAvgOfRelFixedAndAbsFixedCostOfNewVehicle() {
|
||||
calc.setSolutionCompletenessRatio(0.75);
|
||||
calc.setWeightOfFixCost(1.0);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
absFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
relFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
|
||||
//(0.75*absFix + 0.25*relFix) * 0.75 * 1.= (0.75*100.+0.25*50.)*0.75*1. = 65.625
|
||||
assertEquals(65.625, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(65.625, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNullAndSolutionCompleteAndWeightIs05_itShouldReturnHalfOfFixedCostsOfNewVehicle() {
|
||||
calc.setSolutionCompletenessRatio(1.0);
|
||||
calc.setWeightOfFixCost(.5);
|
||||
absFixedCosts.setSolutionCompletenessRatio(1.0);
|
||||
absFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(1.0);
|
||||
relFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(1.*absFix + 0.*relFix) * 1. * 0.5 = (1.*100. + 0.*50.) * 1. * 0.5 = 5.
|
||||
assertEquals(50., calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(50., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNullAndSolutionIs0PercentCompleteAndWeightIs05_itShouldReturnHalfOfNoFixedCosts() {
|
||||
calc.setSolutionCompletenessRatio(0.0);
|
||||
calc.setWeightOfFixCost(.5);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.0);
|
||||
absFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.0);
|
||||
relFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.*absFix + 1.*relFix) * 0. * .5 = 0.
|
||||
assertEquals(0., calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(0., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNullAndSolutionIs50PercentCompleteAndWeightIs05_itShouldReturnHalfOfAvgOfRelFixedAndAbsFixedCostOfNewVehicle() {
|
||||
calc.setSolutionCompletenessRatio(0.5);
|
||||
calc.setWeightOfFixCost(.5);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.5);
|
||||
absFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.5);
|
||||
relFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
|
||||
//(0.5*absFix + 0.5*relFix) * 0.5 * 0.= (0.5*100+0.5*50)*0.5*0.5 = 18.75
|
||||
assertEquals(18.75, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(18.75, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNullAndSolutionIs75PercentCompleteAndWeightIs05_itShouldReturnHalfOfAvgOfRelFixedAndAbsFixedCostOfNewVehicle() {
|
||||
calc.setSolutionCompletenessRatio(0.75);
|
||||
calc.setWeightOfFixCost(0.5);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
absFixedCosts.setWeightOfFixCost(0.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
relFixedCosts.setWeightOfFixCost(0.5);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
|
||||
//(0.75*absFix + 0.25*relFix) * 0.75 * 0.5 = (0.75*100.+0.25*50.)*0.75*0.5 = 32.8125
|
||||
assertEquals(32.8125, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(32.8125, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndSolutionComplete_itShouldReturnHalfOfFixedCostsOfNewVehicle() {
|
||||
calc.setSolutionCompletenessRatio(1.0);
|
||||
calc.setWeightOfFixCost(1.0);
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
absFixedCosts.setSolutionCompletenessRatio(1.0);
|
||||
absFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(1.0);
|
||||
relFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
|
||||
//(1.*absFix + 0.*relFix) * completeness * weight = (1.*(100.-50.) + 0.*(50.-0.)) * 1. * 1. = 50.
|
||||
assertEquals(50., calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(50., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndSolutionIs0PercentComplete_itShouldReturnNoFixedCosts() {
|
||||
calc.setSolutionCompletenessRatio(0.0);
|
||||
calc.setWeightOfFixCost(1.0);
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.0);
|
||||
absFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.0);
|
||||
relFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.*absFix + 1.*relFix) * completeness * weight = 0.
|
||||
assertEquals(0., calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(0., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndSolutionIs50PercentComplete_itShouldCorrectVal() {
|
||||
calc.setSolutionCompletenessRatio(0.5);
|
||||
calc.setWeightOfFixCost(1.0);
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.5);
|
||||
absFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.5);
|
||||
relFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.5*absFix + 0.5*relFix) * 0.5 * 1. = (0.5*(100-50)+0.5*(50-0))*0.5*1. = 25.
|
||||
assertEquals(25., calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(25., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndSolutionIs75PercentComplete_itShouldReturnCorrectVal() {
|
||||
calc.setSolutionCompletenessRatio(0.75);
|
||||
calc.setWeightOfFixCost(1.0);
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
absFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
relFixedCosts.setWeightOfFixCost(1.0);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.75*absFix + 0.25*relFix) * 0.75 * 1.= (0.75*(100.-50.)+0.25*(50.-0.))*0.75*1. = 37.5
|
||||
assertEquals(37.5, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(37.5, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndSolutionCompleteAndWeightIs05_itShouldReturnCorrectVal() {
|
||||
calc.setSolutionCompletenessRatio(1.0);
|
||||
calc.setWeightOfFixCost(.5);
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
absFixedCosts.setSolutionCompletenessRatio(1.0);
|
||||
absFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(1.0);
|
||||
relFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(1.*absFix + 0.*relFix) * 1. * 0.5 = (1.*(100.-50.) + 0.*(50.-0.)) * 1. * 0.5 = 25.
|
||||
assertEquals(25., calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(25., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndSolutionIs0PercentCompleteAndWeightIs05_itShouldReturnCorrectVal() {
|
||||
calc.setSolutionCompletenessRatio(0.0);
|
||||
calc.setWeightOfFixCost(.5);
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.0);
|
||||
absFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.0);
|
||||
relFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.*absFix + 1.*relFix) * 0. * .5 = 0.
|
||||
assertEquals(0., calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(0., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndSolutionIs50PercentCompleteAndWeightIs05_itShouldReturnCorrectVal() {
|
||||
calc.setSolutionCompletenessRatio(0.5);
|
||||
calc.setWeightOfFixCost(.5);
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.5);
|
||||
absFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.5);
|
||||
relFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.5*absFix + 0.5*relFix) * 0.5 * 0.= (0.5*(100-50)+0.5*(50-0))*0.5*0.5 = 12.5
|
||||
assertEquals(12.5, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(12.5, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndSolutionIs75PercentCompleteAndWeightIs05_itShouldReturnCorrectVal() {
|
||||
calc.setSolutionCompletenessRatio(0.75);
|
||||
calc.setWeightOfFixCost(0.5);
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
absFixedCosts.setWeightOfFixCost(0.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
relFixedCosts.setWeightOfFixCost(0.5);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.75*absFix + 0.25*relFix) * 0.75 * 0.5 = (0.75*(100.-50.)+0.25*(50.-0.))*0.75*0.5 = 18.75
|
||||
assertEquals(18.75, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(18.75, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndCurrentLoadIs25AndSolutionIs50PercentCompleteAndWeightIs05_itShouldReturnCorrectVal() {
|
||||
calc.setSolutionCompletenessRatio(0.5);
|
||||
calc.setWeightOfFixCost(.5);
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.5);
|
||||
absFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.5);
|
||||
relFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().addDimension(0, 25).build());
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.5*absFix + 0.5*relFix) * 0.5 * 0.= (0.5*(100-50)+0.5*(75-25))*0.5*0.5 = 12.5
|
||||
assertEquals(12.5, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(12.5, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndCurrentLoadIs25AndSolutionIs75PercentCompleteAndWeightIs05_itShouldReturnCorrectVal() {
|
||||
calc.setSolutionCompletenessRatio(0.75);
|
||||
calc.setWeightOfFixCost(0.5);
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
absFixedCosts.setWeightOfFixCost(0.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
relFixedCosts.setWeightOfFixCost(0.5);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.75*absFix + 0.25*relFix) * 0.75 * 0.5 = (0.75*(100.-50.)+0.25*(75.-25.))*0.75*0.5 = 18.75
|
||||
assertEquals(18.75, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(18.75, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndCurrentLoadIs25AndSolutionIs50PercentCompleteAndWeightIs05WithMultipleCapDims_itShouldReturnCorrectVal() {
|
||||
calc.setSolutionCompletenessRatio(.5);
|
||||
calc.setWeightOfFixCost(.5);
|
||||
absFixedCosts.setSolutionCompletenessRatio(.5);
|
||||
absFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(.5);
|
||||
relFixedCosts.setWeightOfFixCost(.5);
|
||||
|
||||
when(job.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 50).addDimension(1, 0).build());
|
||||
|
||||
VehicleType oType = VehicleTypeImpl.Builder.newInstance("otype").addCapacityDimension(0, 50).addCapacityDimension(1, 100).setFixedCost(50.0).build();
|
||||
when(oVehicle.getType()).thenReturn(oType);
|
||||
when(small.getType()).thenReturn(oType);
|
||||
|
||||
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 100).addCapacityDimension(1, 400).setFixedCost(100.0).build();
|
||||
when(nVehicle.getType()).thenReturn(type);
|
||||
when(medium.getType()).thenReturn(type);
|
||||
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().addDimension(0, 25).addDimension(1, 100).build());
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.5*absFix + 0.5*relFix) * 0.5 * 0.= (0.5*(100-50)+0.5*(75-25))*0.5*0.5 = 12.5
|
||||
/*
|
||||
* (0.5*(100-50)+0.5*(
|
||||
* relFixNew - relFixOld = (75/100+100/400)/2.*100 - ((25/50+100/100)/2.*50.) =
|
||||
* )*0.5*0.5
|
||||
* = (0.5*(100-50)+0.5*((75/100+100/400)/2.*100 - ((25/50+100/100)/2.*50.)))*0.5*0.5
|
||||
* = (0.5*(100-50)+0.5*12.5)*0.5*0.5 = 7.8125
|
||||
*/
|
||||
assertEquals(7.8125, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsMoreExpensive() {
|
||||
absFixedCosts.setSolutionCompletenessRatio(1);
|
||||
absFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(1);
|
||||
relFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
when(job.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 50).addDimension(1, 0).build());
|
||||
|
||||
VehicleType oType = VehicleTypeImpl.Builder.newInstance("otype").addCapacityDimension(0, 50).addCapacityDimension(1, 100).setFixedCost(50.0).build();
|
||||
when(medium.getType()).thenReturn(oType);
|
||||
|
||||
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 100).addCapacityDimension(1, 400).setFixedCost(100.0).build();
|
||||
when(small.getType()).thenReturn(type);
|
||||
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().addDimension(0, 25).addDimension(1, 100).build());
|
||||
//(0.5*absFix + 0.5*relFix) * 0.5 * 0.= (0.5*(100-50)+0.5*(75-25))*0.5*0.5 = 12.5
|
||||
/*
|
||||
|
|
@ -249,26 +393,125 @@ public class JobInsertionConsideringFixCostsCalculatorTest {
|
|||
* = (0.5*(100-50)+0.5*((75/100+100/400)/2.*100 - ((25/50+100/100)/2.*50.)))*0.5*0.5
|
||||
* = (0.5*(100-50)+0.5*12.5)*0.5*0.5 = 7.8125
|
||||
*/
|
||||
assertEquals(7.8125, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
|
||||
double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context);
|
||||
assertEquals(-50d, insertionCost, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void smallVSMediumAbsCosts() {
|
||||
absFixedCosts.setSolutionCompletenessRatio(1);
|
||||
absFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(1);
|
||||
relFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context);
|
||||
assertEquals(50d, insertionCost, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void smallVSLargeAbsCosts() {
|
||||
absFixedCosts.setSolutionCompletenessRatio(1);
|
||||
absFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(1);
|
||||
relFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, large, null, 0d);
|
||||
double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context);
|
||||
assertEquals(150d, insertionCost, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void largeVSMediumAbsCosts() {
|
||||
absFixedCosts.setSolutionCompletenessRatio(1);
|
||||
absFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(1);
|
||||
relFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
when(route.getVehicle()).thenReturn(large);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context);
|
||||
assertEquals(-100d, insertionCost, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mediumVSLargeAbsCosts() {
|
||||
absFixedCosts.setSolutionCompletenessRatio(1);
|
||||
absFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(1);
|
||||
relFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
when(route.getVehicle()).thenReturn(medium);
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, large, null, 0d);
|
||||
|
||||
double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context);
|
||||
assertEquals(100d, insertionCost, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsMoreExpensive2() {
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.1);
|
||||
absFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.1);
|
||||
relFixedCosts.setWeightOfFixCost(1);
|
||||
|
||||
when(job.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 50).addDimension(1, 0).build());
|
||||
|
||||
VehicleType oType = VehicleTypeImpl.Builder.newInstance("otype").addCapacityDimension(0, 50).addCapacityDimension(1, 100).setFixedCost(50.0).build();
|
||||
when(medium.getType()).thenReturn(oType);
|
||||
|
||||
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 100).addCapacityDimension(1, 400).setFixedCost(100.0).build();
|
||||
when(small.getType()).thenReturn(type);
|
||||
|
||||
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().addDimension(0, 25).addDimension(1, 100).build());
|
||||
/*
|
||||
job = 50
|
||||
abs = (50 - 100) * 0.1 * 0.1 * 1.0 = -0.5
|
||||
rel = ( (75/50+100/100)/2 * 50 - (25/100 + 100/400)/2 * 100) * 0.9 * 0.1 = 3.375
|
||||
c = -0.5 + 3.375 = 2.875
|
||||
|
||||
*/
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
|
||||
double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context);
|
||||
assertEquals(2.875, insertionCost, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOldVehicleIsNotNullAndCurrentLoadIs25AndSolutionIs75PercentCompleteAndWeightIs05WithMultipleCapDims_itShouldReturnCorrectVal() {
|
||||
calc.setSolutionCompletenessRatio(0.75);
|
||||
calc.setWeightOfFixCost(0.5);
|
||||
absFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
absFixedCosts.setWeightOfFixCost(0.5);
|
||||
|
||||
relFixedCosts.setSolutionCompletenessRatio(0.75);
|
||||
relFixedCosts.setWeightOfFixCost(0.5);
|
||||
|
||||
when(job.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 50).addDimension(1, 0).build());
|
||||
|
||||
VehicleType oType = VehicleTypeImpl.Builder.newInstance("otype").addCapacityDimension(0, 50).addCapacityDimension(1, 100).setFixedCost(50.0).build();
|
||||
when(oVehicle.getType()).thenReturn(oType);
|
||||
when(small.getType()).thenReturn(oType);
|
||||
|
||||
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 100).addCapacityDimension(1, 400).setFixedCost(100.0).build();
|
||||
when(nVehicle.getType()).thenReturn(type);
|
||||
when(medium.getType()).thenReturn(type);
|
||||
|
||||
when(route.getVehicle()).thenReturn(oVehicle);
|
||||
when(route.getVehicle()).thenReturn(small);
|
||||
when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().addDimension(0, 25).addDimension(1, 100).build());
|
||||
|
||||
JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d);
|
||||
//(0.75*absFix + 0.25*relFix) * 0.75 * 0.5 = (0.75*(100.-50.)+0.25*12.5)*0.75*0.5 = 15.234375
|
||||
|
||||
assertEquals(15.234375, calc.getInsertionData(route, job, nVehicle, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01);
|
||||
assertEquals(15.234375, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ public class ShipmentInsertionCalculatorTest {
|
|||
insertionCalculator.setJobActivityFactory(activityFactory);
|
||||
|
||||
InsertionData iData = insertionCalculator.getInsertionData(route, shipment2, vehicle, 0.0, null, Double.MAX_VALUE);
|
||||
assertEquals(InsertionData.createEmptyInsertionData(), iData);
|
||||
assertTrue(iData instanceof InsertionData.NoInsertionFound);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
|||
import com.graphhopper.jsprit.core.problem.cost.WaitingTimeCosts;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
import com.graphhopper.jsprit.core.problem.job.Shipment;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.End;
|
||||
|
|
@ -91,6 +92,74 @@ public class TestLocalActivityInsertionCostsCalculator {
|
|||
return Location.Builder.newInstance().setId(i).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAddingServiceBetweenDiffStartAndEnd_costMustBeCorrect() {
|
||||
VehicleImpl v = VehicleImpl.Builder.newInstance("v")
|
||||
.setStartLocation(Location.newInstance(0, 0))
|
||||
.setEndLocation(Location.newInstance(20, 0))
|
||||
.build();
|
||||
Service s = Service.Builder.newInstance("s")
|
||||
.setLocation(Location.newInstance(10, 0))
|
||||
.build();
|
||||
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
|
||||
.addVehicle(v)
|
||||
.addJob(s)
|
||||
.build();
|
||||
VehicleRoute route = VehicleRoute.emptyRoute();
|
||||
JobInsertionContext jobInsertionContext =
|
||||
new JobInsertionContext(route, s, v, null, 0);
|
||||
LocalActivityInsertionCostsCalculator localActivityInsertionCostsCalculator =
|
||||
new LocalActivityInsertionCostsCalculator(
|
||||
vrp.getTransportCosts(),
|
||||
vrp.getActivityCosts(),
|
||||
new StateManager(vrp));
|
||||
double cost = localActivityInsertionCostsCalculator.getCosts(
|
||||
jobInsertionContext,
|
||||
new Start(v.getStartLocation(),0,Double.MAX_VALUE),
|
||||
new End(v.getEndLocation(),0,Double.MAX_VALUE),
|
||||
vrp.getActivities(s).get(0),
|
||||
0);
|
||||
assertEquals(20., cost, Math.ulp(20.));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAddingShipmentBetweenDiffStartAndEnd_costMustBeCorrect() {
|
||||
VehicleImpl v = VehicleImpl.Builder.newInstance("v")
|
||||
.setStartLocation(Location.newInstance(0, 0))
|
||||
.setEndLocation(Location.newInstance(20, 0))
|
||||
.build();
|
||||
Shipment s = Shipment.Builder.newInstance("p")
|
||||
.setPickupLocation(Location.newInstance(10, 0))
|
||||
.setDeliveryLocation(Location.newInstance(10, 7.5))
|
||||
.build();
|
||||
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
|
||||
.addVehicle(v)
|
||||
.addJob(s)
|
||||
.build();
|
||||
VehicleRoute route = VehicleRoute.emptyRoute();
|
||||
JobInsertionContext jobInsertionContext =
|
||||
new JobInsertionContext(route, s, v, null, 0);
|
||||
LocalActivityInsertionCostsCalculator localActivityInsertionCostsCalculator =
|
||||
new LocalActivityInsertionCostsCalculator(
|
||||
vrp.getTransportCosts(),
|
||||
vrp.getActivityCosts(),
|
||||
new StateManager(vrp));
|
||||
double cost = localActivityInsertionCostsCalculator.getCosts(
|
||||
jobInsertionContext,
|
||||
new Start(v.getStartLocation(),0,Double.MAX_VALUE),
|
||||
new End(v.getEndLocation(),0,Double.MAX_VALUE),
|
||||
vrp.getActivities(s).get(0),
|
||||
0);
|
||||
assertEquals(20., cost, Math.ulp(20.));
|
||||
cost = localActivityInsertionCostsCalculator.getCosts(
|
||||
jobInsertionContext,
|
||||
vrp.getActivities(s).get(0),
|
||||
new End(v.getEndLocation(),0,Double.MAX_VALUE),
|
||||
vrp.getActivities(s).get(1),
|
||||
0);
|
||||
assertEquals(10, cost, Math.ulp(10.));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInsertingActBetweenTwoRouteActs_itCalcsMarginalTpCosts() {
|
||||
TourActivity prevAct = mock(TourActivity.class);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.algorithm.ruin;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 13/01/17.
|
||||
*/
|
||||
public class StringUtilTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
int stringLength = 4;
|
||||
int seedIndex = 4;
|
||||
int noActivities = 10;
|
||||
List<Integer> bounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities);
|
||||
Assert.assertEquals(4, bounds.size());
|
||||
Assert.assertEquals(1, (int) bounds.get(0));
|
||||
Assert.assertEquals(2, (int) bounds.get(1));
|
||||
Assert.assertEquals(3, (int) bounds.get(2));
|
||||
Assert.assertEquals(4, (int) bounds.get(3));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
int stringLength = 4;
|
||||
int seedIndex = 2;
|
||||
int noActivities = 10;
|
||||
List<Integer> bounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities);
|
||||
Assert.assertEquals(3, bounds.size());
|
||||
Assert.assertEquals(0, (int) bounds.get(0));
|
||||
Assert.assertEquals(1, (int) bounds.get(1));
|
||||
Assert.assertEquals(2, (int) bounds.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test3() {
|
||||
int stringLength = 4;
|
||||
int seedIndex = 0;
|
||||
int noActivities = 10;
|
||||
List<Integer> bounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities);
|
||||
Assert.assertEquals(1, bounds.size());
|
||||
Assert.assertEquals(0, (int) bounds.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test4() {
|
||||
int stringLength = 4;
|
||||
int seedIndex = 9;
|
||||
int noActivities = 10;
|
||||
List<Integer> bounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities);
|
||||
Assert.assertEquals(1, bounds.size());
|
||||
Assert.assertEquals(6, (int) bounds.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test5() {
|
||||
int stringLength = 4;
|
||||
int seedIndex = 8;
|
||||
int noActivities = 10;
|
||||
List<Integer> bounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities);
|
||||
Assert.assertEquals(2, bounds.size());
|
||||
Assert.assertEquals(5, (int) bounds.get(0));
|
||||
Assert.assertEquals(6, (int) bounds.get(1));
|
||||
}
|
||||
}
|
||||
|
|
@ -18,10 +18,18 @@
|
|||
|
||||
package com.graphhopper.jsprit.core.problem;
|
||||
|
||||
import com.graphhopper.jsprit.core.util.Coordinate;
|
||||
import junit.framework.Assert;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.graphhopper.jsprit.core.util.Coordinate;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 16.12.14.
|
||||
*/
|
||||
|
|
@ -34,6 +42,12 @@ public class LocationTest {
|
|||
Assert.assertTrue(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNameSet_buildLocation() {
|
||||
Location l = Location.Builder.newInstance().setName("mystreet 6a").setIndex(1).build();
|
||||
Assert.assertEquals("mystreet 6a",l.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenIndexSetWitFactory_returnCorrectLocation() {
|
||||
Location l = Location.newInstance(1);
|
||||
|
|
@ -68,8 +82,8 @@ public class LocationTest {
|
|||
@Test
|
||||
public void whenCoordinateSet_build() {
|
||||
Location l = Location.Builder.newInstance().setCoordinate(Coordinate.newInstance(10, 20)).build();
|
||||
Assert.assertEquals(10., l.getCoordinate().getX());
|
||||
Assert.assertEquals(20., l.getCoordinate().getY());
|
||||
Assert.assertEquals(10., l.getCoordinate().getX(),0.001);
|
||||
Assert.assertEquals(20., l.getCoordinate().getY(),0.001);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
|
||||
|
|
@ -77,10 +91,22 @@ public class LocationTest {
|
|||
public void whenCoordinateSetWithFactory_returnCorrectLocation() {
|
||||
// Location l = Location.Builder.newInstance().setCoordinate(Coordinate.newInstance(10,20)).build();
|
||||
Location l = Location.newInstance(10, 20);
|
||||
Assert.assertEquals(10., l.getCoordinate().getX());
|
||||
Assert.assertEquals(20., l.getCoordinate().getY());
|
||||
Assert.assertEquals(10., l.getCoordinate().getX(),0.001);
|
||||
Assert.assertEquals(20., l.getCoordinate().getY(),0.001);
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenSettingUserData_itIsAssociatedWithTheLocation() {
|
||||
Location one = Location.Builder.newInstance().setCoordinate(Coordinate.newInstance(10, 20))
|
||||
.setUserData(new HashMap<String, Object>()).build();
|
||||
Location two = Location.Builder.newInstance().setIndex(1).setUserData(42).build();
|
||||
Location three = Location.Builder.newInstance().setIndex(2).build();
|
||||
|
||||
assertTrue(one.getUserData() instanceof Map);
|
||||
assertEquals(42, two.getUserData());
|
||||
assertNull(three.getUserData());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import com.graphhopper.jsprit.core.problem.job.Shipment;
|
|||
import com.graphhopper.jsprit.core.problem.misc.ActivityContext;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||
|
||||
|
|
@ -47,7 +48,9 @@ public class MaxTimeInVehicleConstraintTest {
|
|||
|
||||
Delivery d1;
|
||||
|
||||
Shipment shipment;
|
||||
Shipment s1;
|
||||
|
||||
Shipment s2;
|
||||
|
||||
Delivery d2;
|
||||
|
||||
|
|
@ -68,8 +71,13 @@ public class MaxTimeInVehicleConstraintTest {
|
|||
|
||||
private void ini(double maxTime){
|
||||
d1 = Delivery.Builder.newInstance("d1").setLocation(Location.newInstance(10,0)).build();
|
||||
shipment = Shipment.Builder.newInstance("shipment").setPickupLocation(Location.newInstance(20,0))
|
||||
|
||||
s1 = Shipment.Builder.newInstance("s1").setPickupLocation(Location.newInstance(20,0))
|
||||
.setDeliveryLocation(Location.newInstance(40,0)).setMaxTimeInVehicle(maxTime).build();
|
||||
|
||||
s2 = Shipment.Builder.newInstance("s2").setPickupLocation(Location.newInstance(20,0))
|
||||
.setDeliveryLocation(Location.newInstance(40,0)).setMaxTimeInVehicle(maxTime).build();
|
||||
|
||||
d2 = Delivery.Builder.newInstance("d2").setLocation(Location.newInstance(30,0)).setServiceTime(10).build();
|
||||
|
||||
p1 = Pickup.Builder.newInstance("p1").setLocation(Location.newInstance(10, 0)).build();
|
||||
|
|
@ -77,11 +85,59 @@ public class MaxTimeInVehicleConstraintTest {
|
|||
|
||||
v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0)).build();
|
||||
|
||||
vrp = VehicleRoutingProblem.Builder.newInstance().addJob(d1).addJob(shipment).addJob(d2).addJob(p1).addJob(p2)
|
||||
vrp = VehicleRoutingProblem.Builder.newInstance().addJob(d1).addJob(s1).addJob(d2).addJob(p1).addJob(p2)
|
||||
.addVehicle(v).build();
|
||||
|
||||
route = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory())
|
||||
.addDelivery(d1).addPickup(shipment).addDelivery(shipment).build();
|
||||
.addDelivery(d1).addPickup(s1).addDelivery(s1).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shiftOfExistingShipmentsShouldWork(){
|
||||
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0)).build();
|
||||
|
||||
Shipment s1 = Shipment.Builder.newInstance("s1").setPickupLocation(Location.newInstance(20,0))
|
||||
.setDeliveryLocation(Location.newInstance(40,0)).setMaxTimeInVehicle(20).build();
|
||||
|
||||
Shipment s2 = Shipment.Builder.newInstance("s2").setPickupLocation(Location.newInstance(20,0))
|
||||
.setPickupServiceTime(10)
|
||||
.setDeliveryLocation(Location.newInstance(40,0)).setMaxTimeInVehicle(20).build();
|
||||
|
||||
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addJob(s1).addJob(s2).addVehicle(v).build();
|
||||
|
||||
VehicleRoute route = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory())
|
||||
.addPickup(s1).addDelivery(s1).build();
|
||||
|
||||
StateManager stateManager = new StateManager(vrp);
|
||||
StateId latestStartId = stateManager.createStateId("latest-start-id");
|
||||
|
||||
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||
stateManager.addStateUpdater(updater);
|
||||
stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList<Job>());
|
||||
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
|
||||
JobInsertionContext c = new JobInsertionContext(route,s2,v,route.getDriver(),0.);
|
||||
List<AbstractActivity> acts = vrp.getActivities(s2);
|
||||
|
||||
c.getAssociatedActivities().add(acts.get(0));
|
||||
c.getAssociatedActivities().add(acts.get(1));
|
||||
|
||||
Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getStart(), acts.get(0), route.getActivities().get(0), 0));
|
||||
Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, act(route,0), acts.get(0), act(route,1), 20));
|
||||
Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, act(route,1), acts.get(0), route.getEnd(), 40));
|
||||
|
||||
//insert pickup at 0
|
||||
c.setRelatedActivityContext(new ActivityContext());
|
||||
c.getRelatedActivityContext().setArrivalTime(20);
|
||||
c.getRelatedActivityContext().setEndTime(30);
|
||||
c.getRelatedActivityContext().setInsertionIndex(0);
|
||||
|
||||
Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, acts.get(0), acts.get(1), act(route,0), 30));
|
||||
Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, act(route,0), acts.get(1), act(route,1), 30));
|
||||
}
|
||||
|
||||
private TourActivity act(VehicleRoute route, int index){
|
||||
return route.getActivities().get(index);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -94,7 +150,7 @@ public class MaxTimeInVehicleConstraintTest {
|
|||
stateManager.addStateUpdater(updater);
|
||||
stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList<Job>());
|
||||
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager);
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
|
||||
JobInsertionContext c = new JobInsertionContext(route,d2,v,route.getDriver(),0.);
|
||||
List<AbstractActivity> acts = vrp.getActivities(d2);
|
||||
c.getAssociatedActivities().add(acts.get(0));
|
||||
|
|
@ -116,7 +172,7 @@ public class MaxTimeInVehicleConstraintTest {
|
|||
stateManager.addStateUpdater(updater);
|
||||
stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList<Job>());
|
||||
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager);
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
|
||||
JobInsertionContext c = new JobInsertionContext(route,d2,v,route.getDriver(),0.);
|
||||
List<AbstractActivity> acts = vrp.getActivities(d2);
|
||||
c.getAssociatedActivities().add(acts.get(0));
|
||||
|
|
@ -142,9 +198,9 @@ public class MaxTimeInVehicleConstraintTest {
|
|||
stateManager.addStateUpdater(updater);
|
||||
stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList<Job>());
|
||||
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager);
|
||||
JobInsertionContext c = new JobInsertionContext(r,shipment,v,r.getDriver(),0.);
|
||||
List<AbstractActivity> acts = vrp.getActivities(shipment);
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
|
||||
JobInsertionContext c = new JobInsertionContext(r, s1,v,r.getDriver(),0.);
|
||||
List<AbstractActivity> acts = vrp.getActivities(s1);
|
||||
c.getAssociatedActivities().add(acts.get(0));
|
||||
c.getAssociatedActivities().add(acts.get(1));
|
||||
|
||||
|
|
@ -169,8 +225,8 @@ public class MaxTimeInVehicleConstraintTest {
|
|||
// stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList<Job>());
|
||||
//
|
||||
// MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager);
|
||||
// JobInsertionContext c = new JobInsertionContext(r,shipment,v,r.getDriver(),0.);
|
||||
// List<AbstractActivity> acts = vrp.getActivities(shipment);
|
||||
// JobInsertionContext c = new JobInsertionContext(r,s1,v,r.getDriver(),0.);
|
||||
// List<AbstractActivity> acts = vrp.getActivities(s1);
|
||||
// c.getAssociatedActivities().add(acts.get(0));
|
||||
// c.getAssociatedActivities().add(acts.get(1));
|
||||
//
|
||||
|
|
@ -192,14 +248,14 @@ public class MaxTimeInVehicleConstraintTest {
|
|||
StateId latestStartId = stateManager.createStateId("latest-start-id");
|
||||
|
||||
Map<String,Double> maxTimes = new HashMap<>();
|
||||
maxTimes.put("shipment",25d);
|
||||
maxTimes.put("s1",25d);
|
||||
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||
stateManager.addStateUpdater(updater);
|
||||
stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList<Job>());
|
||||
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager);
|
||||
JobInsertionContext c = new JobInsertionContext(r,shipment,v,r.getDriver(),0.);
|
||||
List<AbstractActivity> acts = vrp.getActivities(shipment);
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
|
||||
JobInsertionContext c = new JobInsertionContext(r, s1,v,r.getDriver(),0.);
|
||||
List<AbstractActivity> acts = vrp.getActivities(s1);
|
||||
c.getAssociatedActivities().add(acts.get(0));
|
||||
c.getAssociatedActivities().add(acts.get(1));
|
||||
|
||||
|
|
@ -223,14 +279,14 @@ public class MaxTimeInVehicleConstraintTest {
|
|||
StateId latestStartId = stateManager.createStateId("latest-start-id");
|
||||
|
||||
Map<String,Double> maxTimes = new HashMap<>();
|
||||
maxTimes.put("shipment",25d);
|
||||
maxTimes.put("s1",25d);
|
||||
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||
stateManager.addStateUpdater(updater);
|
||||
stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList<Job>());
|
||||
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager);
|
||||
JobInsertionContext c = new JobInsertionContext(r,shipment,v,r.getDriver(),0.);
|
||||
List<AbstractActivity> acts = vrp.getActivities(shipment);
|
||||
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
|
||||
JobInsertionContext c = new JobInsertionContext(r, s1,v,r.getDriver(),0.);
|
||||
List<AbstractActivity> acts = vrp.getActivities(s1);
|
||||
c.getAssociatedActivities().add(acts.get(0));
|
||||
c.getAssociatedActivities().add(acts.get(1));
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.problem.constraint;
|
||||
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateId;
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.cost.TransportDistance;
|
||||
import com.graphhopper.jsprit.core.problem.job.Delivery;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.job.Pickup;
|
||||
import com.graphhopper.jsprit.core.problem.job.Shipment;
|
||||
import com.graphhopper.jsprit.core.problem.misc.ActivityContext;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.End;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.Start;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||
import com.graphhopper.jsprit.core.util.ManhattanCosts;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 18/05/16.
|
||||
*/
|
||||
public class VehicleDependentTraveledDistanceTest {
|
||||
|
||||
StateManager stateManager;
|
||||
|
||||
VehicleRoute route;
|
||||
|
||||
StateId traveledDistanceId;
|
||||
|
||||
Vehicle vehicle;
|
||||
|
||||
Vehicle vehicle2;
|
||||
|
||||
VehicleRoutingProblem vrp;
|
||||
|
||||
Delivery d1,d2,newDelivery;
|
||||
|
||||
Pickup pickup;
|
||||
|
||||
Shipment s1;
|
||||
|
||||
Map<Vehicle,Double> maxDistanceMap;
|
||||
|
||||
|
||||
@Before
|
||||
public void doBefore(){
|
||||
vehicle = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0)).build();
|
||||
vehicle2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance(10,10)).build();
|
||||
|
||||
maxDistanceMap = new HashMap<>();
|
||||
maxDistanceMap.put(vehicle,200d);
|
||||
maxDistanceMap.put(vehicle2,200d);
|
||||
|
||||
d1 = Delivery.Builder.newInstance("d1").setLocation(Location.newInstance(10,10)).build();
|
||||
d2 = Delivery.Builder.newInstance("d2").setLocation(Location.newInstance(20,15)).build();
|
||||
pickup = Pickup.Builder.newInstance("pickup").setLocation(Location.newInstance(50,50)).build();
|
||||
s1 = Shipment.Builder.newInstance("s1").setPickupLocation(Location.newInstance(35,30))
|
||||
.setDeliveryLocation(Location.newInstance(20,25)).build();
|
||||
|
||||
newDelivery = Delivery.Builder.newInstance("new").setLocation(Location.newInstance(-10,10)).build();
|
||||
|
||||
vrp = VehicleRoutingProblem.Builder.newInstance()
|
||||
.setRoutingCost(new ManhattanCosts()).addVehicle(vehicle).addVehicle(vehicle2)
|
||||
.addJob(d1).addJob(d2).addJob(s1).addJob(pickup).addJob(newDelivery).build();
|
||||
|
||||
route = VehicleRoute.Builder.newInstance(vehicle).setJobActivityFactory(vrp.getJobActivityFactory())
|
||||
.addDelivery(d1).addDelivery(d2).addPickup(s1).addPickup(pickup).addDelivery(s1).build();
|
||||
|
||||
stateManager = new StateManager(vrp);
|
||||
|
||||
traveledDistanceId = stateManager.createStateId("traveledDistance");
|
||||
|
||||
com.graphhopper.jsprit.core.algorithm.state.VehicleDependentTraveledDistance traveledDistance =
|
||||
new com.graphhopper.jsprit.core.algorithm.state.VehicleDependentTraveledDistance(new TransportDistance() {
|
||||
@Override
|
||||
public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) {
|
||||
return new ManhattanCosts().getDistance(from,to,departureTime,vehicle);
|
||||
}
|
||||
},stateManager,traveledDistanceId,Arrays.asList(vehicle,vehicle2));
|
||||
|
||||
stateManager.addStateUpdater(traveledDistance);
|
||||
stateManager.informInsertionStarts(Arrays.asList(route), Collections.<Job>emptyList());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenEndLocationIsSet_constraintShouldWork(){
|
||||
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0))
|
||||
.setEndLocation(Location.newInstance(10,0)).build();
|
||||
Pickup pickup = Pickup.Builder.newInstance("pickup").setLocation(Location.newInstance(10,0)).build();
|
||||
vrp = VehicleRoutingProblem.Builder.newInstance().addVehicle(vehicle).addJob(pickup).build();
|
||||
route = VehicleRoute.emptyRoute();
|
||||
maxDistanceMap = new HashMap<>();
|
||||
maxDistanceMap.put(vehicle,5d);
|
||||
|
||||
MaxDistanceConstraint maxDistanceConstraint =
|
||||
new MaxDistanceConstraint(new StateManager(vrp), traveledDistanceId, new TransportDistance() {
|
||||
@Override
|
||||
public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) {
|
||||
return vrp.getTransportCosts().getTransportTime(from,to,departureTime, null, vehicle);
|
||||
}
|
||||
},maxDistanceMap);
|
||||
JobInsertionContext context = new JobInsertionContext(route,pickup,vehicle,null,0);
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,
|
||||
new Start(vehicle.getStartLocation(),0,Double.MAX_VALUE),vrp.getActivities(pickup).get(0),
|
||||
new End(vehicle.getEndLocation(),0,Double.MAX_VALUE),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED));
|
||||
}
|
||||
|
||||
/*
|
||||
vehicle: 200.0
|
||||
vehicle (max distance): 200.0
|
||||
vehicle2: 160.0
|
||||
vehicle2 (max distance): 180.0
|
||||
*/
|
||||
@Test
|
||||
public void insertNewInVehicleShouldFail(){
|
||||
MaxDistanceConstraint maxDistanceConstraint =
|
||||
new MaxDistanceConstraint(stateManager, traveledDistanceId, new TransportDistance() {
|
||||
@Override
|
||||
public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) {
|
||||
return vrp.getTransportCosts().getTransportTime(from,to,departureTime, null, vehicle);
|
||||
}
|
||||
},maxDistanceMap);
|
||||
JobInsertionContext context = new JobInsertionContext(route,newDelivery,vehicle,null,0);
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,route.getStart(),newAct(),act(0),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED));
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(0),newAct(),act(1),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED));
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(1),newAct(),act(2),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED));
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(2),newAct(),act(3),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED));
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(3),newAct(),act(4),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED));
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(4),newAct(),route.getEnd(),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void insertNewInVehicle2ShouldBeCorrect(){
|
||||
//current distance vehicle2: 160 allowed: 200
|
||||
MaxDistanceConstraint maxDistanceConstraint =
|
||||
new MaxDistanceConstraint(stateManager, traveledDistanceId, new TransportDistance() {
|
||||
@Override
|
||||
public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) {
|
||||
return vrp.getTransportCosts().getTransportTime(from,to,departureTime, null, vehicle);
|
||||
}
|
||||
},maxDistanceMap);
|
||||
JobInsertionContext context = new JobInsertionContext(route,newDelivery,vehicle2,null,0);
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,route.getStart(),newAct(),act(0),0).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED));
|
||||
//additional distance: 20+35-15=40
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(0),newAct(),act(1),0).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED));
|
||||
//additional distance: 35+65-30=70
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(1),newAct(),act(2),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED));
|
||||
//additional distance: 65+100-35
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(2),newAct(),act(3),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED));
|
||||
//additional distance: 100+45-55
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(3),newAct(),act(4),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED));
|
||||
//additional distance: 45+20-25
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(4),newAct(),route.getEnd(),0).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED));
|
||||
}
|
||||
|
||||
private TourActivity act(int i) {
|
||||
return route.getActivities().get(i);
|
||||
}
|
||||
|
||||
private TourActivity newAct(){
|
||||
return vrp.getActivities(newDelivery).get(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void traveledDistanceShouldBeCorrect(){
|
||||
Assert.assertEquals(20d,stateManager.getActivityState(route.getActivities().get(0),vehicle,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(35d,stateManager.getActivityState(route.getActivities().get(1),vehicle,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(65d,stateManager.getActivityState(route.getActivities().get(2),vehicle,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(100d,stateManager.getActivityState(route.getActivities().get(3),vehicle,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(155d,stateManager.getActivityState(route.getActivities().get(4),vehicle,traveledDistanceId,Double.class),0.01);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void traveledDistanceWithVehicle2ShouldBeCorrect(){
|
||||
Assert.assertEquals(0d,stateManager.getActivityState(route.getActivities().get(0),vehicle2,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(15d,stateManager.getActivityState(route.getActivities().get(1),vehicle2,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(45d,stateManager.getActivityState(route.getActivities().get(2),vehicle2,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(80d,stateManager.getActivityState(route.getActivities().get(3),vehicle2,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(135d,stateManager.getActivityState(route.getActivities().get(4),vehicle2,traveledDistanceId,Double.class),0.01);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void distanceOfShipmentInRoute(){
|
||||
double traveledDistanceBeforePickup = stateManager.getActivityState(route.getActivities().get(2), vehicle,traveledDistanceId, Double.class);
|
||||
double traveledDistanceBeforeDelivery = stateManager.getActivityState(route.getActivities().get(4), vehicle, traveledDistanceId, Double.class);
|
||||
Assert.assertEquals(90d,traveledDistanceBeforeDelivery-traveledDistanceBeforePickup,0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void distanceOfShipmentInRouteVehicle2(){
|
||||
double traveledDistanceBeforePickup = stateManager.getActivityState(route.getActivities().get(2), vehicle2,traveledDistanceId, Double.class);
|
||||
double traveledDistanceBeforeDelivery = stateManager.getActivityState(route.getActivities().get(4), vehicle2, traveledDistanceId, Double.class);
|
||||
Assert.assertEquals(90d,traveledDistanceBeforeDelivery-traveledDistanceBeforePickup,0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void distanceOfPickupInRoute(){
|
||||
double traveledDistanceBeforePickup = stateManager.getActivityState(route.getActivities().get(3), vehicle, traveledDistanceId, Double.class);
|
||||
double total = stateManager.getRouteState(route, vehicle,traveledDistanceId, Double.class);
|
||||
Assert.assertEquals(100d,total-traveledDistanceBeforePickup,0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void distanceOfPickupInRouteVehicle2(){
|
||||
double traveledDistanceBeforePickup = stateManager.getActivityState(route.getActivities().get(3), vehicle2, traveledDistanceId, Double.class);
|
||||
double total = stateManager.getRouteState(route, vehicle2,traveledDistanceId, Double.class);
|
||||
Assert.assertEquals(80d,total-traveledDistanceBeforePickup,0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void distanceToTravelShouldBeCorrect(){
|
||||
double total = stateManager.getRouteState(route, vehicle, traveledDistanceId, Double.class);
|
||||
Assert.assertEquals(180d,total - stateManager.getActivityState(route.getActivities().get(0),vehicle,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(165d, total - stateManager.getActivityState(route.getActivities().get(1), vehicle, traveledDistanceId, Double.class), 0.01);
|
||||
Assert.assertEquals(135d,total - stateManager.getActivityState(route.getActivities().get(2),vehicle,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(100d, total - stateManager.getActivityState(route.getActivities().get(3), vehicle, traveledDistanceId, Double.class), 0.01);
|
||||
Assert.assertEquals(45d, total - stateManager.getActivityState(route.getActivities().get(4), vehicle, traveledDistanceId, Double.class), 0.01);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void distanceToTravelShouldBeCorrectVehicle2(){
|
||||
double total = stateManager.getRouteState(route, vehicle2, traveledDistanceId, Double.class);
|
||||
Assert.assertEquals(160d,total - stateManager.getActivityState(route.getActivities().get(0),vehicle2,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(145d, total - stateManager.getActivityState(route.getActivities().get(1), vehicle2, traveledDistanceId, Double.class), 0.01);
|
||||
Assert.assertEquals(115d,total - stateManager.getActivityState(route.getActivities().get(2),vehicle2,traveledDistanceId,Double.class),0.01);
|
||||
Assert.assertEquals(80d, total - stateManager.getActivityState(route.getActivities().get(3), vehicle2, traveledDistanceId, Double.class), 0.01);
|
||||
Assert.assertEquals(25d, total - stateManager.getActivityState(route.getActivities().get(4), vehicle2, traveledDistanceId, Double.class), 0.01);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAddingDeliverShipment_constraintShouldWork() {
|
||||
Shipment shipment = Shipment.Builder.newInstance("s")
|
||||
.setPickupLocation(Location.newInstance(0, 3))
|
||||
.setDeliveryLocation(Location.newInstance(4, 0))
|
||||
.build();
|
||||
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("v")
|
||||
.setStartLocation(Location.newInstance(0, 0))
|
||||
.build();
|
||||
final VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
|
||||
.addJob(shipment)
|
||||
.addVehicle(vehicle)
|
||||
.build();
|
||||
VehicleRoute route = VehicleRoute.emptyRoute();
|
||||
JobInsertionContext context = new JobInsertionContext(route, shipment, vehicle, null, 0);
|
||||
context.getAssociatedActivities().add(vrp.getActivities(shipment).get(0));
|
||||
context.getAssociatedActivities().add(vrp.getActivities(shipment).get(1));
|
||||
maxDistanceMap = new HashMap<>();
|
||||
maxDistanceMap.put(vehicle,12d);
|
||||
|
||||
StateManager stateManager = new StateManager(vrp);
|
||||
MaxDistanceConstraint maxDistanceConstraint =
|
||||
new MaxDistanceConstraint(stateManager, traveledDistanceId, new TransportDistance() {
|
||||
@Override
|
||||
public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) {
|
||||
return vrp.getTransportCosts().getTransportTime(from,to,departureTime, null, vehicle);
|
||||
}
|
||||
},maxDistanceMap);
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,
|
||||
new Start(vehicle.getStartLocation(), 0, Double.MAX_VALUE),
|
||||
vrp.getActivities(shipment).get(0),
|
||||
new End(vehicle.getEndLocation(), 0, Double.MAX_VALUE),
|
||||
0).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED));
|
||||
|
||||
ActivityContext pickupContext = new ActivityContext();
|
||||
pickupContext.setArrivalTime(3);
|
||||
pickupContext.setEndTime(3);
|
||||
pickupContext.setInsertionIndex(0);
|
||||
context.setRelatedActivityContext(pickupContext);
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,
|
||||
vrp.getActivities(shipment).get(0),
|
||||
vrp.getActivities(shipment).get(1),
|
||||
new End(vehicle.getEndLocation(), 0, Double.MAX_VALUE),
|
||||
3).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAddingDeliverShipmentWithVehDiffStartEndLocs_constraintShouldWork() {
|
||||
Shipment shipment = Shipment.Builder.newInstance("s")
|
||||
.setPickupLocation(Location.newInstance(0, 1))
|
||||
.setDeliveryLocation(Location.newInstance(4, 1))
|
||||
.build();
|
||||
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("v")
|
||||
.setStartLocation(Location.newInstance(0, 0))
|
||||
.setEndLocation(Location.newInstance(0, 4))
|
||||
.build();
|
||||
final VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
|
||||
.addJob(shipment)
|
||||
.addVehicle(vehicle)
|
||||
.build();
|
||||
VehicleRoute route = VehicleRoute.emptyRoute();
|
||||
JobInsertionContext context = new JobInsertionContext(route, shipment, vehicle, null, 0);
|
||||
context.getAssociatedActivities().add(vrp.getActivities(shipment).get(0));
|
||||
context.getAssociatedActivities().add(vrp.getActivities(shipment).get(1));
|
||||
maxDistanceMap = new HashMap<>();
|
||||
maxDistanceMap.put(vehicle,10d);
|
||||
|
||||
StateManager stateManager = new StateManager(vrp);
|
||||
MaxDistanceConstraint maxDistanceConstraint =
|
||||
new MaxDistanceConstraint(stateManager, traveledDistanceId, new TransportDistance() {
|
||||
@Override
|
||||
public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) {
|
||||
return vrp.getTransportCosts().getTransportTime(from,to,departureTime, null, vehicle);
|
||||
}
|
||||
},maxDistanceMap);
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,
|
||||
new Start(vehicle.getStartLocation(), 0, Double.MAX_VALUE),
|
||||
vrp.getActivities(shipment).get(0),
|
||||
new End(vehicle.getEndLocation(), 0, Double.MAX_VALUE),
|
||||
0).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED));
|
||||
|
||||
ActivityContext pickupContext = new ActivityContext();
|
||||
pickupContext.setArrivalTime(1);
|
||||
pickupContext.setEndTime(1);
|
||||
pickupContext.setInsertionIndex(0);
|
||||
context.setRelatedActivityContext(pickupContext);
|
||||
Assert.assertTrue(maxDistanceConstraint.fulfilled(context,
|
||||
vrp.getActivities(shipment).get(0),
|
||||
vrp.getActivities(shipment).get(1),
|
||||
new End(vehicle.getEndLocation(), 0, Double.MAX_VALUE),
|
||||
1).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED));
|
||||
}
|
||||
}
|
||||
|
|
@ -17,11 +17,18 @@
|
|||
*/
|
||||
package com.graphhopper.jsprit.core.problem.job;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
|
||||
public class DeliveryTest {
|
||||
|
||||
|
|
@ -119,4 +126,16 @@ public class DeliveryTest {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenSettingUserData_itIsAssociatedWithTheJob() {
|
||||
Delivery one = Delivery.Builder.newInstance("s").setLocation(Location.newInstance("loc"))
|
||||
.setUserData(new HashMap<String, Object>()).build();
|
||||
Delivery two = Delivery.Builder.newInstance("s2").setLocation(Location.newInstance("loc")).setUserData(42)
|
||||
.build();
|
||||
Delivery three = Delivery.Builder.newInstance("s3").setLocation(Location.newInstance("loc")).build();
|
||||
|
||||
assertTrue(one.getUserData() instanceof Map);
|
||||
assertEquals(42, two.getUserData());
|
||||
assertNull(three.getUserData());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,18 @@
|
|||
*/
|
||||
package com.graphhopper.jsprit.core.problem.job;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
|
||||
public class PickupTest {
|
||||
|
||||
|
|
@ -105,6 +112,18 @@ public class PickupTest {
|
|||
Assert.assertEquals(2, s.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSettingUserData_itIsAssociatedWithTheJob() {
|
||||
Pickup one = Pickup.Builder.newInstance("s").setLocation(Location.newInstance("loc"))
|
||||
.setUserData(new HashMap<String, Object>()).build();
|
||||
Pickup two = Pickup.Builder.newInstance("s2").setLocation(Location.newInstance("loc")).setUserData(42).build();
|
||||
Pickup three = Pickup.Builder.newInstance("s3").setLocation(Location.newInstance("loc")).build();
|
||||
|
||||
assertTrue(one.getUserData() instanceof Map);
|
||||
assertEquals(42, two.getUserData());
|
||||
assertNull(three.getUserData());
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void whenAddingMaxTimeInVehicle_itShouldThrowEx(){
|
||||
Pickup s = Pickup.Builder.newInstance("s").setLocation(Location.newInstance("loc"))
|
||||
|
|
|
|||
|
|
@ -17,17 +17,25 @@
|
|||
*/
|
||||
package com.graphhopper.jsprit.core.problem.job;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsCollectionContaining.hasItem;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsCollectionContaining.hasItem;
|
||||
import static org.junit.Assert.*;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
|
||||
public class ServiceTest {
|
||||
|
||||
|
|
@ -250,6 +258,13 @@ public class ServiceTest {
|
|||
Assert.assertEquals(3, s.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSettingPriorities_itShouldBeSetCorrectly3() {
|
||||
Service s = Service.Builder.newInstance("s").setLocation(Location.newInstance("loc"))
|
||||
.setPriority(10).build();
|
||||
Assert.assertEquals(10, s.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNotSettingPriorities_defaultShouldBe2(){
|
||||
Service s = Service.Builder.newInstance("s").setLocation(Location.newInstance("loc"))
|
||||
|
|
@ -285,4 +300,17 @@ public class ServiceTest {
|
|||
Assert.assertEquals(Double.MAX_VALUE, s.getMaxTimeInVehicle(),0.001);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenSettingUserData_itIsAssociatedWithTheJob() {
|
||||
Service one = Service.Builder.newInstance("s").setLocation(Location.newInstance("loc"))
|
||||
.setUserData(new HashMap<String, Object>()).build();
|
||||
Service two = Service.Builder.newInstance("s2").setLocation(Location.newInstance("loc")).setUserData(42)
|
||||
.build();
|
||||
Service three = Service.Builder.newInstance("s3").setLocation(Location.newInstance("loc")).build();
|
||||
|
||||
assertTrue(one.getUserData() instanceof Map);
|
||||
assertEquals(42, two.getUserData());
|
||||
assertNull(three.getUserData());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,16 +17,25 @@
|
|||
*/
|
||||
package com.graphhopper.jsprit.core.problem.job;
|
||||
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsCollectionContaining.hasItem;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
import com.graphhopper.jsprit.core.util.Coordinate;
|
||||
import com.graphhopper.jsprit.core.util.TestUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsCollectionContaining.hasItem;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ShipmentTest {
|
||||
|
||||
|
|
@ -401,6 +410,14 @@ public class ShipmentTest {
|
|||
Assert.assertEquals(3, s.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSettingPriorities_itShouldBeSetCorrectly3() {
|
||||
Shipment s = Shipment.Builder.newInstance("s").setPickupLocation(Location.newInstance("loc"))
|
||||
.setDeliveryLocation(Location.newInstance("loc"))
|
||||
.setPriority(10).build();
|
||||
Assert.assertEquals(10, s.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNotSettingPriorities_defaultShouldBe2(){
|
||||
Shipment s = Shipment.Builder.newInstance("s").setPickupLocation(Location.newInstance("loc"))
|
||||
|
|
@ -425,6 +442,19 @@ public class ShipmentTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSettingUserData_itIsAssociatedWithTheJob() {
|
||||
Shipment one = Shipment.Builder.newInstance("s").setPickupLocation(Location.newInstance("loc"))
|
||||
.setDeliveryLocation(Location.newInstance("loc")).setUserData(new HashMap<String, Object>()).build();
|
||||
Shipment two = Shipment.Builder.newInstance("s2").setPickupLocation(Location.newInstance("loc"))
|
||||
.setDeliveryLocation(Location.newInstance("loc")).setUserData(42).build();
|
||||
Shipment three = Shipment.Builder.newInstance("s3").setPickupLocation(Location.newInstance("loc"))
|
||||
.setDeliveryLocation(Location.newInstance("loc")).build();
|
||||
|
||||
assertTrue(one.getUserData() instanceof Map);
|
||||
assertEquals(42, two.getUserData());
|
||||
assertNull(three.getUserData());
|
||||
}
|
||||
@Test
|
||||
public void whenAddingMaxTimeInVehicle_itShouldBeSet(){
|
||||
Shipment s = Shipment.Builder.newInstance("s").setPickupLocation(Location.newInstance("loc")).setDeliveryLocation(Location.newInstance("loc"))
|
||||
|
|
|
|||
|
|
@ -18,12 +18,20 @@
|
|||
package com.graphhopper.jsprit.core.problem.vehicle;
|
||||
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.job.Break;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
public class VehicleImplTest {
|
||||
|
|
@ -39,7 +47,7 @@ public class VehicleImplTest {
|
|||
@Test
|
||||
public void whenAddingDriverBreak_itShouldBeAddedCorrectly() {
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("type").build();
|
||||
Break aBreak = (Break) Break.Builder.newInstance("break").setTimeWindow(TimeWindow.newInstance(100, 200)).setServiceTime(30).build();
|
||||
Break aBreak = Break.Builder.newInstance("break").setTimeWindow(TimeWindow.newInstance(100, 200)).setServiceTime(30).build();
|
||||
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("start"))
|
||||
.setType(type1).setEndLocation(Location.newInstance("start"))
|
||||
.setBreak(aBreak).build();
|
||||
|
|
@ -237,5 +245,19 @@ public class VehicleImplTest {
|
|||
assertFalse(v.getSkills().containsSkill("ScrewDriver"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSettingUserData_itIsAssociatedWithTheVehicle() {
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("type").build();
|
||||
Vehicle one = VehicleImpl.Builder.newInstance("v").setType(type1)
|
||||
.setStartLocation(Location.newInstance("start")).setUserData(new HashMap<String, Object>()).build();
|
||||
Vehicle two = VehicleImpl.Builder.newInstance("v").setType(type1)
|
||||
.setStartLocation(Location.newInstance("start")).setUserData(42).build();
|
||||
Vehicle three = VehicleImpl.Builder.newInstance("v").setType(type1)
|
||||
.setStartLocation(Location.newInstance("start")).build();
|
||||
|
||||
assertTrue(one.getUserData() instanceof Map);
|
||||
assertEquals(42, two.getUserData());
|
||||
assertNull(three.getUserData());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,15 @@
|
|||
*/
|
||||
package com.graphhopper.jsprit.core.problem.vehicle;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class VehicleTypeImplTest {
|
||||
|
||||
|
|
@ -152,4 +158,15 @@ public class VehicleTypeImplTest {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenSettingUserData_itIsAssociatedWithTheVehicleType() {
|
||||
VehicleType one = VehicleTypeImpl.Builder.newInstance("type").setUserData(new HashMap<String, Object>())
|
||||
.build();
|
||||
VehicleType two = VehicleTypeImpl.Builder.newInstance("type").setUserData(42).build();
|
||||
VehicleType three = VehicleTypeImpl.Builder.newInstance("type").build();
|
||||
|
||||
assertTrue(one.getUserData() instanceof Map);
|
||||
assertEquals(42, two.getUserData());
|
||||
assertNull(three.getUserData());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ public class FastVehicleRoutingTransportCostsMatrixTest {
|
|||
assertEquals(2., matrix.getDistance(2, 1), 0.1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenAddingDistanceToAsymmetricMatrix_itShouldReturnCorrectValues() {
|
||||
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(3, false);
|
||||
|
|
@ -62,6 +63,18 @@ public class FastVehicleRoutingTransportCostsMatrixTest {
|
|||
assertEquals(2., matrix.getTransportTime(loc(2), loc(1), 0.0, null, null), 0.1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAddingTimeAndDistanceToSymmetricMatrix_itShouldReturnCorrectValues2() {
|
||||
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(3, true);
|
||||
matrixBuilder.addTransportTimeAndDistance(1, 2, 2.,100.);
|
||||
FastVehicleRoutingTransportCostsMatrix matrix = matrixBuilder.build();
|
||||
assertEquals(2., matrix.getTransportTime(loc(1), loc(2), 0.0, null, null), 0.1);
|
||||
assertEquals(2., matrix.getTransportTime(loc(2), loc(1), 0.0, null, null), 0.1);
|
||||
|
||||
assertEquals(100., matrix.getDistance(loc(1), loc(2), 0.0, null), 0.1);
|
||||
assertEquals(100., matrix.getDistance(loc(2), loc(1), 0.0, null), 0.1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAddingTimeToAsymmetricMatrix_itShouldReturnCorrectValues() {
|
||||
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(3, false);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.util;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||
import com.graphhopper.jsprit.core.algorithm.box.Jsprit;
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateId;
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.MaxDistanceConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.cost.TransportDistance;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
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 org.apache.commons.math3.stat.Frequency;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 06/02/17.
|
||||
*/
|
||||
public class UnassignedJobReasonTrackerTest {
|
||||
|
||||
Vehicle vehicle;
|
||||
|
||||
@Before
|
||||
public void doBefore() {
|
||||
VehicleTypeImpl.Builder vehicleTypeBuilder = VehicleTypeImpl.Builder.newInstance("vehicleType").addCapacityDimension(0, 1);
|
||||
VehicleType vehicleType = vehicleTypeBuilder.build();
|
||||
VehicleImpl.Builder vehicleBuilder = VehicleImpl.Builder.newInstance("vehicle");
|
||||
vehicleBuilder.setStartLocation(Location.newInstance(10, 10));
|
||||
vehicleBuilder.setType(vehicleType);
|
||||
vehicleBuilder.setEarliestStart(0).setLatestArrival(100);
|
||||
vehicle = vehicleBuilder.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnCorrectCapacityReasonCode() {
|
||||
Service service = Service.Builder.newInstance("1").addSizeDimension(0, 5).setLocation(Location.newInstance(5, 7)).build();
|
||||
|
||||
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.FINITE).addVehicle(vehicle).addJob(service)
|
||||
.build();
|
||||
|
||||
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
|
||||
UnassignedJobReasonTracker reasonTracker = new UnassignedJobReasonTracker();
|
||||
vra.addListener(reasonTracker);
|
||||
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
|
||||
Assert.assertEquals(1, solution.getUnassignedJobs().size());
|
||||
Assert.assertEquals(3, reasonTracker.getMostLikelyReasonCode(solution.getUnassignedJobs().iterator().next().getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnCorrectSkillReasonCode() {
|
||||
Service service = Service.Builder.newInstance("1").addSizeDimension(0, 1).addRequiredSkill("ice").setLocation(Location.newInstance(5, 7)).build();
|
||||
|
||||
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.FINITE).addVehicle(vehicle).addJob(service)
|
||||
.build();
|
||||
|
||||
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
|
||||
UnassignedJobReasonTracker reasonTracker = new UnassignedJobReasonTracker();
|
||||
vra.addListener(reasonTracker);
|
||||
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
|
||||
Assert.assertEquals(1, solution.getUnassignedJobs().size());
|
||||
Assert.assertEquals(1, reasonTracker.getMostLikelyReasonCode(solution.getUnassignedJobs().iterator().next().getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnCorrectTWReasonCode() {
|
||||
Service service = Service.Builder.newInstance("1").addSizeDimension(0, 1).setTimeWindow(TimeWindow.newInstance(110, 200)).setLocation(Location.newInstance(5, 7)).build();
|
||||
|
||||
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.FINITE).addVehicle(vehicle).addJob(service)
|
||||
.build();
|
||||
|
||||
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
|
||||
UnassignedJobReasonTracker reasonTracker = new UnassignedJobReasonTracker();
|
||||
vra.addListener(reasonTracker);
|
||||
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
|
||||
Assert.assertEquals(1, solution.getUnassignedJobs().size());
|
||||
Assert.assertEquals(2, reasonTracker.getMostLikelyReasonCode(solution.getUnassignedJobs().iterator().next().getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnCorrectMaxDistanceReasonCode() {
|
||||
Service service = Service.Builder.newInstance("1").setLocation(Location.newInstance(51, 0)).build();
|
||||
|
||||
Vehicle vehicle = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0, 0)).build();
|
||||
|
||||
final VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.FINITE).addVehicle(vehicle).addJob(service).build();
|
||||
|
||||
StateManager stateManager = new StateManager(vrp);
|
||||
ConstraintManager constraintManager = new ConstraintManager(vrp, stateManager);
|
||||
StateId maxDistance = stateManager.createStateId("max-distance");
|
||||
Map<Vehicle, Double> distMap = new HashMap<>();
|
||||
distMap.put(vehicle, 100d);
|
||||
MaxDistanceConstraint distanceConstraint = new MaxDistanceConstraint(stateManager, maxDistance, new TransportDistance() {
|
||||
@Override
|
||||
public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) {
|
||||
return vrp.getTransportCosts().getTransportCost(from, to, departureTime, null, vehicle);
|
||||
}
|
||||
}, distMap);
|
||||
constraintManager.addConstraint(distanceConstraint, ConstraintManager.Priority.CRITICAL);
|
||||
|
||||
VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp).setStateAndConstraintManager(stateManager, constraintManager)
|
||||
.buildAlgorithm();
|
||||
UnassignedJobReasonTracker reasonTracker = new UnassignedJobReasonTracker();
|
||||
vra.addListener(reasonTracker);
|
||||
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
|
||||
Assert.assertEquals(1, solution.getUnassignedJobs().size());
|
||||
Assert.assertEquals(4, reasonTracker.getMostLikelyReasonCode(solution.getUnassignedJobs().iterator().next().getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFreq() {
|
||||
Frequency frequency = new Frequency();
|
||||
frequency.addValue("VehicleDependentTimeWindowHardActivityConstraint");
|
||||
frequency.addValue("b");
|
||||
frequency.addValue("VehicleDependentTimeWindowHardActivityConstraint");
|
||||
|
||||
Iterator<Map.Entry<Comparable<?>, Long>> entryIterator = frequency.entrySetIterator();
|
||||
while (entryIterator.hasNext()) {
|
||||
Map.Entry<Comparable<?>, Long> e = entryIterator.next();
|
||||
System.out.println(e.getKey().toString() + " " + e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
56
jsprit-examples/input/p01_mod
Normal file
56
jsprit-examples/input/p01_mod
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
2 4 50 4
|
||||
0 2000
|
||||
1 37 52 0 7 1 4 1 2 4 8
|
||||
2 49 49 0 30 1 4 1 2 4 8
|
||||
3 52 64 0 16 1 4 1 2 4 8
|
||||
4 20 26 0 9 1 4 1 2 4 8
|
||||
5 40 30 0 21 1 4 1 2 4 8
|
||||
6 21 47 0 15 1 4 1 2 4 8
|
||||
7 17 63 0 19 1 4 1 2 4 8
|
||||
8 31 62 0 23 1 4 1 2 4 8
|
||||
9 52 33 0 11 1 4 1 2 4 8
|
||||
10 51 21 0 5 1 4 1 2 4 8
|
||||
11 42 41 0 19 1 4 1 2 4 8
|
||||
12 31 32 0 29 1 4 1 2 4 8
|
||||
13 5 25 0 23 1 4 1 2 4 8
|
||||
14 12 42 0 21 1 4 1 2 4 8
|
||||
15 36 16 0 10 1 4 1 2 4 8
|
||||
16 52 41 0 15 1 4 1 2 4 8
|
||||
17 27 23 0 3 1 4 1 2 4 8
|
||||
18 17 33 0 41 1 4 1 2 4 8
|
||||
19 13 13 0 9 1 4 1 2 4 8
|
||||
20 57 58 0 28 1 4 1 2 4 8
|
||||
21 62 42 0 8 1 4 1 2 4 8
|
||||
22 42 57 0 8 1 4 1 2 4 8
|
||||
23 16 57 0 16 1 4 1 2 4 8
|
||||
24 8 52 0 10 1 4 1 2 4 8
|
||||
25 7 38 0 28 1 4 1 2 4 8
|
||||
26 27 68 0 7 1 4 1 2 4 8
|
||||
27 30 48 0 15 1 4 1 2 4 8
|
||||
28 43 67 0 14 1 4 1 2 4 8
|
||||
29 58 48 0 6 1 4 1 2 4 8
|
||||
30 58 27 0 19 1 4 1 2 4 8
|
||||
31 37 69 0 11 1 4 1 2 4 8
|
||||
32 38 46 0 12 1 4 1 2 4 8
|
||||
33 46 10 0 23 1 4 1 2 4 8
|
||||
34 61 33 0 26 1 4 1 2 4 8
|
||||
35 62 63 0 17 1 4 1 2 4 8
|
||||
36 63 69 0 6 1 4 1 2 4 8
|
||||
37 32 22 0 9 1 4 1 2 4 8
|
||||
38 45 35 0 15 1 4 1 2 4 8
|
||||
39 59 15 0 14 1 4 1 2 4 8
|
||||
40 5 6 0 7 1 4 1 2 4 8
|
||||
41 10 17 0 27 1 4 1 2 4 8
|
||||
42 21 10 0 13 1 4 1 2 4 8
|
||||
43 5 64 0 11 1 4 1 2 4 8
|
||||
44 30 15 0 16 1 4 1 2 4 8
|
||||
45 39 10 0 10 1 4 1 2 4 8
|
||||
46 32 39 0 5 1 4 1 2 4 8
|
||||
47 25 32 0 25 1 4 1 2 4 8
|
||||
48 25 55 0 17 1 4 1 2 4 8
|
||||
49 48 28 0 18 1 4 1 2 4 8
|
||||
50 56 37 0 10 1 4 1 2 4 8
|
||||
51 20 20 0 0 0 0
|
||||
52 30 40 0 0 0 0
|
||||
53 50 30 0 0 0 0
|
||||
54 60 50 0 0 0 0
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
<parent>
|
||||
<groupId>com.graphhopper</groupId>
|
||||
<artifactId>jsprit</artifactId>
|
||||
<version>1.6.3-SNAPSHOT</version>
|
||||
<version>1.7.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ package com.graphhopper.jsprit.examples;
|
|||
|
||||
|
||||
import com.graphhopper.jsprit.analysis.toolbox.AlgorithmEventsRecorder;
|
||||
import com.graphhopper.jsprit.analysis.toolbox.AlgorithmEventsViewer;
|
||||
import com.graphhopper.jsprit.core.algorithm.PrettyAlgorithmBuilder;
|
||||
import com.graphhopper.jsprit.core.algorithm.SearchStrategy;
|
||||
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||
|
|
@ -116,17 +115,18 @@ public class BuildAlgorithmFromScratch {
|
|||
final VehicleRoutingProblem vrp = vrpBuilder.build();
|
||||
|
||||
VehicleRoutingAlgorithm vra = createAlgorithm(vrp);
|
||||
vra.setMaxIterations(100);
|
||||
vra.setMaxIterations(2000);
|
||||
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");
|
||||
|
||||
// AlgorithmEventsViewer viewer = new AlgorithmEventsViewer();
|
||||
// viewer.setRuinDelay(3);
|
||||
// viewer.setRecreationDelay(1);
|
||||
// viewer.display("output/events.dgs.gz");
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -146,10 +146,11 @@ public class BuildAlgorithmFromScratch {
|
|||
//regret insertion
|
||||
InsertionBuilder iBuilder = new InsertionBuilder(vrp, fleetManager, stateManager, constraintManager);
|
||||
iBuilder.setInsertionStrategy(InsertionBuilder.Strategy.REGRET);
|
||||
iBuilder.setFastRegret(true);
|
||||
RegretInsertionFast regret = (RegretInsertionFast) iBuilder.build();
|
||||
DefaultScorer scoringFunction = new DefaultScorer(vrp);
|
||||
scoringFunction.setDepotDistanceParam(0.2);
|
||||
scoringFunction.setTimeWindowParam(-.2);
|
||||
scoringFunction.setDepotDistanceParam(0.0);
|
||||
scoringFunction.setTimeWindowParam(0.0);
|
||||
regret.setScoringFunction(scoringFunction);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
<parent>
|
||||
<groupId>com.graphhopper</groupId>
|
||||
<artifactId>jsprit</artifactId>
|
||||
<version>1.6.3-SNAPSHOT</version>
|
||||
<version>1.7.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
<parent>
|
||||
<groupId>com.graphhopper</groupId>
|
||||
<artifactId>jsprit</artifactId>
|
||||
<version>1.6.3-SNAPSHOT</version>
|
||||
<version>1.7.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
|||
|
|
@ -701,7 +701,8 @@ public class VrpXMLReader {
|
|||
List<HierarchicalConfiguration> breakTWConfigs = vehicleConfig.configurationsAt("breaks.timeWindows.timeWindow");
|
||||
if (!breakTWConfigs.isEmpty()) {
|
||||
String breakDurationString = vehicleConfig.getString("breaks.duration");
|
||||
Break.Builder current_break = Break.Builder.newInstance(vehicleId);
|
||||
String id = vehicleConfig.getString("breaks.id");
|
||||
Break.Builder current_break = Break.Builder.newInstance(id);
|
||||
current_break.setServiceTime(Double.parseDouble(breakDurationString));
|
||||
for (HierarchicalConfiguration twConfig : breakTWConfigs) {
|
||||
current_break.addTimeWindow(TimeWindow.newInstance(twConfig.getDouble("start"), twConfig.getDouble("end")));
|
||||
|
|
|
|||
|
|
@ -41,9 +41,7 @@ import org.slf4j.LoggerFactory;
|
|||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
|
@ -94,8 +92,36 @@ public class VrpXMLWriter {
|
|||
public void write(String filename) {
|
||||
if (!filename.endsWith(".xml")) filename += ".xml";
|
||||
log.info("write vrp: " + filename);
|
||||
XMLConf xmlConfig = new XMLConf();
|
||||
XMLConf xmlConfig = createXMLConfiguration();
|
||||
|
||||
try {
|
||||
xmlConfig.setFileName(filename);
|
||||
Writer out = new FileWriter(filename);
|
||||
XMLSerializer serializer = new XMLSerializer(out, createOutputFormat());
|
||||
serializer.serialize(xmlConfig.getDocument());
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public OutputStream write() {
|
||||
XMLConf xmlConfig = createXMLConfiguration();
|
||||
OutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
XMLSerializer serializer = new XMLSerializer(out, createOutputFormat());
|
||||
serializer.serialize(xmlConfig.getDocument());
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private XMLConf createXMLConfiguration() {
|
||||
XMLConf xmlConfig = new XMLConf();
|
||||
xmlConfig.setRootElementName("problem");
|
||||
xmlConfig.setAttributeSplittingDisabled(true);
|
||||
xmlConfig.setDelimiterParsingDisabled(true);
|
||||
|
|
@ -123,10 +149,6 @@ public class VrpXMLWriter {
|
|||
writeSolutions(xmlConfig);
|
||||
|
||||
|
||||
OutputFormat format = new OutputFormat();
|
||||
format.setIndenting(true);
|
||||
format.setIndent(5);
|
||||
|
||||
try {
|
||||
Document document = xmlConfig.createDoc();
|
||||
|
||||
|
|
@ -138,17 +160,14 @@ public class VrpXMLWriter {
|
|||
} catch (ConfigurationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
Writer out = new FileWriter(filename);
|
||||
XMLSerializer serializer = new XMLSerializer(out, format);
|
||||
serializer.serialize(xmlConfig.getDocument());
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
return xmlConfig;
|
||||
}
|
||||
|
||||
|
||||
private OutputFormat createOutputFormat() {
|
||||
OutputFormat format = new OutputFormat();
|
||||
format.setIndenting(true);
|
||||
format.setIndent(5);
|
||||
return format;
|
||||
}
|
||||
|
||||
private void writeInitialRoutes(XMLConf xmlConfig) {
|
||||
|
|
@ -203,12 +222,12 @@ public class VrpXMLWriter {
|
|||
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act(" + actCounter + ")[@type]", act.getName());
|
||||
if (act instanceof TourActivity.JobActivity) {
|
||||
Job job = ((TourActivity.JobActivity) act).getJob();
|
||||
if (job instanceof Service) {
|
||||
if (job instanceof Break) {
|
||||
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act(" + actCounter + ").breakId", job.getId());
|
||||
} else if (job instanceof Service) {
|
||||
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act(" + actCounter + ").serviceId", job.getId());
|
||||
} else if (job instanceof Shipment) {
|
||||
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act(" + actCounter + ").shipmentId", job.getId());
|
||||
} else if (job instanceof Break) {
|
||||
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act(" + actCounter + ").breakId", job.getId());
|
||||
} else {
|
||||
throw new IllegalStateException("cannot write solution correctly since job-type is not know. make sure you use either service or shipment, or another writer");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -395,6 +395,7 @@
|
|||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="duration" type="xs:double" minOccurs="1" maxOccurs="1" default="0.0"/>
|
||||
<xs:element name="id" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
|
|
|
|||
|
|
@ -31,9 +31,11 @@ import com.graphhopper.jsprit.core.util.Coordinate;
|
|||
import com.graphhopper.jsprit.core.util.Solutions;
|
||||
import com.graphhopper.jsprit.io.util.TestUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
|
@ -42,77 +44,15 @@ import static org.junit.Assert.*;
|
|||
|
||||
public class VrpXMLWriterTest {
|
||||
|
||||
private String infileName;
|
||||
|
||||
@Before
|
||||
public void doBefore() {
|
||||
infileName = "src/test/resources/infiniteWriterV2Test.xml";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingInfiniteVrp_itWritesCorrectly() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
builder.setFleetSize(VehicleRoutingProblem.FleetSize.INFINITE);
|
||||
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("myVehicle").setStartLocation(TestUtils.loc("loc")).setType(type).build();
|
||||
builder.addVehicle(vehicle);
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingFiniteVrp_itWritesCorrectly() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
builder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE);
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(TestUtils.loc("loc")).setType(type2).build();
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void t() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
builder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE);
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(TestUtils.loc("loc")).setType(type2).build();
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingServices_itWritesThemCorrectly() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(TestUtils.loc("loc")).setType(type2).build();
|
||||
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
|
||||
VehicleRoutingProblem.Builder builder = twoVehicleTypesAndImpls();
|
||||
|
||||
Service s1 = Service.Builder.newInstance("1").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc")).setServiceTime(2.0).build();
|
||||
Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc2")).setServiceTime(4.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
assertEquals(2, readVrp.getJobs().size());
|
||||
|
||||
Service s1_read = (Service) vrp.getJobs().get("1");
|
||||
|
|
@ -128,11 +68,7 @@ public class VrpXMLWriterTest {
|
|||
Service s1 = Service.Builder.newInstance("1").setName("cleaning").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc")).setServiceTime(2.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
Service s1_read = (Service) readVrp.getJobs().get("1");
|
||||
assertTrue(s1_read.getName().equals("cleaning"));
|
||||
}
|
||||
|
|
@ -146,11 +82,7 @@ public class VrpXMLWriterTest {
|
|||
.setDeliveryLocation(TestUtils.loc("del")).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
Shipment s1_read = (Shipment) readVrp.getJobs().get("1");
|
||||
assertTrue(s1_read.getName().equals("cleaning"));
|
||||
Assert.assertEquals(1, s1_read.getPickupLocation().getIndex());
|
||||
|
|
@ -167,32 +99,20 @@ public class VrpXMLWriterTest {
|
|||
Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc2")).setServiceTime(4.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
assertEquals(2, readVrp.getJobs().size());
|
||||
|
||||
Service s1_read = (Service) vrp.getJobs().get("1");
|
||||
|
||||
Assert.assertEquals(2, s1_read.getSize().getNuOfDimensions());
|
||||
Assert.assertEquals(20, s1_read.getSize().get(0));
|
||||
Assert.assertEquals(200, s1_read.getSize().get(1));
|
||||
assertEquals(2, s1_read.getSize().getNuOfDimensions());
|
||||
assertEquals(20, s1_read.getSize().get(0));
|
||||
assertEquals(200, s1_read.getSize().get(1));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingShipments_readingThemAgainMustReturnTheWrittenLocationIdsOfS1() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(TestUtils.loc("loc")).setType(type2).build();
|
||||
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
VehicleRoutingProblem.Builder builder = twoVehicleTypesAndImpls();
|
||||
|
||||
Shipment s1 = Shipment.Builder.newInstance("1").addSizeDimension(0, 10)
|
||||
.setPickupLocation(Location.Builder.newInstance().setId("pickLoc").build())
|
||||
|
|
@ -205,29 +125,17 @@ public class VrpXMLWriterTest {
|
|||
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
assertEquals(2, readVrp.getJobs().size());
|
||||
|
||||
Assert.assertEquals("pickLoc", ((Shipment) readVrp.getJobs().get("1")).getPickupLocation().getId());
|
||||
Assert.assertEquals("delLoc", ((Shipment) readVrp.getJobs().get("1")).getDeliveryLocation().getId());
|
||||
assertEquals("pickLoc", ((Shipment) readVrp.getJobs().get("1")).getPickupLocation().getId());
|
||||
assertEquals("delLoc", ((Shipment) readVrp.getJobs().get("1")).getDeliveryLocation().getId());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingShipments_readingThemAgainMustReturnTheWrittenPickupTimeWindowsOfS1() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(TestUtils.loc("loc")).setType(type2).build();
|
||||
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
VehicleRoutingProblem.Builder builder = twoVehicleTypesAndImpls();
|
||||
|
||||
Shipment s1 = Shipment.Builder.newInstance("1").addSizeDimension(0, 10)
|
||||
.setPickupLocation(Location.Builder.newInstance().setId("pickLoc").build())
|
||||
|
|
@ -240,30 +148,18 @@ public class VrpXMLWriterTest {
|
|||
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
assertEquals(2, readVrp.getJobs().size());
|
||||
|
||||
Assert.assertEquals(1.0, ((Shipment) readVrp.getJobs().get("1")).getPickupTimeWindow().getStart(), 0.01);
|
||||
Assert.assertEquals(2.0, ((Shipment) readVrp.getJobs().get("1")).getPickupTimeWindow().getEnd(), 0.01);
|
||||
assertEquals(1.0, ((Shipment) readVrp.getJobs().get("1")).getPickupTimeWindow().getStart(), 0.01);
|
||||
assertEquals(2.0, ((Shipment) readVrp.getJobs().get("1")).getPickupTimeWindow().getEnd(), 0.01);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingShipments_readingThemAgainMustReturnTheWrittenDeliveryTimeWindowsOfS1() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(TestUtils.loc("loc")).setType(type2).build();
|
||||
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
VehicleRoutingProblem.Builder builder = twoVehicleTypesAndImpls();
|
||||
|
||||
Shipment s1 = Shipment.Builder.newInstance("1").addSizeDimension(0, 10)
|
||||
.setPickupLocation(Location.Builder.newInstance().setId("pickLoc").build())
|
||||
|
|
@ -276,29 +172,17 @@ public class VrpXMLWriterTest {
|
|||
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
assertEquals(2, readVrp.getJobs().size());
|
||||
|
||||
Assert.assertEquals(3.0, ((Shipment) readVrp.getJobs().get("1")).getDeliveryTimeWindow().getStart(), 0.01);
|
||||
Assert.assertEquals(4.0, ((Shipment) readVrp.getJobs().get("1")).getDeliveryTimeWindow().getEnd(), 0.01);
|
||||
assertEquals(3.0, ((Shipment) readVrp.getJobs().get("1")).getDeliveryTimeWindow().getStart(), 0.01);
|
||||
assertEquals(4.0, ((Shipment) readVrp.getJobs().get("1")).getDeliveryTimeWindow().getEnd(), 0.01);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingShipments_readingThemAgainMustReturnTheWrittenDeliveryServiceTimeOfS1() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(TestUtils.loc("loc")).setType(type2).build();
|
||||
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
VehicleRoutingProblem.Builder builder = twoVehicleTypesAndImpls();
|
||||
|
||||
Shipment s1 = Shipment.Builder.newInstance("1").addSizeDimension(0, 10)
|
||||
.setPickupLocation(Location.Builder.newInstance().setId("pickLoc").build())
|
||||
|
|
@ -311,11 +195,7 @@ public class VrpXMLWriterTest {
|
|||
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
assertEquals(2, readVrp.getJobs().size());
|
||||
|
||||
assertEquals(100.0, ((Shipment) readVrp.getJobs().get("1")).getPickupServiceTime(), 0.01);
|
||||
|
|
@ -325,15 +205,7 @@ public class VrpXMLWriterTest {
|
|||
|
||||
@Test
|
||||
public void whenWritingShipments_readingThemAgainMustReturnTheWrittenLocationIdOfS1() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(TestUtils.loc("loc")).setType(type2).build();
|
||||
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
VehicleRoutingProblem.Builder builder = twoVehicleTypesAndImpls();
|
||||
|
||||
Shipment s1 = Shipment.Builder.newInstance("1").addSizeDimension(0, 10)
|
||||
.setPickupLocation(TestUtils.loc(Coordinate.newInstance(1, 2))).setDeliveryLocation(TestUtils.loc("delLoc")).setPickupTimeWindow(TimeWindow.newInstance(1, 2))
|
||||
|
|
@ -345,18 +217,14 @@ public class VrpXMLWriterTest {
|
|||
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
assertEquals(2, readVrp.getJobs().size());
|
||||
|
||||
Assert.assertEquals("[x=1.0][y=2.0]", ((Shipment) readVrp.getJobs().get("1")).getPickupLocation().getId());
|
||||
assertEquals("[x=1.0][y=2.0]", ((Shipment) readVrp.getJobs().get("1")).getPickupLocation().getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingVehicles_vehShouldHave2Skills() {
|
||||
public void whenWritingVehicles_vehShouldHave3Skills() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleImpl v = VehicleImpl.Builder.newInstance("v1").addSkill("SKILL5").addSkill("skill1").addSkill("Skill2")
|
||||
|
|
@ -364,70 +232,12 @@ public class VrpXMLWriterTest {
|
|||
builder.addVehicle(v);
|
||||
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
Vehicle veh1 = getVehicle("v1", readVrp);
|
||||
|
||||
Assert.assertEquals(3, veh1.getSkills().values().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingVehicles_vehShouldContain_skill5() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleImpl v = VehicleImpl.Builder.newInstance("v1").addSkill("SKILL5").addSkill("skill1").addSkill("Skill2")
|
||||
.setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
builder.addVehicle(v);
|
||||
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
Vehicle veh1 = getVehicle("v1", readVrp);
|
||||
|
||||
assertEquals(3, veh1.getSkills().values().size());
|
||||
assertTrue(veh1.getSkills().containsSkill("skill5"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingVehicles_vehShouldContain_skill1() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleImpl v = VehicleImpl.Builder.newInstance("v1").addSkill("SKILL5").addSkill("skill1").addSkill("Skill2")
|
||||
.setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
builder.addVehicle(v);
|
||||
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
Vehicle veh1 = getVehicle("v1", readVrp);
|
||||
|
||||
assertTrue(veh1.getSkills().containsSkill("skill1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingVehicles_vehShouldContain_skill2() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleImpl v = VehicleImpl.Builder.newInstance("v1").addSkill("SKILL5").addSkill("skill1").addSkill("Skill2")
|
||||
.setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
builder.addVehicle(v);
|
||||
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
Vehicle veh1 = getVehicle("v1", readVrp);
|
||||
|
||||
assertTrue(veh1.getSkills().containsSkill("skill2"));
|
||||
}
|
||||
|
||||
|
|
@ -439,14 +249,10 @@ public class VrpXMLWriterTest {
|
|||
builder.addVehicle(v);
|
||||
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
Vehicle veh = getVehicle("v1", readVrp);
|
||||
|
||||
Assert.assertEquals(0, veh.getSkills().values().size());
|
||||
assertEquals(0, veh.getSkills().values().size());
|
||||
}
|
||||
|
||||
private Vehicle getVehicle(String v1, VehicleRoutingProblem readVrp) {
|
||||
|
|
@ -468,89 +274,17 @@ public class VrpXMLWriterTest {
|
|||
.setDeliveryTimeWindow(TimeWindow.newInstance(3, 4)).setPickupServiceTime(100).setDeliveryServiceTime(50).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
|
||||
Assert.assertEquals(3, readVrp.getJobs().get("1").getRequiredSkills().values().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingShipments_shipmentShouldContain_skill1() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
Shipment s = Shipment.Builder.newInstance("1").addRequiredSkill("skill1").addRequiredSkill("skill2").addRequiredSkill("skill3")
|
||||
.addSizeDimension(0, 10)
|
||||
.setPickupLocation(TestUtils.loc(Coordinate.newInstance(1, 2)))
|
||||
.setDeliveryLocation(TestUtils.loc("delLoc", Coordinate.newInstance(5, 6)))
|
||||
.setPickupTimeWindow(TimeWindow.newInstance(1, 2))
|
||||
.setDeliveryTimeWindow(TimeWindow.newInstance(3, 4)).setPickupServiceTime(100).setDeliveryServiceTime(50).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
|
||||
assertEquals(3, readVrp.getJobs().get("1").getRequiredSkills().values().size());
|
||||
assertTrue(readVrp.getJobs().get("1").getRequiredSkills().containsSkill("skill1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingShipments_shipmentShouldContain_skill2() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
Shipment s = Shipment.Builder.newInstance("1").addRequiredSkill("skill1").addRequiredSkill("Skill2").addRequiredSkill("skill3")
|
||||
.addSizeDimension(0, 10)
|
||||
.setPickupLocation(TestUtils.loc(Coordinate.newInstance(1, 2)))
|
||||
.setDeliveryLocation(TestUtils.loc("delLoc", Coordinate.newInstance(5, 6)))
|
||||
.setPickupTimeWindow(TimeWindow.newInstance(1, 2))
|
||||
.setDeliveryTimeWindow(TimeWindow.newInstance(3, 4)).setPickupServiceTime(100).setDeliveryServiceTime(50).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
|
||||
assertTrue(readVrp.getJobs().get("1").getRequiredSkills().containsSkill("skill2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingShipments_shipmentShouldContain_skill3() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
Shipment s = Shipment.Builder.newInstance("1").addRequiredSkill("skill1").addRequiredSkill("Skill2").addRequiredSkill("skill3")
|
||||
.addSizeDimension(0, 10)
|
||||
.setPickupLocation(TestUtils.loc(Coordinate.newInstance(1, 2)))
|
||||
.setDeliveryLocation(TestUtils.loc("delLoc", Coordinate.newInstance(5, 6)))
|
||||
.setPickupTimeWindow(TimeWindow.newInstance(1, 2))
|
||||
.setDeliveryTimeWindow(TimeWindow.newInstance(3, 4)).setPickupServiceTime(100).setDeliveryServiceTime(50).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
|
||||
assertTrue(readVrp.getJobs().get("1").getRequiredSkills().containsSkill("skill3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingShipments_readingThemAgainMustReturnTheWrittenLocationCoordinateOfS1() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(TestUtils.loc("loc")).setType(type2).build();
|
||||
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
VehicleRoutingProblem.Builder builder = twoVehicleTypesAndImpls();
|
||||
|
||||
Shipment s1 = Shipment.Builder.newInstance("1").addSizeDimension(0, 10).setPickupLocation(TestUtils.loc(Coordinate.newInstance(1, 2)))
|
||||
.setDeliveryLocation(TestUtils.loc("delLoc", Coordinate.newInstance(5, 6)))
|
||||
|
|
@ -564,18 +298,14 @@ public class VrpXMLWriterTest {
|
|||
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
assertEquals(2, readVrp.getJobs().size());
|
||||
|
||||
Assert.assertEquals(1.0, ((Shipment) readVrp.getJobs().get("1")).getPickupLocation().getCoordinate().getX(), 0.01);
|
||||
Assert.assertEquals(2.0, ((Shipment) readVrp.getJobs().get("1")).getPickupLocation().getCoordinate().getY(), 0.01);
|
||||
assertEquals(1.0, ((Shipment) readVrp.getJobs().get("1")).getPickupLocation().getCoordinate().getX(), 0.01);
|
||||
assertEquals(2.0, ((Shipment) readVrp.getJobs().get("1")).getPickupLocation().getCoordinate().getY(), 0.01);
|
||||
|
||||
Assert.assertEquals(5.0, ((Shipment) readVrp.getJobs().get("1")).getDeliveryLocation().getCoordinate().getX(), 0.01);
|
||||
Assert.assertEquals(6.0, ((Shipment) readVrp.getJobs().get("1")).getDeliveryLocation().getCoordinate().getY(), 0.01);
|
||||
assertEquals(5.0, ((Shipment) readVrp.getJobs().get("1")).getDeliveryLocation().getCoordinate().getX(), 0.01);
|
||||
assertEquals(6.0, ((Shipment) readVrp.getJobs().get("1")).getDeliveryLocation().getCoordinate().getY(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -597,23 +327,34 @@ public class VrpXMLWriterTest {
|
|||
.setDeliveryTimeWindow(TimeWindow.newInstance(7, 8)).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
assertEquals(3, (readVrp.getJobs().get("1")).getSize().getNuOfDimensions());
|
||||
assertEquals(10, (readVrp.getJobs().get("1")).getSize().get(0));
|
||||
assertEquals(0, (readVrp.getJobs().get("1")).getSize().get(1));
|
||||
assertEquals(100, (readVrp.getJobs().get("1")).getSize().get(2));
|
||||
|
||||
Assert.assertEquals(3, (readVrp.getJobs().get("1")).getSize().getNuOfDimensions());
|
||||
Assert.assertEquals(10, (readVrp.getJobs().get("1")).getSize().get(0));
|
||||
Assert.assertEquals(0, (readVrp.getJobs().get("1")).getSize().get(1));
|
||||
Assert.assertEquals(100, (readVrp.getJobs().get("1")).getSize().get(2));
|
||||
|
||||
Assert.assertEquals(1, (readVrp.getJobs().get("2")).getSize().getNuOfDimensions());
|
||||
Assert.assertEquals(20, (readVrp.getJobs().get("2")).getSize().get(0));
|
||||
assertEquals(1, (readVrp.getJobs().get("2")).getSize().getNuOfDimensions());
|
||||
assertEquals(20, (readVrp.getJobs().get("2")).getSize().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingVehicleV1_itsStartLocationMustBeWrittenCorrectly() {
|
||||
VehicleRoutingProblem.Builder builder = twoVehicleTypesAndImpls();
|
||||
|
||||
Service s1 = Service.Builder.newInstance("1").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc")).setServiceTime(2.0).build();
|
||||
Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc2")).setServiceTime(4.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
|
||||
Vehicle v = getVehicle("v1", readVrp.getVehicles());
|
||||
assertEquals("loc", v.getStartLocation().getId());
|
||||
assertEquals("loc", v.getEndLocation().getId());
|
||||
|
||||
}
|
||||
|
||||
private VehicleRoutingProblem.Builder twoVehicleTypesAndImpls() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
|
|
@ -623,74 +364,27 @@ public class VrpXMLWriterTest {
|
|||
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
|
||||
Service s1 = Service.Builder.newInstance("1").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc")).setServiceTime(2.0).build();
|
||||
Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc2")).setServiceTime(4.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
|
||||
Vehicle v = getVehicle("v1", readVrp.getVehicles());
|
||||
Assert.assertEquals("loc", v.getStartLocation().getId());
|
||||
Assert.assertEquals("loc", v.getEndLocation().getId());
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingService_itShouldHaveTheCorrectNuSkills() {
|
||||
public void whenWritingService_itShouldContain_bothSkills() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
Service s = Service.Builder.newInstance("1").addRequiredSkill("sKill1").addRequiredSkill("skill2").addSizeDimension(0, 1)
|
||||
//skill names are case-insensitive
|
||||
Service s = Service.Builder.newInstance("1").addRequiredSkill("skill1").addRequiredSkill("SKILL2").addSizeDimension(0, 1)
|
||||
.setLocation(TestUtils.loc("loc")).setServiceTime(2.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
|
||||
Assert.assertEquals(2, readVrp.getJobs().get("1").getRequiredSkills().values().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingService_itShouldContain_skill1() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
Service s = Service.Builder.newInstance("1").addRequiredSkill("sKill1").addRequiredSkill("skill2").addSizeDimension(0, 1)
|
||||
.setLocation(TestUtils.loc("loc")).setServiceTime(2.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
|
||||
assertEquals(2, readVrp.getJobs().get("1").getRequiredSkills().values().size());
|
||||
assertTrue(readVrp.getJobs().get("1").getRequiredSkills().containsSkill("skill1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingService_itShouldContain_skill2() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
Service s = Service.Builder.newInstance("1").addRequiredSkill("sKill1").addRequiredSkill("skill2").addSizeDimension(0, 1)
|
||||
.setLocation(TestUtils.loc("loc")).setServiceTime(2.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
|
||||
assertTrue(readVrp.getJobs().get("1").getRequiredSkills().containsSkill("skill2"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenWritingVehicleV1_itDoesNotReturnToDepotMustBeWrittenCorrectly() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
|
@ -708,11 +402,7 @@ public class VrpXMLWriterTest {
|
|||
Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc2")).setServiceTime(4.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
|
||||
Vehicle v = getVehicle("v1", readVrp.getVehicles());
|
||||
assertFalse(v.isReturnToDepot());
|
||||
|
|
@ -734,11 +424,7 @@ public class VrpXMLWriterTest {
|
|||
Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc2")).setServiceTime(4.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
|
||||
Vehicle v = getVehicle("v1", readVrp.getVehicles());
|
||||
assertEquals("vehType", v.getType().getTypeId());
|
||||
|
|
@ -760,15 +446,11 @@ public class VrpXMLWriterTest {
|
|||
Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc2")).setServiceTime(4.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
|
||||
Vehicle v = getVehicle("v2", readVrp.getVehicles());
|
||||
assertEquals("vehType2", v.getType().getTypeId());
|
||||
Assert.assertEquals(200, v.getType().getCapacityDimensions().get(0));
|
||||
assertEquals(200, v.getType().getCapacityDimensions().get(0));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -776,35 +458,6 @@ public class VrpXMLWriterTest {
|
|||
public void whenWritingVehicleV2_readingItsLocationsAgainReturnsCorrectLocations() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setReturnToDepot(false).setStartLocation(TestUtils.loc("loc")).setType(type1).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2")
|
||||
.setStartLocation(TestUtils.loc("startLoc", Coordinate.newInstance(1, 2)))
|
||||
.setEndLocation(TestUtils.loc("endLoc", Coordinate.newInstance(4, 5))).setType(type2).build();
|
||||
|
||||
builder.addVehicle(v1);
|
||||
builder.addVehicle(v2);
|
||||
|
||||
Service s1 = Service.Builder.newInstance("1").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc")).setServiceTime(2.0).build();
|
||||
Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc2")).setServiceTime(4.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
|
||||
Vehicle v = getVehicle("v2", readVrp.getVehicles());
|
||||
Assert.assertEquals("startLoc", v.getStartLocation().getId());
|
||||
Assert.assertEquals("endLoc", v.getEndLocation().getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWritingVehicleV2_readingItsLocationsCoordsAgainReturnsCorrectLocationsCoords() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
||||
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build();
|
||||
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2").addCapacityDimension(0, 200).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setReturnToDepot(false)
|
||||
|
|
@ -820,20 +473,18 @@ public class VrpXMLWriterTest {
|
|||
Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(TestUtils.loc("loc2")).setServiceTime(4.0).build();
|
||||
|
||||
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
|
||||
Vehicle v = getVehicle("v2", readVrp.getVehicles());
|
||||
Assert.assertEquals(1.0, v.getStartLocation().getCoordinate().getX(), 0.01);
|
||||
Assert.assertEquals(2.0, v.getStartLocation().getCoordinate().getY(), 0.01);
|
||||
|
||||
Assert.assertEquals(4.0, v.getEndLocation().getCoordinate().getX(), 0.01);
|
||||
Assert.assertEquals(5.0, v.getEndLocation().getCoordinate().getY(), 0.01);
|
||||
assertEquals("startLoc", v.getStartLocation().getId());
|
||||
assertEquals("endLoc", v.getEndLocation().getId());
|
||||
assertEquals(1.0, v.getStartLocation().getCoordinate().getX(), 0.01);
|
||||
assertEquals(2.0, v.getStartLocation().getCoordinate().getY(), 0.01);
|
||||
assertEquals(4.0, v.getEndLocation().getCoordinate().getX(), 0.01);
|
||||
assertEquals(5.0, v.getEndLocation().getCoordinate().getY(), 0.01);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenWritingVehicleWithSeveralCapacityDimensions_itShouldBeWrittenAndRereadCorrectly() {
|
||||
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
|
||||
|
|
@ -850,17 +501,13 @@ public class VrpXMLWriterTest {
|
|||
builder.addVehicle(v2);
|
||||
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
|
||||
Vehicle v = getVehicle("v", readVrp.getVehicles());
|
||||
Assert.assertEquals(3, v.getType().getCapacityDimensions().getNuOfDimensions());
|
||||
Assert.assertEquals(100, v.getType().getCapacityDimensions().get(0));
|
||||
Assert.assertEquals(1000, v.getType().getCapacityDimensions().get(1));
|
||||
Assert.assertEquals(10000, v.getType().getCapacityDimensions().get(2));
|
||||
assertEquals(3, v.getType().getCapacityDimensions().getNuOfDimensions());
|
||||
assertEquals(100, v.getType().getCapacityDimensions().get(0));
|
||||
assertEquals(1000, v.getType().getCapacityDimensions().get(1));
|
||||
assertEquals(10000, v.getType().getCapacityDimensions().get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -879,16 +526,12 @@ public class VrpXMLWriterTest {
|
|||
builder.addVehicle(v2);
|
||||
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
new VrpXMLWriter(vrp, null).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
|
||||
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
|
||||
VehicleRoutingProblem readVrp = writeAndRereadXml(vrp);
|
||||
|
||||
Vehicle v = getVehicle("v", readVrp.getVehicles());
|
||||
Assert.assertEquals(11, v.getType().getCapacityDimensions().getNuOfDimensions());
|
||||
Assert.assertEquals(0, v.getType().getCapacityDimensions().get(9));
|
||||
Assert.assertEquals(10000, v.getType().getCapacityDimensions().get(10));
|
||||
assertEquals(11, v.getType().getCapacityDimensions().getNuOfDimensions());
|
||||
assertEquals(0, v.getType().getCapacityDimensions().get(9));
|
||||
assertEquals(10000, v.getType().getCapacityDimensions().get(10));
|
||||
}
|
||||
|
||||
private Vehicle getVehicle(String string, Collection<Vehicle> vehicles) {
|
||||
|
|
@ -916,14 +559,10 @@ public class VrpXMLWriterTest {
|
|||
List<VehicleRoutingProblemSolution> solutions = new ArrayList<VehicleRoutingProblemSolution>();
|
||||
solutions.add(solution);
|
||||
|
||||
new VrpXMLWriter(vrp, solutions).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
List<VehicleRoutingProblemSolution> solutionsToRead = new ArrayList<VehicleRoutingProblemSolution>();
|
||||
new VrpXMLReader(vrpToReadBuilder, solutionsToRead).read(infileName);
|
||||
List<VehicleRoutingProblemSolution> solutionsToRead = writeAndRereadXmlWithSolutions(vrp, solutions);
|
||||
|
||||
assertEquals(1, solutionsToRead.size());
|
||||
Assert.assertEquals(10., Solutions.bestOf(solutionsToRead).getCost(), 0.01);
|
||||
assertEquals(10., Solutions.bestOf(solutionsToRead).getCost(), 0.01);
|
||||
assertTrue(Solutions.bestOf(solutionsToRead).getUnassignedJobs().isEmpty());
|
||||
}
|
||||
|
||||
|
|
@ -948,16 +587,46 @@ public class VrpXMLWriterTest {
|
|||
List<VehicleRoutingProblemSolution> solutions = new ArrayList<VehicleRoutingProblemSolution>();
|
||||
solutions.add(solution);
|
||||
|
||||
new VrpXMLWriter(vrp, solutions).write(infileName);
|
||||
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
List<VehicleRoutingProblemSolution> solutionsToRead = new ArrayList<VehicleRoutingProblemSolution>();
|
||||
new VrpXMLReader(vrpToReadBuilder, solutionsToRead).read(infileName);
|
||||
List<VehicleRoutingProblemSolution> solutionsToRead = writeAndRereadXmlWithSolutions(vrp, solutions);
|
||||
|
||||
assertEquals(1, solutionsToRead.size());
|
||||
Assert.assertEquals(10., Solutions.bestOf(solutionsToRead).getCost(), 0.01);
|
||||
Assert.assertEquals(1, Solutions.bestOf(solutionsToRead).getUnassignedJobs().size());
|
||||
Assert.assertEquals("2", Solutions.bestOf(solutionsToRead).getUnassignedJobs().iterator().next().getId());
|
||||
assertEquals(10., Solutions.bestOf(solutionsToRead).getCost(), 0.01);
|
||||
assertEquals(1, Solutions.bestOf(solutionsToRead).getUnassignedJobs().size());
|
||||
assertEquals("2", Solutions.bestOf(solutionsToRead).getUnassignedJobs().iterator().next().getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void outputStreamAndFileContentsAreEqual() throws IOException {
|
||||
VehicleRoutingProblem.Builder builder = twoVehicleTypesAndImpls();
|
||||
VehicleRoutingProblem vrp = builder.build();
|
||||
|
||||
VrpXMLWriter vrpXMLWriter = new VrpXMLWriter(vrp, null);
|
||||
ByteArrayOutputStream os = (ByteArrayOutputStream) vrpXMLWriter.write();
|
||||
|
||||
String outputStringFromFile = new String(os.toByteArray());
|
||||
String outputStringFromStream = new VrpXMLWriter(vrp, null).write().toString();
|
||||
|
||||
assertEquals(outputStringFromFile, outputStringFromStream);
|
||||
|
||||
}
|
||||
|
||||
private VehicleRoutingProblem writeAndRereadXml(VehicleRoutingProblem vrp) {
|
||||
VrpXMLWriter vrpXMLWriter = new VrpXMLWriter(vrp, null);
|
||||
ByteArrayOutputStream os = (ByteArrayOutputStream) vrpXMLWriter.write();
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
new VrpXMLReader(vrpToReadBuilder, null).read(is);
|
||||
return vrpToReadBuilder.build();
|
||||
}
|
||||
|
||||
private List<VehicleRoutingProblemSolution> writeAndRereadXmlWithSolutions(VehicleRoutingProblem vrp, List<VehicleRoutingProblemSolution> solutions) {
|
||||
VrpXMLWriter vrpXMLWriter = new VrpXMLWriter(vrp, solutions);
|
||||
ByteArrayOutputStream os = (ByteArrayOutputStream) vrpXMLWriter.write();
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
List<VehicleRoutingProblemSolution> solutionsToRead = new ArrayList<VehicleRoutingProblemSolution>();
|
||||
new VrpXMLReader(vrpToReadBuilder, solutionsToRead).read(is);
|
||||
return solutionsToRead;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
20
pom.xml
20
pom.xml
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
<groupId>com.graphhopper</groupId>
|
||||
<artifactId>jsprit</artifactId>
|
||||
<version>1.6.3-SNAPSHOT</version>
|
||||
<version>1.7.3-SNAPSHOT</version>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
|
@ -56,6 +56,7 @@
|
|||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
|
||||
<issueManagement>
|
||||
<system>github</system>
|
||||
<url>https://github.com/graphhopper/jsprit/issues</url>
|
||||
|
|
@ -81,6 +82,15 @@
|
|||
</properties>
|
||||
|
||||
<build>
|
||||
|
||||
<extensions>
|
||||
<extension>
|
||||
<groupId>io.packagecloud.maven.wagon</groupId>
|
||||
<artifactId>maven-packagecloud-wagon</artifactId>
|
||||
<version>0.0.4</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<testSourceDirectory>src/test/java</testSourceDirectory>
|
||||
<directory>target</directory>
|
||||
|
|
@ -180,9 +190,13 @@
|
|||
</dependencies>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>packagecloud-graphhopper</id>
|
||||
<url>packagecloud+https://packagecloud.io/graphhopper/jsprit</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
<id>packagecloud-graphhopper</id>
|
||||
<url>packagecloud+https://packagecloud.io/graphhopper/jsprit</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue