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

如何为TimeFold求解器实现无1%分数提升即终止的动态逻辑

TimeFold 实现连续无分数提升终止器指引

核心思路

实现自定义终止器,跟踪最佳分数变化:当连续30秒内分数提升未达1%时触发求解终止;若分数提升达标,则重置计时继续计算。如需保留原30秒总时长限制,可将两个终止器组合为OR逻辑。

步骤1:编写自定义终止器类

创建ScoreImprovementThresholdTermination类,继承AbstractTermination处理分数跟踪与终止判断:

import org.optaplanner.core.api.score.hardsoft.HardSoftScore;
import org.optaplanner.core.impl.termination.AbstractTermination;
import org.optaplanner.core.impl.solver.scope.SolverScope;
import java.time.Duration;

public class ScoreImprovementThresholdTermination extends AbstractTermination<EmployeeSchedule> {
    // 配置参数:连续无提升时长、分数提升阈值(1%即0.01)
    private Duration noImprovementSpentLimit;
    private double scoreImprovementThreshold;

    // 状态变量:最后一次分数提升时间、当前最佳分数
    private long lastImprovementTimeMillis;
    private HardSoftScore bestScore;

    @Override
    public void solvingStarted(SolverScope<EmployeeSchedule> solverScope) {
        super.solvingStarted(solverScope);
        // 初始化求解开始状态
        lastImprovementTimeMillis = System.currentTimeMillis();
        bestScore = (HardSoftScore) solverScope.getBestScore();
    }

    @Override
    public boolean isTerminated(SolverScope<EmployeeSchedule> solverScope) {
        HardSoftScore currentBestScore = (HardSoftScore) solverScope.getBestScore();
        long currentTimeMillis = System.currentTimeMillis();

        // 判断分数是否有1%以上提升(示例以软分数为优化目标,可按需调整)
        boolean hasQualifiedImprovement = false;
        int currentSoft = currentBestScore.getSoftScore();
        int bestSoft = bestScore.getSoftScore();

        if (currentSoft > bestSoft) {
            double improvementRate = (double) (currentSoft - bestSoft) / Math.abs(bestSoft);
            if (improvementRate >= scoreImprovementThreshold) {
                hasQualifiedImprovement = true;
            }
        }

        // 更新状态或判断终止
        if (hasQualifiedImprovement) {
            lastImprovementTimeMillis = currentTimeMillis;
            bestScore = currentBestScore;
            return false; // 继续求解
        } else {
            long timeElapsed = currentTimeMillis - lastImprovementTimeMillis;
            return timeElapsed >= noImprovementSpentLimit.toMillis();
        }
    }

    // 配置参数注入方法(TimeFold自动绑定配置值)
    public void setNoImprovementSpentLimit(Duration noImprovementSpentLimit) {
        this.noImprovementSpentLimit = noImprovementSpentLimit;
    }

    public void setScoreImprovementThreshold(double scoreImprovementThreshold) {
        this.scoreImprovementThreshold = scoreImprovementThreshold;
    }
}

步骤2:配置终止器(两种方式选其一)

方式1:编程式配置(灵活可控)

创建Solver配置类,注册自定义终止器并组合原有总时长限制:

import io.quarkus.timefold.solver.SolverConfigurer;
import org.optaplanner.core.config.solver.SolverConfig;
import org.optaplanner.core.config.termination.TerminationConfig;
import org.optaplanner.core.config.termination.TerminationCompositionStyle;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.List;

@ApplicationScoped
public class EmployeeScheduleSolverConfigurer implements SolverConfigurer<EmployeeSchedule> {

    @Override
    public void configure(SolverConfig solverConfig) {
        // 组合终止器:总时长30秒 OR 连续30秒无1%分数提升
        TerminationConfig combinedTermination = new TerminationConfig()
                .withTerminationCompositionStyle(TerminationCompositionStyle.OR)
                .withTerminationList(List.of(
                        new TerminationConfig().withSpentLimit("30s"),
                        new TerminationConfig()
                                .withTerminationClass(ScoreImprovementThresholdTermination.class)
                                .withParameter("noImprovementSpentLimit", "30s")
                                .withParameter("scoreImprovementThreshold", "0.01")
                ));
        solverConfig.setTerminationConfig(combinedTermination);
    }
}

方式2:配置文件(application.properties)

直接通过配置绑定自定义终止器:

# 可选:保留总时长限制
quarkus.timefold.solver.termination.spent-limit=30s
quarkus.timefold.solver.termination.composition-style=OR

# 自定义终止器配置
quarkus.timefold.solver.termination.termination-class=com.yourpackage.ScoreImprovementThresholdTermination
quarkus.timefold.solver.termination.no-improvement-spent-limit=30s
quarkus.timefold.solver.termination.score-improvement-threshold=0.01

关键注意事项

  • 分数类型适配:若使用SimpleScore、HardMediumSoftScore等其他分数类型,需修改代码中的分数转换与计算逻辑。
  • 提升率逻辑调整:示例以软分数为优化目标,若业务关注硬分数或综合分数,可修改isTerminated方法中的分数对比逻辑。
  • 组合终止器逻辑:使用OR时任一条件满足即终止;需同时满足两个条件才终止可改为AND。

内容的提问来源于stack exchange,提问作者I. Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 17:55:53