OptaPlanner Facts 是否可以包含 Planning Entity 对象?
Can OptaPlanner Facts include Planning Entity objects?
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
你的预感是对的,答案是没有。
In OptaPlanner all problems facts and planning entities are plain old JavaBeans (POJO's). You can load them from a database (JDBC/JPA/JDO), an XML file, a data repository or even a noSQL cloud. OptaPlanner doesn't care.
规划实体:
A planning entity is a JavaBean (POJO) that changes during solving, for example a Queen that changes to another row. A planning problem has multiple planning entities, for example for a single n queens problem, each Queen is a planning entity. But there's usually only 1 planning entity class, for example the Queen class.
@PlanningEntity
public class Queen {
private Column column;
// Planning variables: changes during planning, between score calculations.
private Row row;
// ... getters and setters
}
问题事实:
A problem fact is any JavaBean (POJO) with getters that does not change during planning. Implementing the interface Serializable is recommended (but not required). For example in n queens, the columns and rows are problem facts:
public class Column implements Serializable {
private int index;
// ... getters
}
此答案已记录在案。布鲁斯的回答本质上更好:)
可以,但在大多数情况下,不建议。有一些陷阱。有两种方式:
A) 将问题事实 class 变成影子计划实体 class。影子计划实体 class 是一个 class 只有影子计划变量(因此没有真正的计划变量)。当然,请确保在求解器配置中注册 class 并正确注释。但在这种情况下,它应该非常有效(包括计划克隆等)。
B) 破解它(不推荐!)。将其保留为问题事实 class,但自定义计划克隆器以便计划克隆(因为默认情况下它可能不会被克隆)。确保您首先清楚地了解 "planning clone" 的含义(请参阅文档)。它不是浅克隆,也不是深层克隆,它介于两者之间(逻辑取决于计划注释等)。这个 hack 很难正确实施(并且可能不是未来的证明)。
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
你的预感是对的,答案是没有。
In OptaPlanner all problems facts and planning entities are plain old JavaBeans (POJO's). You can load them from a database (JDBC/JPA/JDO), an XML file, a data repository or even a noSQL cloud. OptaPlanner doesn't care.
规划实体:
A planning entity is a JavaBean (POJO) that changes during solving, for example a Queen that changes to another row. A planning problem has multiple planning entities, for example for a single n queens problem, each Queen is a planning entity. But there's usually only 1 planning entity class, for example the Queen class.
@PlanningEntity
public class Queen {
private Column column;
// Planning variables: changes during planning, between score calculations.
private Row row;
// ... getters and setters
}
问题事实:
A problem fact is any JavaBean (POJO) with getters that does not change during planning. Implementing the interface Serializable is recommended (but not required). For example in n queens, the columns and rows are problem facts:
public class Column implements Serializable {
private int index;
// ... getters
}
此答案已记录在案。布鲁斯的回答本质上更好:)
可以,但在大多数情况下,不建议。有一些陷阱。有两种方式:
A) 将问题事实 class 变成影子计划实体 class。影子计划实体 class 是一个 class 只有影子计划变量(因此没有真正的计划变量)。当然,请确保在求解器配置中注册 class 并正确注释。但在这种情况下,它应该非常有效(包括计划克隆等)。
B) 破解它(不推荐!)。将其保留为问题事实 class,但自定义计划克隆器以便计划克隆(因为默认情况下它可能不会被克隆)。确保您首先清楚地了解 "planning clone" 的含义(请参阅文档)。它不是浅克隆,也不是深层克隆,它介于两者之间(逻辑取决于计划注释等)。这个 hack 很难正确实施(并且可能不是未来的证明)。