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

如何通过CPO Optimizer Python API保存日志与中间解以生成优化演化图表?

解决CPO Optimizer Python API记录中间解与时间戳的方案

当然有办法,下面是两种实用的方案,都能帮你记录中间解和时间戳,进而构建优化过程演化图表:

方案一:自定义回调函数(推荐,灵活可控)

CPO Optimizer的Python API支持通过自定义回调函数,在每次找到新的可行解或改进解时触发逻辑,直接记录时间戳、目标值甚至完整变量解。

实现步骤:

  1. 继承CpoCallback类,重写notify_solution方法,在该方法中捕获解信息与时间;
  2. 实例化自定义回调类,在求解时传入callbacks参数;
  3. 求解完成后,从回调对象中提取数据,保存为文件或直接用于绘图。

代码示例:

from docplex.cp.model import CpoModel
from docplex.cp.callback import CpoCallback
import time
import csv
import matplotlib.pyplot as plt

# 自定义回调类,用于记录中间解
class SolutionLogger(CpoCallback):
    def __init__(self):
        super().__init__()
        self.solution_history = []  # 存储格式:(耗时秒数, 目标值, 变量值字典)
    
    def notify_solution(self, solution):
        # 获取优化启动以来的耗时
        elapsed_time = self.get_cpo_info().get_elapsed_time()
        # 获取当前解的目标值
        objective_value = solution.get_objective_value()
        # 提取所有变量的取值
        var_values = {var.get_name(): solution.get_value(var) for var in self.model.get_all_variables()}
        # 存入历史记录
        self.solution_history.append((elapsed_time, objective_value, var_values))

# 构建你的CPO模型(这里以简单示例为例)
model = CpoModel()
x = model.integer_var(0, 20, "x")
y = model.integer_var(0, 20, "y")
model.add(x + y >= 10)
model.minimize(3*x + 2*y)

# 实例化回调并求解
solution_logger = SolutionLogger()
solve_result = model.solve(agent='local', callbacks=[solution_logger])

# 将记录保存为CSV文件
with open('cpo_optimization_history.csv', 'w', newline='') as csv_file:
    writer = csv.writer(csv_file)
    # 写入表头
    writer.writerow(["Elapsed Time (s)", "Objective Value", "x", "y"])
    # 写入每一条记录
    for t, obj, vars in solution_logger.solution_history:
        writer.writerow([round(t, 2), obj, vars["x"], vars["y"]])

# 绘制优化过程演化图
times = [entry[0] for entry in solution_logger.solution_history]
objectives = [entry[1] for entry in solution_logger.solution_history]

plt.figure(figsize=(10, 6))
plt.plot(times, objectives, marker='o', linestyle='-', color='b')
plt.xlabel('Elapsed Time (s)')
plt.ylabel('Objective Value (Minimization)')
plt.title('CPO Optimizer Progress')
plt.grid(True)
plt.show()

方案二:解析CPO日志文件(轻量快速)

如果只需要记录目标值和时间戳,可以直接将CPO的求解日志定向到文件,再通过正则表达式解析日志中的关键信息。

实现步骤:

  1. 求解时将log_output参数设置为文件对象,把日志写入文件;
  2. 读取日志文件,用正则匹配提取中间解的时间和目标值;
  3. 用提取的数据绘图。

代码示例:

from docplex.cp.model import CpoModel
import re
import matplotlib.pyplot as plt

# 构建模型(同方案一示例)
model = CpoModel()
x = model.integer_var(0, 20, "x")
y = model.integer_var(0, 20, "y")
model.add(x + y >= 10)
model.minimize(3*x + 2*y)

# 将日志写入文件
with open('cpo_solve_log.txt', 'w') as log_file:
    solve_result = model.solve(agent='local', log_output=log_file)

# 解析日志文件
log_entries = []
pattern = re.compile(r'! New solution, objective (\d+\.?\d*) \(time (\d+\.?\d*) sec')

with open('cpo_solve_log.txt', 'r') as f:
    for line in f:
        match = pattern.search(line)
        if match:
            obj_val = float(match.group(1))
            elapsed_time = float(match.group(2))
            log_entries.append((elapsed_time, obj_val))

# 绘制演化图
plt.figure(figsize=(10, 6))
plt.plot([t for t, obj in log_entries], [obj for t, obj in log_entries], marker='x', linestyle='--', color='r')
plt.xlabel('Elapsed Time (s)')
plt.ylabel('Objective Value (Minimization)')
plt.title('CPO Optimizer Progress from Log')
plt.grid(True)
plt.show()

注意事项:

  • 回调方案可以获取完整的变量解,适合需要分析变量取值变化的场景;
  • 日志解析方案更轻量,但只能提取日志中显示的信息(默认日志会输出目标值和时间,变量细节需要开启更详细的日志级别);
  • 如果需要绝对时间戳(而非优化耗时),可以在回调的notify_solution方法中用time.time()替代get_elapsed_time()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 07:54:59