2017-07-18 1 views
0

J'essaie d'obtenir la liste des contraintes brisées à partir d'une instance de problème dans OptaPlanner. J'utilise OptaPlanner version 7.0.0.Final et bave pour le moteur de règles (également 7.0.0.Final). Le problème est résolu correctement et sans aucune erreur, mais lorsque j'essaie d'obtenir des contraintes brisées, j'obtiens une exception NullPointer. Pour autant que j'ai étudié, j'ai découvert que cela ne se produit que lorsque j'utilise un accumulateur de bave sans opération inverse (comme max ou min). En outre, j'ai fait un accumulateur personnalisé, qui est la copie exacte de org.drools.core.base.accumulators.LongSumAccumulateFunction et tout fonctionne comme prévu, mais dès que je change la fonction supportsReverse() pour retourner false, l'exception NullPointer augmente.Obtenir des contraintes brisées dans OptaPanner avec accumulateur non réversible

J'ai réussi à reconstruire ce problème dans l'un des exemples fournis - CloudBalancing. Ceci est le changement à CloudBalancingHelloWorld, son seul but est d'obtenir la liste des contraintes brisées comme mentionné dans ce post.

public class CloudBalancingHelloWorld { 

public static void main(String[] args) { 
    // Build the Solver 
    SolverFactory<CloudBalance> solverFactory = SolverFactory.createFromXmlResource(
      "org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml"); 
    Solver<CloudBalance> solver = solverFactory.buildSolver(); 

    // Load a problem with 400 computers and 1200 processes 
    CloudBalance unsolvedCloudBalance = new CloudBalancingGenerator().createCloudBalance(400, 1200); 

    // Solve the problem 
    CloudBalance solvedCloudBalance = solver.solve(unsolvedCloudBalance); 

    // Display the result 
    System.out.println("\nSolved cloudBalance with 400 computers and 1200 processes:\n" 
      + toDisplayString(solvedCloudBalance)); 

    // 
    //A Piece of code added - start 
    // 

    ScoreDirector<CloudBalance> scoreDirector = solver.getScoreDirectorFactory().buildScoreDirector(); 
    scoreDirector.setWorkingSolution(solvedCloudBalance); 
    Collection<ConstraintMatchTotal> constrains = scoreDirector.getConstraintMatchTotals(); 
    System.out.println(constrains.size()); 

    // 
    //A Piece of code added - end 
    // 



} 

public static String toDisplayString(CloudBalance cloudBalance) { 
    StringBuilder displayString = new StringBuilder(); 
    for (CloudProcess process : cloudBalance.getProcessList()) { 
     CloudComputer computer = process.getComputer(); 
     displayString.append(" ").append(process.getLabel()).append(" -> ") 
       .append(computer == null ? null : computer.getLabel()).append("\n"); 
    } 
    return displayString.toString(); 
} 

} 

Et c'est la modification à la règle requiredCpoPowerTotal. S'il vous plaît noter que je l'ai fait seulement pour démontrer le problème. Basicaly j'ai changé sum à max.

rule "requiredCpuPowerTotal" 
when 
    $computer : CloudComputer($cpuPower : cpuPower) 
    accumulate(
     CloudProcess(
      computer == $computer, 
      $requiredCpuPower : requiredCpuPower); 
     $requiredCpuPowerTotal : max($requiredCpuPower); 
     (Integer) $requiredCpuPowerTotal > $cpuPower 
    ) 
then 
    scoreHolder.addHardConstraintMatch(kcontext, $cpuPower - (Integer) $requiredCpuPowerTotal); 
end 

Je suis vraiment confus, parce que l'erreur ne se produit pas lors de la phase de rabotage, mais quand le scoreDirector recalcule le score pour obtenir cassé CONTRAINTES il le fait. Je veux dire que les mêmes calculs doivent avoir eu lieu pendant la phase de planification, n'est-ce pas?

Quoi qu'il en soit ici est la pile trace

