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

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