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

add breaks

This commit is contained in:
oblonski 2015-08-04 20:36:48 +02:00
parent 543d1c2ace
commit 4e83871984
16 changed files with 871 additions and 14 deletions

View file

@ -0,0 +1,183 @@
/*******************************************************************************
* Copyright (C) 2014 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.algorithm.recreate;
import jsprit.core.problem.JobActivityFactory;
import jsprit.core.problem.Location;
import jsprit.core.problem.constraint.*;
import jsprit.core.problem.constraint.HardActivityConstraint.ConstraintsStatus;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Break;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.BreakActivity;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.Start;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.util.CalculationUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* Calculator that calculates the best insertion position for a {@link jsprit.core.problem.job.Service}.
*
* @author schroeder
*
*/
final class BreakInsertionCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = LogManager.getLogger(BreakInsertionCalculator.class);
private HardRouteConstraint hardRouteLevelConstraint;
private HardActivityConstraint hardActivityLevelConstraint;
private SoftRouteConstraint softRouteConstraint;
private SoftActivityConstraint softActivityConstraint;
private VehicleRoutingTransportCosts transportCosts;
private ActivityInsertionCostsCalculator additionalTransportCostsCalculator;
private JobActivityFactory activityFactory;
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
public BreakInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager) {
super();
this.transportCosts = routingCosts;
hardRouteLevelConstraint = constraintManager;
hardActivityLevelConstraint = constraintManager;
softActivityConstraint = constraintManager;
softRouteConstraint = constraintManager;
this.additionalTransportCostsCalculator = additionalTransportCostsCalculator;
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
logger.debug("initialise " + this);
}
public void setJobActivityFactory(JobActivityFactory jobActivityFactory){
this.activityFactory = jobActivityFactory;
}
@Override
public String toString() {
return "[name=calculatesServiceInsertion]";
}
/**
* Calculates the marginal cost of inserting job i locally. This is based on the
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
*
*/
@Override
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
Break breakToInsert = (Break) jobToInsert;
if(newVehicle.getBreak() == null || newVehicle.getBreak() != breakToInsert) return InsertionData.createEmptyInsertionData();
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
int insertionIndex = InsertionData.NO_INDEX;
BreakActivity breakAct2Insert = (BreakActivity) activityFactory.createActivities(breakToInsert).get(0);
insertionContext.getAssociatedActivities().add(breakAct2Insert);
boolean differentVehicles = false;
if(!currentRoute.isEmpty()){
differentVehicles = currentRoute.getVehicle() != newVehicle;
}
/*
check hard constraints at route level
*/
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.createEmptyInsertionData();
}
/*
check soft constraints at route level
*/
double additionalICostsAtRouteLevel = softRouteConstraint.getCosts(insertionContext);
double bestCost = bestKnownCosts;
additionalICostsAtRouteLevel += additionalAccessEgressCalculator.getCosts(insertionContext);
/*
generate new start and end for new vehicle
*/
Start start = new Start(newVehicle.getStartLocation(), newVehicle.getEarliestDeparture(), Double.MAX_VALUE);
start.setEndTime(newVehicleDepartureTime);
End end = new End(newVehicle.getEndLocation(), 0.0, newVehicle.getLatestArrival());
Location bestLocation = null;
TourActivity prevAct = start;
double prevActStartTime = newVehicleDepartureTime;
int actIndex = 0;
Iterator<TourActivity> activityIterator = currentRoute.getActivities().iterator();
boolean tourEnd = false;
while(!tourEnd){
TourActivity nextAct;
if(activityIterator.hasNext()) nextAct = activityIterator.next();
else{
nextAct = end;
tourEnd = true;
}
boolean breakThis = true;
List<Location> locations = Arrays.asList( prevAct.getLocation(), nextAct.getLocation());
for(Location location : locations) {
breakAct2Insert.setLocation(location);
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, breakAct2Insert, nextAct, prevActStartTime);
if (status.equals(ConstraintsStatus.FULFILLED)) {
//from job2insert induced costs at activity level
double additionalICostsAtActLevel = softActivityConstraint.getCosts(insertionContext, prevAct, breakAct2Insert, nextAct, prevActStartTime);
double additionalTransportationCosts = additionalTransportCostsCalculator.getCosts(insertionContext, prevAct, nextAct, breakAct2Insert, prevActStartTime);
if (additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts < bestCost) {
bestCost = additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts;
insertionIndex = actIndex;
bestLocation = location;
}
breakThis = false;
} else if (status.equals(ConstraintsStatus.NOT_FULFILLED)) {
breakThis = false;
}
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActStartTime, newDriver, newVehicle);
prevActStartTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
prevAct = nextAct;
actIndex++;
}
if(breakThis) break;
}
if(insertionIndex == InsertionData.NO_INDEX) {
return InsertionData.createEmptyInsertionData();
}
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
breakAct2Insert.setLocation(bestLocation);
insertionData.getEvents().add(new InsertBreak(currentRoute,newVehicle,breakAct2Insert,insertionIndex));
insertionData.getEvents().add(new SwitchVehicle(currentRoute,newVehicle,newVehicleDepartureTime));
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
return insertionData;
}
}