Exception in thread "main" Exception executing consequence for rule "requiredCpuPowerTotal" in org.optaplanner.examples.cloudbalancing.solver: java.lang.NullPointerException 
at org.drools.core.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39) 
at org.drools.core.common.DefaultAgenda.handleException(DefaultAgenda.java:1256) 
at org.drools.core.phreak.RuleExecutor.innerFireActivation(RuleExecutor.java:438) 
at org.drools.core.phreak.RuleExecutor.fireActivation(RuleExecutor.java:379) 
at org.drools.core.phreak.RuleExecutor.fire(RuleExecutor.java:135) 
at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:88) 
at org.drools.core.concurrent.AbstractRuleEvaluator.internalEvaluateAndFire(AbstractRuleEvaluator.java:34) 
at org.drools.core.concurrent.SequentialRuleEvaluator.evaluateAndFire(SequentialRuleEvaluator.java:43) 
at org.drools.core.common.DefaultAgenda.fireLoop(DefaultAgenda.java:1072) 
at org.drools.core.common.DefaultAgenda.internalFireAllRules(DefaultAgenda.java:1019) 
at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1011) 
at org.drools.core.impl.StatefulKnowledgeSessionImpl.internalFireAllRules(StatefulKnowledgeSessionImpl.java:1321) 
at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1312) 
at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1296) 
at org.optaplanner.core.impl.score.director.drools.DroolsScoreDirector.getConstraintMatchTotals(DroolsScoreDirector.java:134) 
at org.optaplanner.examples.cloudbalancing.app.CloudBalancingHelloWorld.main(CloudBalancingHelloWorld.java:52) 
Caused by: java.lang.NullPointerException 
at org.drools.core.base.accumulators.JavaAccumulatorFunctionExecutor$JavaAccumulatorFunctionContext.getAccumulatedObjects(JavaAccumulatorFunctionExecutor.java:208) 
at org.drools.core.reteoo.FromNodeLeftTuple.getAccumulatedObjects(FromNodeLeftTuple.java:94) 
at org.drools.core.common.AgendaItem.getObjectsDeep(AgendaItem.java:78) 
at org.drools.core.reteoo.RuleTerminalNodeLeftTuple.getObjectsDeep(RuleTerminalNodeLeftTuple.java:359) 
at org.optaplanner.core.api.score.holder.AbstractScoreHolder.extractJustificationList(AbstractScoreHolder.java:118) 
at org.optaplanner.core.api.score.holder.AbstractScoreHolder.registerConstraintMatch(AbstractScoreHolder.java:88) 
at org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder.addHardConstraintMatch(HardSoftScoreHolder.java:53) 
at org.optaplanner.examples.cloudbalancing.solver.Rule_requiredCpuPowerTotal1284553313.defaultConsequence(Rule_requiredCpuPowerTotal1284553313.java:14) 
at org.optaplanner.examples.cloudbalancing.solver.Rule_requiredCpuPowerTotal1284553313DefaultConsequenceInvokerGenerated.evaluate(Unknown Source) 
at org.optaplanner.examples.cloudbalancing.solver.Rule_requiredCpuPowerTotal1284553313DefaultConsequenceInvoker.evaluate(Unknown Source) 
at org.drools.core.phreak.RuleExecutor.innerFireActivation(RuleExecutor.java:431) 
... 13 more 

Merci pour toute aide à l'avance.

+0

Eh bien, j'ai réussi à esquiver le problème en implémentant mon propre SumAccumulator, qui supporte les opérations inversées en utilisant 'PriorityQueue'. Vous vous demandez toujours pourquoi le 'ScoreDirector' a besoin d'opérations inverses, car il connaît déjà l'affectation à l'avance. –

Répondre

0

Que NPE ressemble à un bogue dans Drools. L'API ConstraintMatch devrait toujours fonctionner. Très bien que vous l'obtenez contre la dernière version principale. Si oui, s'il vous plaît create a jira pour cela avec un reproducteur minimal et nous allons regarder dans.

+1

Déclaré comme https://issues.jboss.org/browse/DROOLS-1687. – yurloc