2017-08-20 59 views
3

我試圖解決每個客戶有多個位置,其中只有一個需要訪問的車輛路線。我得到optaplanner掌握和以下面的方式修改了vehiclerouting例如:每個客戶有多個位置的車輛路線

Customer.java:

/* 
* Copyright 2012 Red Hat, Inc. and/or its affiliates. 
* 
* Licensed 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 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 a positive number, the distance multiplied by 1000 to avoid floating point arithmetic rounding errors 
    */ 
    public long getDistanceFromPreviousStandstill() { 
     if (previousStandstill == null) { 
      throw new IllegalStateException("This method must not be called when the previousStandstill (" 
        + previousStandstill + ") is not initialized yet."); 
     } 
     return getDistanceFrom(previousStandstill); 
    } 

    /** 
    * @param standstill never null 
    * @return a positive number, the distance multiplied by 1000 to avoid floating point arithmetic rounding errors 
    */ 
    public long getDistanceFrom(Standstill standstill) { 
     return standstill.getLocation().getDistanceTo(getLocation()); 
    } 

    /** 
    * @param standstill never null 
    * @return a positive number, the distance multiplied by 1000 to avoid floating point arithmetic rounding errors 
    */ 
    public long getDistanceTo(Standstill standstill) { 
     return getLocation().getDistanceTo(standstill.getLocation()); 
    } 


} 

在VehicleRoutingImporter.java,讀取客戶的位置的代碼已更改爲:

List<Location> locations = new ArrayList<>(lineTokens.length-2); 
for (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 for customer id=" + id); 
     locations.add(location) 
} 
customer.setLocations(locations); 

用於調用Customer.setLocation(location)的所有其他代碼現在調用Customer.setLocations(Collections.singletonList(location))。我不認爲它實際上被稱爲。

在vehicleRoutingSolverConfig.xml,我除去這些線(否則,它抱怨多個變量):現在

<subChainChangeMoveSelector> 
    <selectReversingMoveToo>true</selectReversingMoveToo> 
    </subChainChangeMoveSelector> 
    <subChainSwapMoveSelector> 
    <selectReversingMoveToo>true</selectReversingMoveToo> 
    </subChainSwapMoveSelector> 

教程-01-uncapacitated.vrp是:

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 

這似乎在小型測試案例中找到最佳解決方案(在大型案例中看起來像是一個合理的解決方案)。然而,當我設置FAST_ASSERT模式時,出現以下錯誤:

Caused by: java.lang.IllegalStateException: Impossible VariableListener corruption: the expectedWorkingScore (0hard/-30000soft) is not the workingScore (0hard/-34142soft) after all VariableListeners were triggered without changes to the genuine variables. But all the shadow variable values are still the same, so this is impossible.

+0

當我使用VehicleRoutingEasyScoreCalculator而不是drl時,它的工作原理沒有錯誤。 – msasha

+0

你能否在DRL中註釋掉一個分數規則來找出哪個分數規則導致了這個問題,然後複製粘貼到這個問題中? (即使你可以修復它,我需要能夠重現以修復錯誤信息。)在任何情況下,錯誤信息都是誤導性的,應該包括腐敗分析,所以我創建了[此問題](https:/ /issues.jboss.org/browse/PLANNER-866)。 –

+0

我的DRL中只有兩條規則 - 容量的硬約束和距離的軟約束。當我刪除軟約束時,它不會返回此錯誤。這裏是DRL規則: 規則 「distanceToPreviousStandstill」 當 $客戶:客戶(previousStandstill = NULL,$ distanceFromPreviousStandstill:distanceFromPreviousStandstill) 然後 scoreHolder.addSoftConstraintMatch(kcontext, - $ distanceFromPreviousStandstill); 結束 – msasha

回答

0

打開FULL_ASSERT,而不是FAST_ASSERT失敗更快指向真正的問題。請參閱the PR comment,其中解釋瞭如何幫助檢測問題。

相關問題