View file

@ -13,6 +13,7 @@ class EventListeners {
public EventListeners() {
listeners.add(new InsertActivityListener());
listeners.add(new SwitchVehicleListener());
listeners.add(new InsertBreakListener());
}
public void inform(Event event){

View file

@ -0,0 +1,42 @@
package jsprit.core.algorithm.recreate;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
/**
* Created by schroeder on 19/05/15.
*/
class InsertBreak implements Event {
private VehicleRoute vehicleRoute;
private Vehicle newVehicle;
private TourActivity activity;
private int index;
public InsertBreak(VehicleRoute vehicleRoute, Vehicle newVehicle, TourActivity activity, int index) {
this.vehicleRoute = vehicleRoute;
this.newVehicle = newVehicle;
this.activity = activity;
this.index = index;
}
public Vehicle getNewVehicle() {
return newVehicle;
}
public VehicleRoute getVehicleRoute() {
return vehicleRoute;
}
public TourActivity getActivity() {
return activity;
}
public int getIndex() {
return index;
}
}

View file

@ -0,0 +1,31 @@
package jsprit.core.algorithm.recreate;
import jsprit.core.problem.solution.route.VehicleRoute;
/**
* Created by schroeder on 19/05/15.
*/
class InsertBreakListener implements EventListener {
@Override
public void inform(Event event) {
if(event instanceof InsertBreak){
InsertBreak insertActivity = (InsertBreak) event;
if(!insertActivity.getNewVehicle().isReturnToDepot()){
if(insertActivity.getIndex()>=insertActivity.getVehicleRoute().getActivities().size()){
insertActivity.getVehicleRoute().getEnd().setLocation(insertActivity.getActivity().getLocation());
}
}
VehicleRoute vehicleRoute = ((InsertBreak) event).getVehicleRoute();
if(!vehicleRoute.isEmpty()){
if(vehicleRoute.getVehicle() != ((InsertBreak) event).getNewVehicle()){
if(vehicleRoute.getVehicle().getBreak() != null){
vehicleRoute.getTourActivities().removeJob(vehicleRoute.getVehicle().getBreak());
}
}
}
insertActivity.getVehicleRoute().getTourActivities().addActivity(insertActivity.getIndex(),((InsertBreak) event).getActivity());
}
}
}

View file

@ -290,11 +290,15 @@ public class JobInsertionCostsCalculatorBuilder {
ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager);
serviceInsertion.setJobActivityFactory(activityFactory);
BreakInsertionCalculator breakInsertionCalculator = new BreakInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager);
breakInsertionCalculator.setJobActivityFactory(activityFactory);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
switcher.put(Shipment.class, shipmentInsertion);
switcher.put(Service.class, serviceInsertion);
switcher.put(Pickup.class, serviceInsertion);
switcher.put(Delivery.class, serviceInsertion);
switcher.put(Break.class, breakInsertionCalculator);
return new CalculatorPlusListeners(switcher);
}

View file

@ -160,10 +160,14 @@ public class RegretInsertion extends AbstractInsertionStrategy {
}
private double scoreService(InsertionData best, Job job) {
double maxDepotDistance = Math.max(
getDistance(best.getSelectedVehicle().getStartLocation(), ((Service) job).getLocation()),
getDistance(best.getSelectedVehicle().getEndLocation(), ((Service) job).getLocation())
);
Location location = ((Service) job).getLocation();
double maxDepotDistance = 0;
if(location != null) {
maxDepotDistance = Math.max(
getDistance(best.getSelectedVehicle().getStartLocation(), location),
getDistance(best.getSelectedVehicle().getEndLocation(), location)
);
}
return Math.max(tw_param * (((Service)job).getTimeWindow().getEnd() - ((Service)job).getTimeWindow().getStart()),minTimeWindowScore) +
depotDistance_param * maxDepotDistance;
}

