0

For a solution of the time windowed VRP I edited the solved XML file and set <locked>true</locked> for all customers.

I added a SelctionFiler class and configured it as proposed. At the end of solved xml data file I added some new unassigned customers.

I expected that only the new unassigned customers would be optimized and would be inserted at the end of the existing chains - which is not the case - the chains are broken.

Question: What exactly is in 6.2 necessary to handle immovable customer appointments?

I thought the jira issue https://issues.jboss.org/browse/PLANNER-239 has only to be solved for 6.0.1.

Geoffrey wrote: In 6.2 a number of improvements have been made for this IIRC, but it's not solved in all cases. What are the improvements for the time windowed VRP?

This questions belongs to my problem: Can optaplanner solve partly pre-assigned planning entities using Drools rules?

Best regards, Milenko

Community
  • 1
  • 1
len
  • 749
  • 1
  • 8
  • 23

1 Answers1

2

This is the configuration we use with optaplanner 6.2.0. To keep the customers locked in place filters had to be implemented for changeMoveSelector, swapMoveSelector and tailChainSwapMoveSelector in addition to CustomerEntitySelectionFilter.

<localSearch>
    <unionMoveSelector>
        <changeMoveSelector>
            <entitySelector id="entitySelector1"/>
            <filterClass>...THIS....CustomerFilterChangeMove</filterClass>
            <valueSelector>
                <nearbySelection>
                    <originEntitySelector mimicSelectorRef="entitySelector1"/>
                    <nearbyDistanceMeterClass>....CustomerNearbyDistanceMeter</nearbyDistanceMeterClass>
                    <parabolicDistributionSizeMaximum>80</parabolicDistributionSizeMaximum>
                </nearbySelection>
            </valueSelector>
        </changeMoveSelector>
        <swapMoveSelector>
            <filterClass>...THIS....CustomerFilterSwapMove</filterClass>
        </swapMoveSelector>
        <tailChainSwapMoveSelector>
            <entitySelector id="entitySelector3"/>
            <filterClass>...THIS...CustomerFilterTailChainSwapMove</filterClass>
            <valueSelector>
                <nearbySelection>
                    <originEntitySelector mimicSelectorRef="entitySelector3"/>
                    <nearbyDistanceMeterClass>....CustomerNearbyDistanceMeter</nearbyDistanceMeterClass>
                    <parabolicDistributionSizeMaximum>80</parabolicDistributionSizeMaximum>
                </nearbySelection>
            </valueSelector>
            <!--Disabled, doesn't work with tailChain -->
            <!--<selectReversingMoveToo>false</selectReversingMoveToo>-->
        </tailChainSwapMoveSelector>

    </unionMoveSelector>
    <acceptor>
        <lateAcceptanceSize>200</lateAcceptanceSize>
    </acceptor>
    <forager>
        <acceptedCountLimit>1</acceptedCountLimit>
    </forager>
</localSearch>

The customer chain is checked for locked customers on EntitySelectionFilter and CustomerFilterTailChainSwapMove (both chains).

The classes are:

namespace ...THIS...;

public class CustomerFilterChangeMove implements SelectionFilter<ChangeMove> {

    @Override
    public boolean accept(ScoreDirector scoreDirector, ChangeMove changeMove) {
        Customer customer = (Customer) changeMove.getEntity();
        if(customer!=null && customer.isLocked())
            return false;
        //everything is fine
        return true;
    }
}

public class CustomerFilterSwapMove implements SelectionFilter<SwapMove>
{
    @Override
    public boolean accept(ScoreDirector scoreDirector, SwapMove move)
    {
        Customer leftCustomer = (Customer) move.getLeftEntity();
        Customer rightCustomer = (Customer) move.getRightEntity();
        if(leftCustomer!=null && leftCustomer.isLocked())
            return false;
        if(rightCustomer!=null && rightCustomer.isLocked())
            return false;
        return true;
    }
}

public class CustomerFilterTailChainSwapMove implements SelectionFilter<TailChainSwapMove>
{
    /**
     * Chain starting at left entity will be moved to the right. If there's an entity on the right side, it's chain will be moved to the left
     */
    @Override
    public boolean accept(ScoreDirector scoreDirector, TailChainSwapMove move)
    {
        Customer shadow=null;
        Customer leftCustomer = (Customer) move.getLeftEntity();
        Customer rightCustomer = null;
        Vehicle leftVehicle = leftCustomer.getVehicle();
        Vehicle rightVehicle=null;
        if(move.getRightValue() instanceof Customer)
        {
            rightCustomer = (Customer) move.getRightValue();
            rightVehicle = rightCustomer.getVehicle();
        }
        else if(move.getRightValue() instanceof Vehicle)
        {
            rightVehicle = (Vehicle) move.getRightValue();
            rightCustomer = rightVehicle.getNextCustomer();
        }

        shadow=rightCustomer;
        while(shadow!=null)
        {
            if(shadow.isLocked())
                return false;
            shadow=shadow.getNextCustomer();
        }

        shadow=leftCustomer;
        while(shadow!=null)
        {
            if(shadow.isLocked())
                return false;
            shadow=shadow.getNextCustomer();
        }
        return true;
    }
}

public class CustomerEntitySelectionFilter implements SelectionFilter<Customer> {
    @Override
    public boolean accept(ScoreDirector scoreDirector, Customer customer) {
        Customer shadow = customer;
        while(shadow!=null)
        {
            if (shadow.isLocked())
                return false;
            shadow=shadow.getNextCustomer();
        }
        return true;
    }
}
grudolf
  • 1,764
  • 3
  • 22
  • 28
  • Nice workaround for PLANNER-239 :) Too many people are running into that issue, I 'll try to include it in 6.3. – Geoffrey De Smet May 08 '15 at 14:08
  • Dear grundolf,what is meant by : ...THIS....CustomerFilterChangeMove ....CustomerNearbyDistanceMeter ...THIS....CustomerFilterSwapMove ...THIS...CustomerFilterTailChainSwapMove How do this classes look like? – len May 13 '15 at 08:57
  • 1
    I've added the filter classes. – grudolf May 13 '15 at 12:29
  • Dear grundolf, this helps me a lot - only one thing I would like to ask: how does the class "CustomerNearbyDistanceMeter.java" looks like? – len May 15 '15 at 14:50
  • 1
    Customer locking has no effect on it, It can be identical to the one used in the manual ( http://docs.jboss.org/optaplanner/release/6.2.0.Final/optaplanner-docs/html_single/index.html#nearbySelection ) or in the VRP example - check `\examples\sources\src\main\java\org\optaplanner\examples\vehiclerouting\domain\solver\nearby\CustomerNearbyDistanceMeter.java` – grudolf May 15 '15 at 18:37
  • Dear grudolf, I added everything what you proposed. When I use the keyword true the corresponding customers are skipped. But if I add at the end of a solved XML-file one or more unsolved (unassigned) customers (with locked=false, all the solved have locked=true) then the solved arrival time at these additional unassigned customers breaks the existing chain order of the vehicles. Can you try to add for your problem at the end of the solved XML-file only one unassigned customer with a time window somewhere in the middle of the others time windows - what happens? – len May 27 '15 at 09:08
  • Sorry, I can't because our use case is a bit different - the user locks a group of deliveries (a chain of customers) to vehicle trip.The vehicle can start at a different time, make another trip or deliver additional goods before delivering the locked group thus changing their actual delivery time. They'll still stick together and obey the time windows. though. – grudolf May 29 '15 at 08:21
  • Perhaps it's something with the way the depot departure time is calculated? – grudolf May 29 '15 at 08:27