optaplanner - Vehicle Routing with multiple locations per customer -
i'm trying solve vehicle routing each customer has multiple locations, of 1 needs visited. obtained optaplanner-master , modified vehiclerouting example in following manner:
customer.java:
/* * copyright 2012 red hat, inc. and/or affiliates. * * licensed under apache license, version 2.0 (the "license"); * may not use file except in compliance license. * may obtain copy of license @ * * http://www.apache.org/licenses/license-2.0 * * unless required applicable law or agreed in writing, software * distributed under license distributed on "as is" basis, * without warranties or conditions of kind, either express or implied. * see license specific language governing permissions , * limitations under license. */ package org.optaplanner.examples.vehiclerouting.domain; import com.thoughtworks.xstream.annotations.xstreamalias; import com.thoughtworks.xstream.annotations.xstreaminclude; import org.optaplanner.core.api.domain.entity.planningentity; import org.optaplanner.core.api.domain.valuerange.countablevaluerange; import org.optaplanner.core.api.domain.valuerange.valuerangefactory; import org.optaplanner.core.api.domain.valuerange.valuerangeprovider; import org.optaplanner.core.api.domain.variable.anchorshadowvariable; import org.optaplanner.core.api.domain.variable.planningvariable; import org.optaplanner.core.api.domain.variable.planningvariablegraphtype; import org.optaplanner.examples.common.domain.abstractpersistable; import org.optaplanner.examples.vehiclerouting.domain.location.location; import org.optaplanner.examples.vehiclerouting.domain.solver.depotanglecustomerdifficultyweightfactory; import org.optaplanner.examples.vehiclerouting.domain.timewindowed.timewindowedcustomer; import java.util.list; @planningentity(difficultyweightfactoryclass = depotanglecustomerdifficultyweightfactory.class) @xstreamalias("vrpcustomer") @xstreaminclude({ timewindowedcustomer.class }) public class customer extends abstractpersistable implements standstill { protected int demand; // planning variables: changes during planning, between score calculations. protected standstill previousstandstill; // shadow variables protected customer nextcustomer; protected vehicle vehicle; protected list<location> locations; protected integer selectedlocation = 0; public void setselectedlocation(integer selectedlocation){ this.selectedlocation = selectedlocation; } @planningvariable(valuerangeproviderrefs = {"selectedlocation"}) public integer getselectedlocation(){ return selectedlocation; } @valuerangeprovider(id = "selectedlocation") public countablevaluerange<integer> getselectablelocations(){ return valuerangefactory.createintvaluerange(0, locations.size()); } public void setlocations(list<location> locations) { this.locations = locations; } public list<location> getlocations(){ return locations; } @override public location getlocation() { return locations.get(selectedlocation); } @override public string tostring() { return "customer " + getid(); } public int getdemand() { return demand; } public void setdemand(int demand) { this.demand = demand; } @planningvariable(valuerangeproviderrefs = {"vehiclerange", "customerrange"}, graphtype = planningvariablegraphtype.chained) public standstill getpreviousstandstill() { return previousstandstill; } public void setpreviousstandstill(standstill previousstandstill) { this.previousstandstill = previousstandstill; } @override public customer getnextcustomer() { return nextcustomer; } @override public void setnextcustomer(customer nextcustomer) { this.nextcustomer = nextcustomer; } @override @anchorshadowvariable(sourcevariablename = "previousstandstill") public vehicle getvehicle() { return vehicle; } public void setvehicle(vehicle vehicle) { this.vehicle = vehicle; } // ************************************************************************ // complex methods // ************************************************************************ /** * @return positive number, distance multiplied 1000 avoid floating point arithmetic rounding errors */ public long getdistancefrompreviousstandstill() { if (previousstandstill == null) { throw new illegalstateexception("this method must not called when previousstandstill (" + previousstandstill + ") not initialized yet."); } return getdistancefrom(previousstandstill); } /** * @param standstill never null * @return positive number, distance multiplied 1000 avoid floating point arithmetic rounding errors */ public long getdistancefrom(standstill standstill) { return standstill.getlocation().getdistanceto(getlocation()); } /** * @param standstill never null * @return positive number, distance multiplied 1000 avoid floating point arithmetic rounding errors */ public long getdistanceto(standstill standstill) { return getlocation().getdistanceto(standstill.getlocation()); } }
in vehicleroutingimporter.java, code reads customer's location has changed to:
list<location> locations = new arraylist<>(linetokens.length-2); (int j = 2; j < linetokens.length; ++j){ long locationid = long.parselong(linetokens[j]); location location = locationmap.get(locationid); if (location == null) throw new illegalargumentexception("missing location (id=" + locationid + ") specified customer id=" + id); locations.add(location) } customer.setlocations(locations);
all other code used call customer.setlocation(location) calls customer.setlocations(collections.singletonlist(location)). don't think of gets called.
in vehicleroutingsolverconfig.xml, removed these lines (otherwise, complains multiple variables):
<subchainchangemoveselector> <selectreversingmovetoo>true</selectreversingmovetoo> </subchainchangemoveselector> <subchainswapmoveselector> <selectreversingmovetoo>true</selectreversingmovetoo> </subchainswapmoveselector>
tutorial-01-uncapacitated.vrp now:
name : tutorial-01-uncapacitated comment : geoffrey de smet - optaplanner vrp demo 01 type : cvrp dimension : 8 edge_weight_type : euc_2d capacity : 100 node_coord_section 1 50 50 2 45 100 3 30 80 4 70 85 5 60 60 6 35 10 7 30 30 8 45 20 demand_section 1 0 2 1 2 3 3 1 3 4 4 1 4 5 5 1 5 6 6 1 6 7 7 1 7 8 8 1 8 2 depot_section 1 -1 vehicles : 2 eof
it appears work, , finds optimal solution in small test cases (and, looks reasonable solution in large cases). when set fast_assert mode, fails following error:
caused by: java.lang.illegalstateexception: impossible variablelistener corruption: expectedworkingscore (0hard/-30000soft) not workingscore (0hard/-34142soft) after variablelisteners triggered without changes genuine variables. shadow variable values still same, impossible.
Comments
Post a Comment