View file

@ -0,0 +1,31 @@
package jsprit.core.algorithm.ruin;
import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.problem.job.Break;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import java.util.Collection;
/**
* Created by schroeder on 04/08/15.
*/
public class RuinBreaks implements RuinListener {
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
for(VehicleRoute r : routes){
Break aBreak = r.getVehicle().getBreak();
if(aBreak != null){
r.getTourActivities().removeJob(aBreak);
unassignedJobs.add(aBreak);
}
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
}

View file

@ -23,6 +23,7 @@ import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.BreakActivity;
import jsprit.core.problem.solution.route.activity.DefaultShipmentActivityFactory;
import jsprit.core.problem.solution.route.activity.DefaultTourActivityFactory;
import jsprit.core.problem.solution.route.activity.TourActivity;
@ -117,7 +118,7 @@ public class VehicleRoutingProblem {
acts.add(shipmentActivityFactory.createPickup((Shipment) job));
acts.add(shipmentActivityFactory.createDelivery((Shipment) job));
}
return acts;
return acts;
}
};
@ -138,7 +139,7 @@ public class VehicleRoutingProblem {
private final DefaultTourActivityFactory serviceActivityFactory = new DefaultTourActivityFactory();
private void incJobIndexCounter(){
private void incJobIndexCounter(){
jobIndexCounter++;
}
@ -265,6 +266,16 @@ public class VehicleRoutingProblem {
activityMap.put(job, jobActs);
}
private void addBreaksToActivityMap(){
for(Vehicle v : uniqueVehicles){
if(v.getBreak() != null){
AbstractActivity breakActivity = BreakActivity.newInstance(v.getBreak());
breakActivity.setIndex(activityIndexCounter);
incActivityIndexCounter();
activityMap.put(v.getBreak(),Arrays.asList(breakActivity));
}
}
}
/**
* Adds an initial vehicle route.
@ -402,10 +413,12 @@ public class VehicleRoutingProblem {
if(transportCosts == null){
transportCosts = new CrowFlyCosts(getLocations());
}
for(Job job : tentativeJobs.values())
if (!jobsInInitialRoutes.contains(job.getId())) {
addJobToFinalJobMapAndCreateActivities(job);
}
for(Job job : tentativeJobs.values()) {
if (!jobsInInitialRoutes.contains(job.getId())) {
addJobToFinalJobMapAndCreateActivities(job);
}
}
addBreaksToActivityMap();
return new VehicleRoutingProblem(this);
}

View file

@ -0,0 +1,80 @@
/*******************************************************************************
* Copyright (C) 2014 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.problem.job;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.Skills;
/**
* Pickup extends Service and is intended to model a Service where smth is LOADED (i.e. picked up) to a transport unit.
*
* @author schroeder
*
*/
public class Break extends Service {
public static class Builder extends Service.Builder {
/**
* Returns a new instance of builder that builds a pickup.
*
* @param id the id of the pickup
* @return the builder
*/
public static Builder newInstance(String id){
return new Builder(id);
}
private boolean variableLocation = true;
Builder(String id) {
super(id);
}
/**
* Builds Pickup.
*
*<p>Pickup type is "pickup"
*
* @return pickup
* @throws IllegalStateException if neither locationId nor coordinate has been set
*/
public Break build(){
if(location != null){
variableLocation = false;
}
this.setType("break");
super.capacity = Capacity.Builder.newInstance().build();
super.skills = Skills.Builder.newInstance().build();
return new Break(this);
}
}
private boolean variableLocation = true;
Break(Builder builder) {
super(builder);
this.variableLocation = builder.variableLocation;
}
public boolean hasVariableLocation(){
return variableLocation;
}
}

View file

@ -0,0 +1,178 @@
/*******************************************************************************
* Copyright (C) 2014 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.problem.solution.route.activity;
import jsprit.core.problem.AbstractActivity;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.Location;
import jsprit.core.problem.job.Break;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.solution.route.activity.TourActivity.JobActivity;
public class BreakActivity extends AbstractActivity implements JobActivity{
public static int counter = 0;
public double arrTime;
public double endTime;
private Location location;
/**
* @return the arrTime
*/
public double getArrTime() {
return arrTime;
}
/**
* @param arrTime the arrTime to set
*/
public void setArrTime(double arrTime) {
this.arrTime = arrTime;
}
/**
* @return the endTime
*/
public double getEndTime() {
return endTime;
}
/**
* @param endTime the endTime to set
*/
public void setEndTime(double endTime) {
this.endTime = endTime;
}
public static BreakActivity copyOf(BreakActivity breakActivity){
return new BreakActivity(breakActivity);
}
public static BreakActivity newInstance(Break aBreak){
return new BreakActivity(aBreak);
}
private final Break aBreak;
protected BreakActivity(Break aBreak) {
counter++;
this.aBreak = aBreak;
}
protected BreakActivity(BreakActivity breakActivity) {
counter++;
this.aBreak = (Break) breakActivity.getJob();
this.arrTime = breakActivity.getArrTime();
this.endTime = breakActivity.getEndTime();
this.location = breakActivity.getLocation();
setIndex(breakActivity.getIndex());
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((aBreak == null) ? 0 : aBreak.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BreakActivity other = (BreakActivity) obj;
if (aBreak == null) {
if (other.aBreak != null)
return false;
} else if (!aBreak.equals(other.aBreak))
return false;
return true;
}
public double getTheoreticalEarliestOperationStartTime() {
return aBreak.getTimeWindow().getStart();
}
public double getTheoreticalLatestOperationStartTime() {
return aBreak.getTimeWindow().getEnd();
}
@Override
public double getOperationTime() {
return aBreak.getServiceDuration();
}
@Override
public String getLocationId() {
return aBreak.getLocation().getId();
}
@Override
public Location getLocation() {
return location;
}
public void setLocation(Location breakLocation){
this.location = breakLocation;
}
@Override
public Service getJob() {
return aBreak;
}
@Override
public String toString() {
return "[type="+getName()+"][location=" + getLocation()
+ "][size=" + getSize().toString()
+ "][twStart=" + Activities.round(getTheoreticalEarliestOperationStartTime())
+ "][twEnd=" + Activities.round(getTheoreticalLatestOperationStartTime()) + "]";
}
@Override
public String getName() {
return aBreak.getType();
}
@Override
public TourActivity duplicate() {
return new BreakActivity(this);
}
@Override
public Capacity getSize() {
return aBreak.getSize();
}
}

View file

@ -20,6 +20,7 @@ import jsprit.core.problem.HasId;
import jsprit.core.problem.HasIndex;
import jsprit.core.problem.Location;
import jsprit.core.problem.Skills;
import jsprit.core.problem.job.Break;
/**
* Basic interface for vehicle-data.
@ -72,4 +73,6 @@ public interface Vehicle extends HasId, HasIndex {
public abstract VehicleTypeKey getVehicleTypeIdentifier();
public abstract Skills getSkills();
public abstract Break getBreak();
}

View file

@ -19,6 +19,7 @@ package jsprit.core.problem.vehicle;
import jsprit.core.problem.AbstractVehicle;
import jsprit.core.problem.Location;
import jsprit.core.problem.Skills;
import jsprit.core.problem.job.Break;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -91,7 +92,10 @@ public class VehicleImpl extends AbstractVehicle{
public Skills getSkills() {
return null;
}
}
@Override
public Break getBreak() { return null; }
}
/**
* Builder that builds the vehicle.
@ -125,7 +129,9 @@ public class VehicleImpl extends AbstractVehicle{
private Location endLocation;
private Builder(String id) {
private Break aBreak;
private Builder(String id) {
super();
this.id = id;
}
@ -245,7 +251,12 @@ public class VehicleImpl extends AbstractVehicle{
this.skillBuilder.addAllSkills(skills.values());
return this;
}
}
public Builder setBreak(Break aBreak) {
this.aBreak = aBreak;
return this;
}
}
/**
* Returns empty/noVehicle which is a vehicle having no capacity, no type and no reasonable id.
@ -274,6 +285,8 @@ public class VehicleImpl extends AbstractVehicle{
private final Location startLocation;
private final Break aBreak;
private VehicleImpl(Builder builder){
id = builder.id;
type = builder.type;
@ -283,6 +296,7 @@ public class VehicleImpl extends AbstractVehicle{
skills = builder.skills;
endLocation = builder.endLocation;
startLocation = builder.startLocation;
aBreak = builder.aBreak;
setVehicleIdentifier(new VehicleTypeKey(type.getTypeId(),startLocation.getId(),endLocation.getId(),earliestDeparture,latestArrival,skills));
}
@ -341,7 +355,12 @@ public class VehicleImpl extends AbstractVehicle{
return skills;
}
/* (non-Javadoc)
@Override
public Break getBreak() {
return aBreak;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override

View file

@ -0,0 +1,39 @@
package jsprit.core.algorithm.ruin;
import jsprit.core.problem.Location;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Break;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.BreakActivity;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.VehicleImpl;
import junit.framework.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by schroeder on 04/08/15.
*/
public class RuinBreakTest {
@Test
public void test(){
Break aBreak = Break.Builder.newInstance("break").build();
VehicleImpl v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("loc"))
.setBreak(aBreak).build();
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addVehicle(v).build();
VehicleRoute route = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory()).addService(aBreak).build();
TourActivity tourActivity = route.getActivities().get(0);
System.out.println(tourActivity);
Assert.assertTrue(tourActivity instanceof BreakActivity);
RuinBreaks ruinBreaks = new RuinBreaks();
List<Job> unassigned = new ArrayList<Job>();
ruinBreaks.ruinEnds(Arrays.asList(route),unassigned);
Assert.assertEquals(1,unassigned.size());
Assert.assertEquals(aBreak,unassigned.get(0));
}
}

