Optaplanner初始化规划变量异常:求解结果为null且分数0hard/0soft
OptaPlanner测试问题:变量最大化求解失败
刚接触OptaPlanner,为熟悉框架编写了一段简单测试代码:定义取值范围1至30的Integer类型规划变量,目标是最大化该变量,预期求解器返回30。但实际运行后输出:
solution: null
score: 0hard/0soft
以下是代码实现:
规划实体与规划变量
@PlanningEntity public class variable { @PlanningVariable(valueRangeProviderRefs = "xRange") private Integer x; public variable() { } public Integer getX() { return x; } public void setX(Integer x) { this.x = x; } }
规划解决方案
@PlanningSolution public class Planningsolution { @PlanningEntityProperty private variable variable; @ValueRangeProvider(id="xRange") public CountableValueRange<Integer> getxRange(){ return ValueRangeFactory.createIntValueRange(1, 30); } @PlanningScore private HardSoftScore score; public Planningsolution() { } public variable getVariable() { return variable; } public void setVariable(variable variable) { this.variable = variable; } public HardSoftScore getScore() { return score; } public void setScore(HardSoftScore score) { this.score = score; } }
约束提供器
public class SimpleConstraintProvider implements ConstraintProvider { @Override public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { return new Constraint[] { maxValue(constraintFactory), }; } private Constraint maxValue (ConstraintFactory constraintFactory) { return constraintFactory.forEach(variable.class) .reward("maximum", HardSoftScore.ONE_SOFT,variable::getX); } }
主程序
public class SimpleApp { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleApp.class); public static void main(String[] args) { SolverFactory<Planningsolution> solverFactory = SolverFactory.create(new SolverConfig() .withSolutionClass(Planningsolution.class) .withEntityClasses(variable.class) .withConstraintProviderClass(SimpleConstraintProvider.class) .withTerminationSpentLimit(Duration.ofSeconds(10))); // Load the problem Planningsolution problem = new Planningsolution(); // Solve the problem Solver<Planningsolution> solver = solverFactory.buildSolver(); Planningsolution solution = solver.solve(problem); // Visualize the solution System.out.println("solution: " + display(solution) + "\n" + "score: " + solution.getScore());; } public static Integer display(Planningsolution solution) { variable var = new variable(); return var.getX(); } }
Logback配置
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="appender" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d [%t] %-5p %m%n</pattern> </encoder> </appender> <logger name="org.optaplanner" level="info"/> <root level="warn"> <appender-ref ref="appender"/> </root> </configuration>
问题排查与修复
规划实体未初始化
创建Planningsolution对象时,未初始化内部的variable属性,OptaPlanner无法处理空的实体实例,导致无求解结果。
修复主程序的问题初始化代码:// Load the problem Planningsolution problem = new Planningsolution(); problem.setVariable(new variable()); // 初始化规划实体display方法逻辑错误
当前方法新建空的variable实例,而非从解决方案中获取已求解的实体,必然返回null。
修复display方法:public static Integer display(Planningsolution solution) { return solution.getVariable().getX(); }取值范围边界错误
createIntValueRange(1, 30)是左闭右开区间,实际取值范围为1-29,无法达到预期的30。调整取值范围:@ValueRangeProvider(id="xRange") public CountableValueRange<Integer> getxRange(){ return ValueRangeFactory.createIntValueRange(1, 31); // 右边界改为31,包含30 }代码规范优化(非功能影响)
- Java类名遵循大驼峰命名:
variable→Variable,Planningsolution→PlanningSolution - 规划变量添加
nullable = false约束(若变量不允许为空):@PlanningVariable(valueRangeProviderRefs = "xRange", nullable = false) private Integer x;
- Java类名遵循大驼峰命名:
修复后预期输出
solution: 30
score: 0hard/30soft
内容的提问来源于stack exchange,提问作者yassine
相关产品推荐
相关产品推荐

