Question

I'm facing a NPE when trying to solve my solution:

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)

I have annotated my planning entity with the following annotations to collect the value range from two lists in the solution:

@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;
}
    ...

This is the solution:

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;
}
    ...

The strange thing about this is, that during debugging I discoverd that it is the parameter "planningEntity" which is null and not the values in the solution.

Does anybody encounter the same issue or does know how to solve this?

Thanks and best regards!

PS: It seems like this is coming from the method 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: Problem solved. The issue appeared because I forgot to link the clone's dummies-attribute to the original dummies list. So the dummies list in the cloned solution was null.

@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
            ...
Était-ce utile?

La solution

Starting from 6.0.0.Beta1, OptaPlanner (= Drools Planner) supports automatic cloning out-of-the-box. So you don't need to implement the cloneSolution() method no more, because planner figures it out automatically. Because you don't need to implement the method no more, you can't implement it incorrectly.

Note that you can still implement a custom clone method if you really want too.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top