mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
Merge branch 'merge-exp-time-scheduling'
This commit is contained in:
commit
98a682077d
8 changed files with 209 additions and 125 deletions
|
|
@ -117,9 +117,11 @@ final class BestInsertion implements InsertionStrategy{
|
|||
}
|
||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
||||
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||
if(newIData.getInsertionCost() < bestInsertionCost){
|
||||
bestInsertion = new Insertion(newRoute,newIData);
|
||||
vehicleRoutes.add(newRoute);
|
||||
if(!(newIData instanceof NoInsertionFound)){
|
||||
if(newIData.getInsertionCost() < bestInsertionCost){
|
||||
bestInsertion = new Insertion(newRoute,newIData);
|
||||
vehicleRoutes.add(newRoute);
|
||||
}
|
||||
}
|
||||
if(bestInsertion == null) badJobs.add(unassignedJob);
|
||||
else inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||
|
|
|
|||
|
|
@ -1,93 +1,78 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2013 Stefan Schroeder
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
|
||||
import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
|
||||
import jsprit.core.problem.driver.Driver;
|
||||
import jsprit.core.problem.job.Job;
|
||||
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import jsprit.core.problem.vehicle.Vehicle;
|
||||
import jsprit.core.util.RandomNumberGeneration;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator{
|
||||
|
||||
|
||||
private static Logger log = LogManager.getLogger(CalculatesServiceInsertionWithTimeScheduling.class);
|
||||
|
||||
private JobInsertionCostsCalculator jic;
|
||||
|
||||
// private Random random = new Random();
|
||||
|
||||
private int nOfDepartureTimes = 3;
|
||||
|
||||
private double timeSlice = 900.0;
|
||||
|
||||
public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCostsCalculator jic, double timeSlice, int neighbors) {
|
||||
super();
|
||||
this.jic = jic;
|
||||
this.timeSlice = timeSlice;
|
||||
this.nOfDepartureTimes = neighbors;
|
||||
log.info("initialise " + this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertionWithTimeScheduling][timeSlice="+timeSlice+"][#timeSlice="+nOfDepartureTimes+"]";
|
||||
}
|
||||
public static class KnowledgeInjection implements InsertionStartsListener {
|
||||
private CalculatesServiceInsertionWithTimeScheduling c;
|
||||
public KnowledgeInjection(CalculatesServiceInsertionWithTimeScheduling c) {
|
||||
super();
|
||||
this.c = c;
|
||||
}
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes,Collection<Job> unassignedJobs) {
|
||||
List<Double> knowledge = new ArrayList<Double>();
|
||||
if(vehicleRoutes.isEmpty()){
|
||||
// System.out.println("hmm");
|
||||
}
|
||||
for(VehicleRoute route : vehicleRoutes){
|
||||
// if(route.getDepartureTime() == 21600.){
|
||||
// System.out.println("hu");
|
||||
// }
|
||||
knowledge.add(route.getDepartureTime());
|
||||
}
|
||||
c.setDepartureTimeKnowledge(knowledge);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
|
||||
List<Double> vehicleDepartureTimes = new ArrayList<Double>();
|
||||
double currentStart;
|
||||
if(currentRoute.getStart() == null){
|
||||
currentStart = newVehicleDepartureTime;
|
||||
}
|
||||
else currentStart = currentRoute.getStart().getEndTime();
|
||||
|
||||
vehicleDepartureTimes.add(currentStart);
|
||||
// double earliestDeparture = newVehicle.getEarliestDeparture();
|
||||
// double latestEnd = newVehicle.getLatestArrival();
|
||||
|
||||
for(int i=0;i<nOfDepartureTimes;i++){
|
||||
double neighborStartTime_earlier = currentStart - (i+1)*timeSlice;
|
||||
// if(neighborStartTime_earlier > earliestDeparture) {
|
||||
vehicleDepartureTimes.add(neighborStartTime_earlier);
|
||||
// }
|
||||
double neighborStartTime_later = currentStart + (i+1)*timeSlice;
|
||||
// if(neighborStartTime_later < latestEnd) {
|
||||
vehicleDepartureTimes.add(neighborStartTime_later);
|
||||
// }
|
||||
}
|
||||
|
||||
InsertionData bestIData = null;
|
||||
for(Double departureTime : vehicleDepartureTimes){
|
||||
InsertionData iData = jic.getInsertionData(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
|
||||
if(bestIData == null) bestIData = iData;
|
||||
else if(iData.getInsertionCost() < bestIData.getInsertionCost()){
|
||||
iData.setVehicleDepartureTime(departureTime);
|
||||
bestIData = iData;
|
||||
}
|
||||
}
|
||||
// log.info(bestIData);
|
||||
return bestIData;
|
||||
}
|
||||
private static Logger log = LogManager.getLogger(CalculatesServiceInsertionWithTimeScheduling.class);
|
||||
|
||||
private JobInsertionCostsCalculator jic;
|
||||
|
||||
private List<Double> departureTimeKnowledge = new ArrayList<Double>();
|
||||
|
||||
CalculatesServiceInsertionWithTimeScheduling(JobInsertionCostsCalculator jic, double t, double f) {
|
||||
super();
|
||||
this.jic = jic;
|
||||
log.info("initialise " + this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name="+this.getClass().toString()+"]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
|
||||
double departureTime = newVehicleDepartureTime;
|
||||
if(currentRoute.isEmpty()){
|
||||
if(!departureTimeKnowledge.isEmpty()){
|
||||
departureTime = departureTimeKnowledge.get(RandomNumberGeneration.getRandom().nextInt(departureTimeKnowledge.size()));
|
||||
}
|
||||
}
|
||||
|
||||
InsertionData insertionData = jic.getInsertionData(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
|
||||
// if(!(insertionData instanceof NoInsertionFound) && insertionData.getVehicleDepartureTime() < 28000){
|
||||
// System.out.println("hmm");
|
||||
// }
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
public void setDepartureTimeKnowledge(List<Double> departureTimes){
|
||||
departureTimeKnowledge=departureTimes;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2013 Stefan Schroeder
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
||||
import jsprit.core.problem.driver.Driver;
|
||||
import jsprit.core.problem.job.Job;
|
||||
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import jsprit.core.problem.vehicle.Vehicle;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
class CalculatesServiceInsertionWithTimeSchedulingInSlices implements JobInsertionCostsCalculator{
|
||||
|
||||
|
||||
private static Logger log = LogManager.getLogger(CalculatesServiceInsertionWithTimeSchedulingInSlices.class);
|
||||
|
||||
private JobInsertionCostsCalculator jic;
|
||||
|
||||
private int nOfDepartureTimes = 3;
|
||||
|
||||
private double timeSlice = 900.0;
|
||||
|
||||
public CalculatesServiceInsertionWithTimeSchedulingInSlices(JobInsertionCostsCalculator jic, double timeSlice, int neighbors) {
|
||||
super();
|
||||
this.jic = jic;
|
||||
this.timeSlice = timeSlice;
|
||||
this.nOfDepartureTimes = neighbors;
|
||||
log.info("initialise " + this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name="+this.getClass().toString()+"][timeSlice="+timeSlice+"][#timeSlice="+nOfDepartureTimes+"]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
|
||||
List<Double> vehicleDepartureTimes = new ArrayList<Double>();
|
||||
double currentStart;
|
||||
if(currentRoute.getStart() == null){
|
||||
currentStart = newVehicleDepartureTime;
|
||||
}
|
||||
else currentStart = currentRoute.getStart().getEndTime();
|
||||
|
||||
vehicleDepartureTimes.add(currentStart);
|
||||
// double earliestDeparture = newVehicle.getEarliestDeparture();
|
||||
// double latestEnd = newVehicle.getLatestArrival();
|
||||
|
||||
for(int i=0;i<nOfDepartureTimes;i++){
|
||||
double neighborStartTime_earlier = currentStart - (i+1)*timeSlice;
|
||||
// if(neighborStartTime_earlier > earliestDeparture) {
|
||||
vehicleDepartureTimes.add(neighborStartTime_earlier);
|
||||
// }
|
||||
double neighborStartTime_later = currentStart + (i+1)*timeSlice;
|
||||
// if(neighborStartTime_later < latestEnd) {
|
||||
vehicleDepartureTimes.add(neighborStartTime_later);
|
||||
// }
|
||||
}
|
||||
|
||||
InsertionData bestIData = null;
|
||||
for(Double departureTime : vehicleDepartureTimes){
|
||||
InsertionData iData = jic.getInsertionData(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
|
||||
if(bestIData == null) bestIData = iData;
|
||||
else if(iData.getInsertionCost() < bestIData.getInsertionCost()){
|
||||
iData.setVehicleDepartureTime(departureTime);
|
||||
bestIData = iData;
|
||||
}
|
||||
}
|
||||
// log.info(bestIData);
|
||||
return bestIData;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -217,7 +217,12 @@ class CalculatorBuilder {
|
|||
addInsertionListeners(withFixed.getInsertionListener());
|
||||
}
|
||||
if(timeScheduling){
|
||||
baseCalculator = new CalculatesServiceInsertionWithTimeScheduling(baseCalculator,timeSlice,neighbors);
|
||||
// baseCalculator = new CalculatesServiceInsertionWithTimeSchedulingInSlices(baseCalculator,timeSlice,neighbors);
|
||||
CalculatesServiceInsertionWithTimeScheduling wts = new CalculatesServiceInsertionWithTimeScheduling(baseCalculator,timeSlice,neighbors);
|
||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(wts);
|
||||
calcPlusListeners.getInsertionListener().add(new CalculatesServiceInsertionWithTimeScheduling.KnowledgeInjection(wts));
|
||||
addInsertionListeners(calcPlusListeners.getInsertionListener());
|
||||
baseCalculator = calcPlusListeners.getCalculator();
|
||||
}
|
||||
return createFinalInsertion(fleetManager, baseCalculator, states);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,8 +114,7 @@ final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCo
|
|||
else depTime = v.getEarliestDeparture();
|
||||
InsertionData iData = insertionCalculator.getInsertionData(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
|
||||
if(iData instanceof NoInsertionFound) {
|
||||
if(bestIData instanceof NoInsertionFound) bestIData = iData;
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
if(iData.getInsertionCost() < bestKnownCost_){
|
||||
bestIData = iData;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
|
||||
import jsprit.core.problem.VehicleRoutingProblem;
|
||||
|
|
@ -36,9 +37,10 @@ import jsprit.core.problem.vehicle.VehicleTypeImpl;
|
|||
import jsprit.core.util.Coordinate;
|
||||
import jsprit.core.util.Solutions;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
@Ignore
|
||||
public class TestDepartureTimeOpt {
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -5,23 +5,6 @@
|
|||
<fleetSize>FINITE</fleetSize>
|
||||
</problemType>
|
||||
<vehicles>
|
||||
<vehicle>
|
||||
<id>v2</id>
|
||||
<typeId>vehType2</typeId>
|
||||
<startLocation>
|
||||
<id>depotLoc</id>
|
||||
<coord x="10.0" y="100.0"/>
|
||||
</startLocation>
|
||||
<endLocation>
|
||||
<id>depotLoc</id>
|
||||
<coord x="10.0" y="100.0"/>
|
||||
</endLocation>
|
||||
<timeSchedule>
|
||||
<start>0.0</start>
|
||||
<end>1000.0</end>
|
||||
</timeSchedule>
|
||||
<returnToDepot>false</returnToDepot>
|
||||
</vehicle>
|
||||
<vehicle>
|
||||
<id>v3</id>
|
||||
<typeId>vehType2</typeId>
|
||||
|
|
@ -40,8 +23,25 @@
|
|||
<returnToDepot>true</returnToDepot>
|
||||
</vehicle>
|
||||
<vehicle>
|
||||
<id>v5</id>
|
||||
<typeId>vehType3</typeId>
|
||||
<id>v2</id>
|
||||
<typeId>vehType2</typeId>
|
||||
<startLocation>
|
||||
<id>depotLoc</id>
|
||||
<coord x="10.0" y="100.0"/>
|
||||
</startLocation>
|
||||
<endLocation>
|
||||
<id>depotLoc</id>
|
||||
<coord x="10.0" y="100.0"/>
|
||||
</endLocation>
|
||||
<timeSchedule>
|
||||
<start>0.0</start>
|
||||
<end>1000.0</end>
|
||||
</timeSchedule>
|
||||
<returnToDepot>false</returnToDepot>
|
||||
</vehicle>
|
||||
<vehicle>
|
||||
<id>v4</id>
|
||||
<typeId>vehType2</typeId>
|
||||
<startLocation>
|
||||
<id>startLoc</id>
|
||||
<coord x="10.0" y="100.0"/>
|
||||
|
|
@ -57,8 +57,8 @@
|
|||
<returnToDepot>true</returnToDepot>
|
||||
</vehicle>
|
||||
<vehicle>
|
||||
<id>v4</id>
|
||||
<typeId>vehType2</typeId>
|
||||
<id>v5</id>
|
||||
<typeId>vehType3</typeId>
|
||||
<startLocation>
|
||||
<id>startLoc</id>
|
||||
<coord x="10.0" y="100.0"/>
|
||||
|
|
@ -137,20 +137,6 @@
|
|||
</type>
|
||||
</vehicleTypes>
|
||||
<services>
|
||||
<service id="2" type="service">
|
||||
<locationId>i(3,9)</locationId>
|
||||
<coord x="10.0" y="10.0"/>
|
||||
<capacity-dimensions>
|
||||
<dimension index="0">1</dimension>
|
||||
</capacity-dimensions>
|
||||
<duration>0.0</duration>
|
||||
<timeWindows>
|
||||
<timeWindow>
|
||||
<start>0.0</start>
|
||||
<end>4000.0</end>
|
||||
</timeWindow>
|
||||
</timeWindows>
|
||||
</service>
|
||||
<service id="1" type="service">
|
||||
<locationId>j(1,5)</locationId>
|
||||
<coord x="10.0" y="10.0"/>
|
||||
|
|
@ -165,6 +151,20 @@
|
|||
</timeWindow>
|
||||
</timeWindows>
|
||||
</service>
|
||||
<service id="2" type="service">
|
||||
<locationId>i(3,9)</locationId>
|
||||
<coord x="10.0" y="10.0"/>
|
||||
<capacity-dimensions>
|
||||
<dimension index="0">1</dimension>
|
||||
</capacity-dimensions>
|
||||
<duration>0.0</duration>
|
||||
<timeWindows>
|
||||
<timeWindow>
|
||||
<start>0.0</start>
|
||||
<end>4000.0</end>
|
||||
</timeWindow>
|
||||
</timeWindows>
|
||||
</service>
|
||||
</services>
|
||||
<shipments>
|
||||
<shipment id="3">
|
||||
|
|
|
|||
|
|
@ -35,12 +35,12 @@
|
|||
</type>
|
||||
</vehicleTypes>
|
||||
<services>
|
||||
<service id="2" type="service">
|
||||
<locationId>loc2</locationId>
|
||||
<service id="1" type="service">
|
||||
<locationId>loc</locationId>
|
||||
<capacity-dimensions>
|
||||
<dimension index="0">1</dimension>
|
||||
</capacity-dimensions>
|
||||
<duration>4.0</duration>
|
||||
<duration>2.0</duration>
|
||||
<timeWindows>
|
||||
<timeWindow>
|
||||
<start>0.0</start>
|
||||
|
|
@ -48,12 +48,12 @@
|
|||
</timeWindow>
|
||||
</timeWindows>
|
||||
</service>
|
||||
<service id="1" type="service">
|
||||
<locationId>loc</locationId>
|
||||
<service id="2" type="service">
|
||||
<locationId>loc2</locationId>
|
||||
<capacity-dimensions>
|
||||
<dimension index="0">1</dimension>
|
||||
</capacity-dimensions>
|
||||
<duration>2.0</duration>
|
||||
<duration>4.0</duration>
|
||||
<timeWindows>
|
||||
<timeWindow>
|
||||
<start>0.0</start>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue