CompositePlanningValueRangeDescriptor.extractValues中的Nullpointer异常

时间:2013-05-07 16:26:03

标签: drools drools-planner optaplanner

在尝试解决我的解决方案时,我正面临着NPE:

Exception in thread "main" java.lang.NullPointerException
at java.util.ArrayList.addAll(ArrayList.java:472)
at org.drools.planner.core.domain.variable.CompositePlanningValueRangeDescriptor.extractValues(CompositePlanningValueRangeDescriptor.java:46)
at org.drools.planner.core.domain.variable.PlanningVariableDescriptor.extractPlanningValues(PlanningVariableDescriptor.java:259)
at org.drools.planner.core.heuristic.selector.variable.PlanningValueSelector.initSelectedPlanningValueList(PlanningValueSelector.java:91)
at org.drools.planner.core.heuristic.selector.variable.PlanningValueSelector.phaseStarted(PlanningValueSelector.java:73)
at org.drools.planner.core.heuristic.selector.variable.PlanningValueWalker.phaseStarted(PlanningValueWalker.java:64)
at org.drools.planner.core.heuristic.selector.variable.PlanningVariableWalker.phaseStarted(PlanningVariableWalker.java:62)
at org.drools.planner.core.constructionheuristic.greedyFit.decider.DefaultGreedyDecider.phaseStarted(DefaultGreedyDecider.java:62)
at org.drools.planner.core.constructionheuristic.greedyFit.DefaultGreedyFitSolverPhase.phaseStarted(DefaultGreedyFitSolverPhase.java:112)
at org.drools.planner.core.constructionheuristic.greedyFit.DefaultGreedyFitSolverPhase.solve(DefaultGreedyFitSolverPhase.java:57)
at org.drools.planner.core.solver.DefaultSolver.runSolverPhases(DefaultSolver.java:190)
at org.drools.planner.core.solver.DefaultSolver.solve(DefaultSolver.java:155)
at de.haw.dsms.applicationcore.planning.BalancingApp.main(BalancingApp.java:47)

我使用以下注释注释了我的计划实体,以从解决方案中的两个列表中收集值范围:

@PlanningEntity
public class ScheduleItem implements Cloneable{

private ChangeOfferEvent item;

@PlanningVariable() 
@ValueRanges({
        @ValueRange(type = ValueRangeType.FROM_SOLUTION_PROPERTY, solutionProperty = "offers"),
        @ValueRange(type = ValueRangeType.FROM_SOLUTION_PROPERTY, solutionProperty = "dummies")
})
public ChangeOfferEvent getItem() {
    return item;
}

public void setItem(ChangeOfferEvent item) {
    this.item = item;
}

public ScheduleItem() {
    this.item = null;
}
    ...

这是解决方案:

public class ProductionConsumptionBalancing implements Solution<HardAndSoftLongScore> {

/*
 * Problem facts
 */

// The grid entity offers
private List<ChangeOfferEvent> offers;
// Placeholder events to represent "not used schedule items"
private List<PlaceholderOfferEvent> dummies;
// The total energy consumption in the grid
// [Watt]
private TotalEnergyConsumption totalElectricityConsumption;
// The total energy production in the grid
// [Watt]
private TotalEnergyProduction totalElectricityProduction;

public List<ChangeOfferEvent> getOffers() {
    return offers;
}

public void setOffers(List<ChangeOfferEvent> offers) {
    this.offers = offers;
}

public List<PlaceholderOfferEvent> getDummies() {
    return dummies;
}

public void setDummies(List<PlaceholderOfferEvent> dummies) {
    this.dummies = dummies;
}

public TotalEnergyConsumption getTotalElectricityConsumption() {
    return totalElectricityConsumption;
}

public void setTotalElectricityConsumption(
        TotalEnergyConsumption totalElectricityConsumption) {
    this.totalElectricityConsumption = totalElectricityConsumption;
}

public TotalEnergyProduction getTotalElectricityProduction() {
    return totalElectricityProduction;
}

public void setTotalElectricityProduction(
        TotalEnergyProduction totalElectricityProduction) {
    this.totalElectricityProduction = totalElectricityProduction;
}

/*
 * Problem entities
 */
private List<ScheduleItem> schedule;    

@PlanningEntityCollectionProperty
public List<ScheduleItem> getSchedule() {
    return schedule;
}

public void setSchedule(List<ScheduleItem> schedule) {
    this.schedule = schedule;
}
    ...

关于这一点的奇怪之处在于,在调试期间我发现它是参数“planningEntity”,它是null而不是解决方案中的值。

是否有人遇到同样的问题或者知道如何解决这个问题?

谢谢和最诚挚的问候!

PS: 看起来这是来自方法initSelectedPlanningValueList:

 private void initSelectedPlanningValueList(AbstractSolverPhaseScope phaseScope) {
 90         if (planningVariableDescriptor.isPlanningValuesCacheable()) {
 91             Collection<?> planningValues =             planningVariableDescriptor.extractPlanningValues(
 92                     phaseScope.getWorkingSolution(), null);
 93             cachedPlanningValues = applySelectionOrder(planningValues);
 94         } else {
 95             cachedPlanningValues = null;
 96         }
 97     }

PSPS: 问题解决了。 问题出现是因为我忘了将克隆的dummies-attribute链接到原始的假人列表。所以克隆解决方案中的虚拟列表为空。

@Override
public Solution<HardAndSoftLongScore> cloneSolution() {

    ProductionConsumptionBalancing clone = new ProductionConsumptionBalancing();

    // Transfer consumption and production values
    clone.totalElectricityConsumption = this.totalElectricityConsumption;
    clone.totalElectricityProduction = this.totalElectricityProduction;

    // Shallow copy offer lists (shouldn't change)
    clone.offers = this.offers;

    // Shallow copy of dummy list
    clone.dummies = this.dummies;

    // Deep copy schedule
            ...

1 个答案:

答案 0 :(得分:0)

从6.0.0.Beta1开始,OptaPlanner(= Drools Planner)支持automatic cloning out-of-the-box。因此,您不需要再实施cloneSolution()方法,因为planner会自动计算出来。 因为您不再需要实施该方法,所以无法正确实施。

请注意,如果您确实需要,仍然可以实现自定义克隆方法。