You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

问题排查与修复

  1. 规划实体未初始化
    创建Planningsolution对象时,未初始化内部的variable属性,OptaPlanner无法处理空的实体实例,导致无求解结果。
    修复主程序的问题初始化代码:

    // Load the problem
    Planningsolution problem = new Planningsolution();
    problem.setVariable(new variable()); // 初始化规划实体
    
  2. display方法逻辑错误
    当前方法新建空的variable实例,而非从解决方案中获取已求解的实体,必然返回null。
    修复display方法:

    public static Integer display(Planningsolution solution) {
        return solution.getVariable().getX();
    }
    
  3. 取值范围边界错误
    createIntValueRange(1, 30)是左闭右开区间,实际取值范围为1-29,无法达到预期的30。调整取值范围:

    @ValueRangeProvider(id="xRange")
    public CountableValueRange<Integer> getxRange(){
        return ValueRangeFactory.createIntValueRange(1, 31); // 右边界改为31,包含30
    }
    
  4. 代码规范优化(非功能影响)

    • Java类名遵循大驼峰命名:variable → Variable,Planningsolution → PlanningSolution
    • 规划变量添加nullable = false约束(若变量不允许为空):
      @PlanningVariable(valueRangeProviderRefs = "xRange", nullable = false)
      private Integer x;
      

修复后预期输出

solution: 30
score: 0hard/30soft

内容的提问来源于stack exchange,提问作者yassine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 03:58:38