如何计算返回到仓库时间并使其成为硬约束

时间:2014-10-31 12:51:19

标签: optaplanner drools-planner

我正在使用车辆路线的TimeWindowed版本,并且我在车辆中添加了endOfShift时间。我想计算返回仓库的时间并使其成为一个严格的约束。 returnToDepotTime在ArrivalTimeUpdatingVariableListener中计算,我也更改了我添加的drl文件

rule "returnToDepotBeforeEndOfShift"
when
    Vehicle(endOfShift < returnToDepotTime, $endOfShift : endOfShift, $returnToDepotTime : returnToDepotTime)
then
    scoreHolder.addHardConstraintMatch(kcontext, $endOfShift - $returnToDepotTime.intValue());  end

问题是OptaPlanner没有考虑returnToDepotTime,而是计算但不受硬约束计算的影响。知道要改变什么吗?

2 个答案:

答案 0 :(得分:2)

嗨@Snukra非常感谢你解决了我的解决方法我在最后一个客户中保存了所有内容。 但我想知道我的问题在哪里:) 所以这是车辆对象的重要部分:

@PlanningEntity(difficultyComparatorClass = VehicleDifficultyComparator.class)
@XStreamAlias("Vehicle")
public class Vehicle extends AbstractPersistable implements Standstill {

Integer returnToDepotTime;

@CustomShadowVariable(variableListenerClass = ArrivalTimeUpdatingVariableListener.class, sources = { @CustomShadowVariable.Source(variableName = "returnToDepotTime") })

public Integer getReturnToDepotTime() {
    return returnToDepotTime;
}

public void setReturnToDepotTime(Integer returnToDepotTime) {
    this.returnToDepotTime = returnToDepotTime;
}   

}

这是ArrivalTimeUpdatingVariableListener:

public class ArrivalTimeUpdatingVariableListener implements
    VariableListener<Customer> {

public void beforeEntityAdded(ScoreDirector scoreDirector,
        Customer customer) {
    // Do nothing
}

public void afterEntityAdded(ScoreDirector scoreDirector,
        Customer customer) {
    updateVehicle(scoreDirector, customer);
}

public void beforeVariableChanged(ScoreDirector scoreDirector,
        Customer customer) {
    // Do nothing
}

public void afterVariableChanged(ScoreDirector scoreDirector,
        Customer customer) {
    updateVehicle(scoreDirector, customer);
}

public void beforeEntityRemoved(ScoreDirector scoreDirector,
        Customer customer) {
    // Do nothing
}

public void afterEntityRemoved(ScoreDirector scoreDirector,
        Customer customer) {
    // Do nothing
}

protected void updateVehicle(ScoreDirector scoreDirector,
        Customer sourceCustomer) {
    Standstill previousStandstill = sourceCustomer.getPreviousStandstill();
    Integer departureTime = null;
    Customer shadowCustomer = sourceCustomer;
    Integer arrivalTime = 0;

    Vehicle vehicle = null;
    vehicle = sourceCustomer.getVehicle();

    // here the start times are used
    if (previousStandstill instanceof Customer) {
        departureTime = ((Customer) previousStandstill).getDepartureTime();

        arrivalTime = calculateArrivalTime(sourceCustomer, departureTime);
    } else if (previousStandstill instanceof Vehicle) {
        vehicle = (Vehicle) previousStandstill;
        arrivalTime = calculateArrivalTimeFirstCustomer(sourceCustomer,
                vehicle);
    }

    while (shadowCustomer != null
            && ObjectUtils.notEqual(shadowCustomer.getArrivalTime(),
                    arrivalTime)) {
        scoreDirector.beforeVariableChanged(shadowCustomer, "arrivalTime");
        shadowCustomer.setArrivalTime(arrivalTime);     
        scoreDirector.afterVariableChanged(shadowCustomer, "arrivalTime");

        departureTime = shadowCustomer.getDepartureTime();
        if (shadowCustomer.getNextCustomer() == null) {
            scoreDirector.beforeVariableChanged(shadowCustomer,
                    "returnTimeToDepotIfLastOnTour");
            //scoreDirector.beforeVariableChanged(vehicle,
            //      "returnToDepotTime");

            int returnTimeToDepot = shadowCustomer.getArrivalTime()
                    + shadowCustomer.getServiceDuration()
                    + shadowCustomer.getTravelTimeTo(vehicle.getDepot());
            vehicle.setReturnToDepotTime(returnTimeToDepot);
            shadowCustomer
                    .setReturnTimeToDepotIfLastOnTour(returnTimeToDepot);
            shadowCustomer.setEndOfShiftOfVehicle(vehicle.getEndOfShift());

            scoreDirector.afterVariableChanged(shadowCustomer,
                    "returnTimeToDepotIfLastOnTour");
            //scoreDirector.afterVariableChanged(vehicle,
            //      "returnToDepotTime");
        }

        shadowCustomer = shadowCustomer.getNextCustomer();
        arrivalTime = calculateArrivalTime(shadowCustomer, departureTime);
    }
}

private Integer calculateArrivalTimeFirstCustomer(Customer customer,
        Vehicle vehicle) {
    // calculate the earliest possible arrival time for this customer and
    // this vehicle
    int arrivalTime = vehicle.getStartOfShift()
            + customer.getLocation().getTravelTime(
                    vehicle.getStartLocation());

    // if the time is before the redy time of a conatiner we take the ready
    // time of a customer
    if (customer.getReadyTime() > arrivalTime) {
        arrivalTime = customer.getReadyTime();
    }
    return arrivalTime;
}

private Integer calculateArrivalTime(Customer customer,
        Integer previousDepartureTime) {
    if (customer == null) {
        return null;
    }
    if (previousDepartureTime == null) {
        // PreviousStandstill is the Vehicle, so we leave from the Depot
        // at
        // the best suitable time
        int maxTime = Math.max(customer.getReadyTime(),
                customer.getTravelTimeToPreviousStandstill());
        return maxTime;
    }
    int arrivalTime = previousDepartureTime
            + customer.getTravelTimeToPreviousStandstill();
    return arrivalTime;

}

}

评论scoreDirector.beforeVariableChanged(vehicle, "returnToDepotTime");scoreDirector.afterVariableChanged(vehicle, "returnToDepotTime");会返回错误。 你知道为什么吗?

答案 1 :(得分:0)

调整ArrivalTimeUpdatingVariableListener以调整Vehicle returnHomeTime Customer getNextCustomer() null的{​​{1}}。

如果scoreDirectorVehicle的{​​{1}}更改了returnHomeTime,则会相应地更新规则{/ p>}。