View file

@ -0,0 +1,106 @@
/*******************************************************************************
* Copyright (C) 2014 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.problem.solution.route.activity;
import jsprit.core.problem.Location;
import jsprit.core.problem.job.Break;
import jsprit.core.problem.job.Service;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class BreakActivityTest {
private Break service;
private BreakActivity serviceActivity;
@Before
public void doBefore(){
service = (Break) Break.Builder.newInstance("service")
.setTimeWindow(TimeWindow.newInstance(1., 2.)).setServiceTime(3).build();
serviceActivity = BreakActivity.newInstance(service);
}
@Test
public void whenCallingCapacity_itShouldReturnCorrectCapacity(){
assertEquals(0,serviceActivity.getSize().get(0));
}
@Test
public void hasVariableLocationShouldBeTrue(){
Break aBreak = (Break) serviceActivity.getJob();
assertTrue(aBreak.hasVariableLocation());
}
@Test
public void whenStartIsIniWithEarliestStart_itShouldBeSetCorrectly(){
assertEquals(1.,serviceActivity.getTheoreticalEarliestOperationStartTime(),0.01);
}
@Test
public void whenStartIsIniWithLatestStart_itShouldBeSetCorrectly(){
assertEquals(2.,serviceActivity.getTheoreticalLatestOperationStartTime(),0.01);
}
@Test
public void whenSettingArrTime_itShouldBeSetCorrectly(){
serviceActivity.setArrTime(4.0);
assertEquals(4.,serviceActivity.getArrTime(),0.01);
}
@Test
public void whenSettingEndTime_itShouldBeSetCorrectly(){
serviceActivity.setEndTime(5.0);
assertEquals(5.,serviceActivity.getEndTime(),0.01);
}
@Test
public void whenCopyingStart_itShouldBeDoneCorrectly(){
BreakActivity copy = (BreakActivity) serviceActivity.duplicate();
assertEquals(1.,copy.getTheoreticalEarliestOperationStartTime(),0.01);
assertEquals(2.,copy.getTheoreticalLatestOperationStartTime(),0.01);
assertTrue(copy!=serviceActivity);
}
@Test
public void whenTwoDeliveriesHaveTheSameUnderlyingJob_theyAreEqual(){
Service s1 = Service.Builder.newInstance("s").setLocation(Location.newInstance("loc")).build();
Service s2 = Service.Builder.newInstance("s").setLocation(Location.newInstance("loc")).build();
ServiceActivity d1 = ServiceActivity.newInstance(s1);
ServiceActivity d2 = ServiceActivity.newInstance(s2);
assertTrue(d1.equals(d2));
}
@Test
public void whenTwoDeliveriesHaveTheDifferentUnderlyingJob_theyAreNotEqual(){
Service s1 = Service.Builder.newInstance("s").setLocation(Location.newInstance("loc")).build();
Service s2 = Service.Builder.newInstance("s1").setLocation(Location.newInstance("loc")).build();
ServiceActivity d1 = ServiceActivity.newInstance(s1);
ServiceActivity d2 = ServiceActivity.newInstance(s2);
assertFalse(d1.equals(d2));
}
}

View file

@ -20,6 +20,8 @@ package jsprit.core.problem.vehicle;
import jsprit.core.problem.Location;
import jsprit.core.problem.job.Break;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import org.junit.Test;
import static org.junit.Assert.*;
@ -221,5 +223,20 @@ public class VehicleImplTest {
assertFalse(v.getSkills().containsSkill("ScrewDriver"));
}
@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();
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("start"))
.setType(type1).setEndLocation(Location.newInstance("start"))
.setBreak(aBreak).build();
assertNotNull(v.getBreak());
assertEquals(100.,v.getBreak().getTimeWindow().getStart(),0.1);
assertEquals(200.,v.getBreak().getTimeWindow().getEnd(),0.1);
assertEquals(30.,v.getBreak().getServiceDuration(),0.1);
}
}

View file

@ -0,0 +1,106 @@
/*******************************************************************************
* Copyright (C) 2014 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.examples;
import jsprit.analysis.toolbox.Plotter;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.box.Jsprit;
import jsprit.core.algorithm.ruin.RuinBreaks;
import jsprit.core.problem.Location;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Break;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.problem.vehicle.VehicleImpl;
import jsprit.core.problem.vehicle.VehicleImpl.Builder;
import jsprit.core.problem.vehicle.VehicleType;
import jsprit.core.problem.vehicle.VehicleTypeImpl;
import jsprit.core.reporting.SolutionPrinter;
import jsprit.core.util.Solutions;
import java.util.Collection;
public class BreakExample {
public static void main(String[] args) {
/*
* get a vehicle type-builder and build a type with the typeId "vehicleType" and one capacity dimension, i.e. weight, and capacity dimension value of 2
*/
final int WEIGHT_INDEX = 0;
VehicleTypeImpl.Builder vehicleTypeBuilder = VehicleTypeImpl.Builder.newInstance("vehicleType").addCapacityDimension(WEIGHT_INDEX, 4);
VehicleType vehicleType = vehicleTypeBuilder.build();
/*
* get a vehicle-builder and build a vehicle located at (10,10) with type "vehicleType"
*/
Builder vehicleBuilder = Builder.newInstance("vehicle");
vehicleBuilder.setStartLocation(Location.newInstance(10, 10));
Break myFirstBreak = (Break) Break.Builder.newInstance("myFirstBreak").setTimeWindow(TimeWindow.newInstance(30, 50)).setServiceTime(10).build();
vehicleBuilder.setBreak(myFirstBreak);
vehicleBuilder.setType(vehicleType);
VehicleImpl vehicle = vehicleBuilder.build();
/*
* build services at the required locations, each with a capacity-demand of 1.
*/
Service service1 = Service.Builder.newInstance("1").addSizeDimension(WEIGHT_INDEX, 1).setLocation(Location.newInstance(5, 7)).build();
Service service2 = Service.Builder.newInstance("2").addSizeDimension(WEIGHT_INDEX, 1).setLocation(Location.newInstance(5, 13)).build();
Service service3 = Service.Builder.newInstance("3").addSizeDimension(WEIGHT_INDEX, 1).setLocation(Location.newInstance(15, 7)).build();
Service service4 = Service.Builder.newInstance("4").addSizeDimension(WEIGHT_INDEX, 1).setLocation(Location.newInstance(15, 13)).build();
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
vrpBuilder.addVehicle(vehicle);
vrpBuilder.addJob(service1).addJob(service2).addJob(service3).addJob(service4);
vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE);
VehicleRoutingProblem problem = vrpBuilder.build();
/*
* get the algorithm out-of-the-box.
*/
VehicleRoutingAlgorithm algorithm = Jsprit.Builder.newInstance(problem)
.setProperty(Jsprit.Strategy.CLUSTER_REGRET,"0.")
.setProperty(Jsprit.Strategy.CLUSTER_BEST,"0.").buildAlgorithm();
algorithm.addListener(new RuinBreaks());
/*
* and search a solution
*/
Collection<VehicleRoutingProblemSolution> solutions = algorithm.searchSolutions();
/*
* get the best
*/
VehicleRoutingProblemSolution bestSolution = Solutions.bestOf(solutions);
SolutionPrinter.print(problem, bestSolution, SolutionPrinter.Print.VERBOSE);
/*
* plot
*/
new Plotter(problem,bestSolution).plot("output/plot","breaks");
}
}