OptaPlanner事实可以包括规划实体对象吗?

时间:2015-05-28 19:35:47

标签: optaplanner

OptaPlanner Fact可以包含规划实体吗?我的猜测是答案是否定的,因为它违反了事实不能改变的规则。

如果确实支持,我在尝试调用getter方法时遇到空指针异常。

这里是规则,school1是Parings事实的私有变量,包含一个关联的规划实体。



   when
        Run($r : runId)
        Pairings(runId1 == $r, $s1 : school1.adjustment.timeAdjustment)  ...




这是堆栈跟踪。



Exception in thread "main" Exception executing consequence for rule "maximizeLiftPairings" in org.optaplanner.examples.cloudbalancing.solver: java.lang.RuntimeException: cannot invoke getter: getSchool1 [declr.class: org.optaplanner.examples.cloudbalancing.domain.Pairings; act.class: org.optaplanner.examples.cloudbalancing.domain.Pairings] (see trace)
	at org.drools.core.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39)
	at org.drools.core.common.DefaultAgenda.fireActivation(DefaultAgenda.java:1027)
	at org.drools.core.phreak.RuleExecutor.fire(RuleExecutor.java:128)
	at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:70)
	at org.drools.core.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:935)
	at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1200)
	at org.drools.core.common.AbstractWorkingMemory.fireAllRules(AbstractWorkingMemory.java:957)
	at org.drools.core.common.AbstractWorkingMemory.fireAllRules(AbstractWorkingMemory.java:931)
	at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:256)
	at org.optaplanner.core.impl.score.director.drools.DroolsScoreDirector.calculateScore(DroolsScoreDirector.java:98)
	at org.optaplanner.core.impl.solver.scope.DefaultSolverScope.calculateScore(DefaultSolverScope.java:101)
	at org.optaplanner.core.impl.bestsolution.BestSolutionRecaller.solvingStarted(BestSolutionRecaller.java:58)
	at org.optaplanner.core.impl.solver.DefaultSolver.solvingStarted(DefaultSolver.java:177)
	at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:154)
	at org.optaplanner.examples.cloudbalancing.app.CloudBalancingHelloWorld.main(CloudBalancingHelloWorld.java:56)
Caused by: java.lang.RuntimeException: cannot invoke getter: getSchool1 [declr.class: org.optaplanner.examples.cloudbalancing.domain.Pairings; act.class: org.optaplanner.examples.cloudbalancing.domain.Pairings] (see trace)
	at org.mvel2.optimizers.impl.refl.nodes.GetterAccessor.getValue(GetterAccessor.java:74)
	at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:108)
	at org.mvel2.MVELRuntime.execute(MVELRuntime.java:86)
	at org.mvel2.compiler.CompiledExpression.getDirectValue(CompiledExpression.java:123)
	at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:119)
	at org.mvel2.MVEL.executeExpression(MVEL.java:954)
	at org.drools.core.base.extractors.MVELNumberClassFieldReader.getValue(MVELNumberClassFieldReader.java:102)
	at org.drools.core.rule.Declaration.getValue(Declaration.java:229)
	at org.optaplanner.examples.cloudbalancing.solver.Rule_maximizeLiftPairings143464364DefaultConsequenceInvokerGenerated.evaluate(Unknown Source)
	at org.optaplanner.examples.cloudbalancing.solver.Rule_maximizeLiftPairings143464364DefaultConsequenceInvoker.evaluate(Unknown Source)
	at org.drools.core.common.DefaultAgenda.fireActivation(DefaultAgenda.java:1016)
	... 13 more
Caused by: java.lang.RuntimeException: unable to invoke method: org.optaplanner.examples.cloudbalancing.domain.School.getAdjustment: target of method is null
	at org.mvel2.optimizers.impl.refl.nodes.GetterAccessor.getValue(GetterAccessor.java:66)
	at org.mvel2.optimizers.impl.refl.nodes.GetterAccessor.getValue(GetterAccessor.java:40)
	... 23 more
Caused by: java.lang.NullPointerException
	at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.mvel2.optimizers.impl.refl.nodes.GetterAccessor.getValue(GetterAccessor.java:40)
	... 24 more




2 个答案:

答案 0 :(得分:2)

你的预感是对的,答案是没有

来自 documentation

  

在OptaPlanner中,所有问题事实和规划实体都是普通的旧JavaBeans(POJO)。您可以从数据库(JDBC / JPA / JDO),XML文件,数据存储库甚至noSQL云加载它们。 OptaPlanner不关心。

规划实体:

  

计划实体是在解决期间更改的JavaBean(POJO),例如更改为另一行的Queen。计划问题有多个计划实体,例如对于单个n皇后问题,每个皇后都是计划实体。但通常只有1个计划实体类,例如女王级。

@PlanningEntity
public class Queen {


private Column column;


// Planning variables: changes during planning, between score calculations.

private Row row;


// ... getters and setters

}

问题事实:

  

问题是任何带有getter的JavaBean(POJO)在规划期间不会改变。建议实现接口Serializable(但不是必需的)。例如,在n queens中,列和行是问题事实:

public class Column implements Serializable {


private int index;


// ... getters

}

答案 1 :(得分:0)

这个答案是为了记录。布鲁斯的答案本质上更好:)

可能,但在大多数情况下,不推荐。有一些陷阱。有两种方式:

A)将该问题事实类转换为影子规划实体类。影子规划实体类是仅具有影子规划变量的类(因此没有真正的规划变量)。当然,请确保在求解器配置中注册该类并正确地对其进行注释。但在这种情况下,它应该起作用(包括规划克隆等)。

B)破解它(不推荐!)。将它保留为问题事实类,但是自定义规划克隆程序以便进行规划克隆(因为它可能默认情况下无法克隆)。确保您首先清楚地了解"规划克隆"意思是(见文档)。它不是一个浅层克隆,它不是深层克隆,它介于两者之间(逻辑取决于计划注释等)。正确实施这种黑客将是困难的+痛苦(可能不会成为未来的证据)。