求解与配置¶
先阅读路径选择确认模型兼容性。一次性求解返回 Solution 并将本次解的值写入模型;业务代码应先检查 feasible。交互式入口返回会话,在 finish() 时写回最终解。
solve · 本地搜索¶
solution = model.solve(
time_limit_s=30.0,
objective_threshold=None,
log_level="on",
external_evaluation_limit=None,
memory_limit_bytes=None,
deterministic=True,
evaluation_limit=None,
random_seed=1,
worker_threads=None,
)
| 参数 | 默认值 | 约束 / 含义 |
|---|---|---|
time_limit_s |
30.0 |
正数且有限;秒,包含序列化和编译 |
objective_threshold |
None |
目标索引到有限数值的映射;索引从零开始 |
log_level |
"on" |
"off"、"on"、"debug" |
external_evaluation_limit |
None |
可选正整数,限制实际启动的外部回调次数(失败也计入),已知结果和复用不额外计费 |
memory_limit_bytes |
None |
默认自动管理内存;正整数可设置管理内存的字节上限,最大为 sys.maxsize |
deterministic |
True |
按固定逻辑顺序推进并行搜索,内部修复使用工作限额;设为 False 使用吞吐模式 |
evaluation_limit |
None |
可选正整数,限制搜索评价和内部试算;不包含初始化评价 |
random_seed |
1 |
随机种子,整数,范围为 0 到 2**64 - 1 |
worker_threads |
None |
可选正整数,范围为 1 到 1024;默认采用机器报告的硬件并发数 |
需要重复得到相同结果时,固定模型、种子、线程配置、运行版本和评价预算,并为完成工作留出足够时间:
solution = model.solve(
deterministic=True,
evaluation_limit=10000,
random_seed=1,
worker_threads=4,
time_limit_s=120,
)
solution.diagnostics["deterministic_completed"] 表示本次确定性工作正常完成。
若时间到期、取消、发生资源压力或执行失败,该值为 False,返回已有认证解,但不保证终态与其他运行相同。
相同秒数可能完成不同数量的工作,因此仅固定时间和种子不能保证完全相同的结果。
确定性模式暂不支持外部 Python 回调,也不运行依赖时间预算的 HiGHS 搜索路径;
模型包含外部回调时需显式传入 deterministic=False。它保留并行计算,但同步和搜索反馈顺序可能影响耗时与解质量。
默认启用确定性模式;model.solve(deterministic=False) 可切回吞吐模式。
该模式尚未通过性能与解质量无回退验收,是否适合业务模型应通过同时间预算的对照验证。
默认根据系统和容器可用内存调整搜索并发,在压力出现时回收缓存、降低并发,余量恢复后逐步增加并发。
例如 model.solve(memory_limit_bytes=2 * 1024**3) 将管理内存的目标限制在 2 GiB 以内;系统余量不足时实际目标可能更低。
该参数覆盖搜索工作区、候选存储和算法辅助空间,是协作式估算目标,不是整个进程的硬内存上限。
模型编译、Python、外部求解器和单次临时分配仍可能产生额外占用。资源不足时会保留已有的已验证结果,
通过 solution.diagnostics["termination_reason"] 报告 memory_limit,不表示模型无解。
solution.diagnostics["memory_policy"] 提供实际预算、资源来源、探测回退以及并发收缩和恢复次数。
系统资源无法探测时使用至多 256 MiB 的保护目标,并标记 probe_fallback。
solution.feasible=False 表示本次没有交付可行解。到达时间限制且没有可行解时,
solution.status 为 deadline;其他终止情况保留其停止原因。
当前原生搜索路线不交付全局不可行证明,diagnostics 中的 globally_infeasible 为 False;
没有找到可行解时不会据此返回 infeasible。
interactive_solve · 暂停、改解与续跑¶
交互式求解沿用支持暂停、改解和续跑的异步吞吐路径。
from optagent import OptModel, interactive_solve
model = OptModel()
x = model.int(0, 100, default=80)
model.minimize(x * x)
with interactive_solve(model, wall_time_limit_s=60, log_level="off") as session:
outcome = session.run_for(0.1)
if not outcome.finished:
outcome[x] = max(0, outcome[x] - 1)
evaluated = session.evaluate(outcome)
if evaluated.feasible and evaluated.improves_incumbent:
receipt = session.submit(outcome)
print(receipt.status)
outcome = session.run_for(0.1)
result = session.finish()
使用建模时声明的变量定位值:outcome[x] 读取,outcome[x] = value 修改。
已有业务索引可以直接使用,例如 outcome[start_times[job]] = 20。
修改立即可读;x.value 在会话结束前仍表示上一次终态解。
入口参数按名称传入:
| 参数 | 默认值 | 含义 |
|---|---|---|
wall_time_limit_s |
None |
可选正数,单位秒;总墙钟预算,包含序列化、初始化、搜索、暂停和评价;默认不限总时间 |
objective_threshold |
None |
与 solve 相同;提交达到阈值后也会终结搜索 |
log_level |
"on" |
"off"、"on"、"debug" |
external_evaluation_limit |
None |
搜索和交互评价共用的外部函数调用额度 |
memory_limit_bytes |
None |
与 solve 相同的受管内存预算,包含交互评价;Python 导出的值不计入该预算 |
会话操作¶
| 操作 | 返回及约束 |
|---|---|
session.run_for(seconds) |
返回 SolveOutcome;从可搜索状态开始计时,到期请求安全暂停,保留搜索资源 |
session.evaluate(outcome, timeout_s=None) |
返回 EvaluationReport;对当前暂停轮次的完整候选原生验解,不改变全局最优 |
session.submit(outcome) |
返回 SubmissionReceipt;只能提交最后一次修改后已成功验解的当前候选 |
session.cancel() |
非阻塞请求终结,可在另一线程或外部函数中调用;之后用 finish/close 等待清理 |
session.finish() |
终结并返回最后一个认证的 Solution;重复调用返回同一个结果 |
session.close() |
幂等关闭;with 退出时自动调用 |
暂停和取消均为协作式操作;在途任务、外部函数及结果排空可能延长返回时间。
timeout_s 只限制本次评价;到期的评价不提交,若会话总预算仍有效,可继续修改和评价。
已经执行的 Python 外部函数必须自行返回,无法被硬中断。
outcome 的读写与认证¶
SolveOutcome.finished 表示返回时搜索已终结,与可行性分开。
feasible、objectives 是当前版本的认证结果;修改后均变为 None,成功评价后恢复。
revision 记录成功修改次数,incumbent_version 记录创建 outcome 时的全局版本。
非法赋值不改变原值、版本或证书;无认证赋值的终结结果读取决策时抛出 RuntimeError。
标量遵守声明的类型和范围。list 读取返回 tuple,set 返回 frozenset;区间读取为不可变映射,
缺席的可选区间为 None。修改集合需要整体赋值,例如:
变量必须属于原模型且是决策变量。跨变量约束在完整评价时检查,因此可以先修改多个变量再评价。
EvaluationReport 提供 feasible、objectives、improves_incumbent、revision,以及
constraint_violations、hard_structure_violations、undefined_constraints、
undefined_objectives 四项计数。
SubmissionReceipt.accepted 表示实际接纳,status 为 accepted、infeasible 或
not_improving,incumbent_version 是提交后的全局版本。相等目标默认不替换。
未评价、过期或已经终结的提交抛出 RuntimeError,其他会话的 outcome 抛出 ValueError。
每次赋值会使旧证书失效;修改 Python 中的评价报告不会改变原生认证结果。
续跑不会自动提交修改。旧 outcome 保留原值供读取,但不能在之后的暂停轮次提交。
评价和提交期间修改该 outcome 会立即失败;同时运行第二个控制操作也会失败,cancel 除外。
模型声明在整个会话中冻结;外部函数对相同输入的含义也必须保持稳定。
当前仅原生搜索支持此会话接口,其他求解入口仍使用各自的一次性调用方式。
最终 result.diagnostics["interactive"] 包含暂停数、评价尝试/完成数、接纳数,
以及主动搜索、暂停排空、暂停等待、交互评价和 outcome 导出的纳秒计时。
暂停等待包含交互评价时间,两者不能重复相加。
solve_optx · HiGHS¶
from optagent import OptxConfig
solution = model.solve_optx(
config=OptxConfig(time_limit=30.0, mip_rel_gap=0.01, threads=4),
objective_threshold=None,
)
config=None 使用默认配置;包装层未配置时间限制时采用 30 秒。
未指定 threads 或传入 None 时,保留 HiGHS 的 threads=0 自动选择与线程池复用;
未指定 parallel 时保留原生 "choose"。包装层不再按模型规模、整数域或剩余时间推导线程数,
也不额外估算 CPU 配额。受限运行环境可显式设置 threads。
正整数线程数和原生选项始终优先,例如 OptxConfig(threads=4, parallel="on")。
4 和 8 都不是后端最低要求;threads=1 限制后端线程池为单线程。
固定版本中,MIP 树并行需要显式 parallel="on" 且线程数大于 1;默认 "choose" 不自动开启它。
MIP 树并行开启后,默认采用 mip_parallel_strategy="neighborhood",在有可行候选时分配一个 worker 搜索整数邻域。
需要原版树搜索策略时,可设置 OptxConfig(threads=4, parallel="on", mip_parallel_strategy="standard")。
策略效果与模型有关;邻域搜索可能改善候选发现,也可能增加成本。
neighborhood 的协作调度允许搜索轨迹变化,固定 seed 不保证节点和 LP 迭代数一致;standard 保留原版同步调度。
辅助累计预算 mip_neighborhood_budget 默认为 60 秒,时间片 mip_neighborhood_slice 默认为 10 秒,均采用协作式停止。
预算耗尽或没有有效邻域后,worker 返回树搜索;预算为 0 时只禁用辅助任务,完整回退应选择 standard。
这三个实际参数可在 solution.diagnostics["backend_attempts"] 中查询,LP 调用对应值为 None。
连续凸 QP 在 HiPO 可用时默认优先使用 solver="hipo",不按二次变量数量设分界。
HiPO 报错、返回 Unknown 或候选未通过原模型数值核验时,使用剩余总预算尝试一次 ASM,
保留两次尝试中已通过核验且原目标更好的候选。两次调用共享时限,切换不改变容差、线程或并行选项。
LP/MIP 保留原生算法;显式 solver 优先,显式选择的算法不会自动切换。
例如 OptxConfig(solver="qpasm") 固定使用 ASM,适合已确认受益的高频小 QP。
HiPO 默认编入;不可用时自动保留原生 QP 路线,显式请求不可用的 HiPO 会报错。
组合搜索内部 worker 继续遵守既有调度与线程配置。
backend_attempts 记录从实际 Highs 对象读回的顶层 solver、parallel、threads,
以及 algorithm_source 和 quadratic_variables;hipo_available 表示构建能力。
ASM 备选记录的 phase 为 "qp_asm_fallback",fallback_reason 为 "backend_error"、
"unknown" 或 "numerical_verification";time_limit_s 是该次后端调用的剩余时间额度。
verification.candidate_phase 表示最终交付候选来自哪一次尝试,不一定是最后一次调用。
threads=0 表示原生自动选项,不是观测到的活跃线程数,已有线程池可能继续复用。
这些字段也不代表 MIP 子求解器的实时配置或整个进程的线程硬上限。
mip_rel_gap 必须有限且非负;其他原生参数的有效性由求解路径与后端检查。
OptX 的模型转换资源配置与 HiGHS 参数分别传递,可通过以下参数控制:
| 参数 | 默认值 | 计量范围 |
|---|---|---|
max_variables |
1,000,000 | 标量变量,包含展开产生的辅助变量 |
max_constraints |
2,000,000 | 转换生成的约束行 |
max_nonzeros |
20,000,000 | 稀疏系数,包含转换工作区 |
max_compile_bytes |
2,147,483,648 | 矩阵与转换工作区的估算字节数 |
max_collection_slots |
4,096 | 有限集合展开槽位 |
max_quadratic_work |
50,000,000 | 每个二次目标的表达式展开、合并和凸性证明操作 |
这些参数必须是正整数;字节数上限为 2**63 - 1,其他计数上限为 2**31 - 1。字节预算不包含原始模型和后端搜索内存,也不是进程内存硬限制。
例如 OptxConfig(max_variables=500_000, max_compile_bytes=3 * 1024**3)。
超限时抛出 OptxUnsupportedError,问题详情包含转换阶段、实际规模、上限和来源。
二次操作预算与约束行数独立;多项式缓存、临时结果及凸性证明的 Schur 填充同样受非零项和估算字节预算限制。
超限不跳过凸性证明,也不放宽数值容差。
仿射和二次长链式加法可直接转换,无需通过增加 Python 递归上限来支持。
静态 lambda 调用、聚合、map 和固定数组下标行可与连续凸二次目标组合;二次目标仍只能排在最后优先级。
根合取及布尔条件选中的闭比较可直接转为约束行;连续比较作为一般条件或布尔值时仍受原有限制。
大数组的 Count、固定一维下标及适用的纯符号调用可按需读取;请求完整容器仍计入原集合槽位预算。
完整整数派生集合和 List 使用压缩表示,保留原顺序、唯一性和结果恢复语义。
整数常数除模可避免逐值建表;// 向负无穷取整,% 的余数跟随分子符号。
最小化 abs、max 和最大化 min 的适用单调目标可保留为连续模型,
也可与连续凸 QP 组合。表达式被一般约束、反向目标或除法等精确运算复用时,仍要求完整函数图和所需有限界。
整数时间轴上的适用区间加权和、根 All 资源比较按覆盖长度或起止事件转换,
支持缺席、零长度及不依赖时间的动态整数需求;一般时间相关函数仍受通用展开预算限制。
凸性核验无法完成时报告 quadratic_convexity_unverified,与已确认非凸的
nonconvex_quadratic_objective 区分;两者均不进入后端求解。
未知选项、后端不接受的值或超出允许范围的值会抛出 ValueError,包含选项名与传入值;
即使模型没有决策变量也会检查。主搜索保留 HiGHS 原生数值默认值:
primal_feasibility_tolerance=1e-7、dual_feasibility_tolerance=1e-7、
mip_feasibility_tolerance=1e-6、small_matrix_value=1e-9。
显式配置的有效值会传给后端并从后端读回记录。
1e-11 低于后端允许下限,不能用来进一步收紧 primal 和 MIP 可行性容差。
可以显式配置 MIP 容差,并按需查询本次运行实际记录的有效值:
solution = model.solve_optx(
config=OptxConfig(mip_feasibility_tolerance=1e-7),
)
verification = solution.diagnostics.get("verification", {})
if solution.feasible and verification.get("performed"):
print(verification["tolerance"], verification["max_row_violation"])
primal_feasibility_tolerance=1e-5 不会把 MIP 原模型验解容差改成 1e-5。
mip_strict_numerics=True 收紧内部 LP 的数值策略,也不会自动将 MIP 候选验解容差改成 1e-10。
无候选或未完成验解时,verification.tolerance 的占位值不能作为有效验收容差。
不同输入格式、显式配置、重试阶段和平台的验证报告,应分别列明这些条件。
OptX 使用固定提交的个人 HiGHS fork,MIP 默认启用 mip_strict_numerics;
可显式设为 False 使用后端兼容策略。HiGHS 的顶层 LP 容差不直接控制 MIP 的 LP 松弛:
兼容模式的松弛 primal 容差取 MIP 容差,
dual 容差取 max(1e-10, MIP 容差 * 0.1);严格模式的内部 primal 容差不大于 1e-10,
dual 容差为 1e-10。候选的 MIP 可行性容差仍默认 1e-6。
显式顶层容差与内部策略不同时,或显式开启严格模式时,求解前发出 RuntimeWarning。
OptxConfig(numerical_recheck=False) 默认禁止因不可行报告或验解失败而提高精度重跑主搜索。
需要时可显式设为 True;启动前会告知采用的严格 MIP 容差,重试共享剩余总预算。
原模型的约束和变量域始终验解,不能通过验证的候选不会作为可行解交付。
受限修复后的最优性认证可能使用更严格的 LP 精度,启动前告知并单独记录
certification_started、certification_time_s。严格 MIP 路径的后端不可行结论保留为 infeasible;
显式选择兼容策略且未严格复核时,其不可行报告返回 unknown,原始状态仍可查询。
该选项不控制自动 QP 的 HiPO→ASM 切换;后者保持原精度,也不重新分配总时限。
不支持的模型抛出 OptxUnsupportedError,可读取 .issues 中的约束 / 目标名称、表达式路径和限制说明。该入口不回退到本地搜索。
返回值必须通过原模型验解。后端结果只有很小的数值误差时,求解器可固定整数并受限地调整连续变量,
重新检查全部约束和变量边界,并在同一修复范围内按原目标精修。目标值按最终赋值计算。
对有限域标量、单个仿射目标模型,OptX 使用覆盖原表达式舍入误差的全域放松重新求界;
最终可行解与有效全局界的差距达到声明精度时返回 optimal,否则返回 feasible。
精度由 OptxConfig(optimality_abs_tol=1e-8, optimality_rel_tol=1e-10) 配置,
允许间隙为两者中较大者,其中相对精度乘以 max(1, abs(目标值), abs(全局界))。
这两项不放宽约束或变量域。修复后的展开、二次和多目标模型当前保留 feasible。
solution.diagnostics 中的 numerical_repair、repaired_decisions 和 maximum_repair
分别说明是否修复、修复的决策数量和最大改动。
solution.status 描述最终交付结果;solution.diagnostics["backend_status"]
单独保存最后一次 HiGHS 运行的原始状态文本,例如 "Optimal"、"Infeasible"。
optimality_certified 说明修复后是否通过再次认证,optimality_bound、optimality_gap、
optimality_tolerance 给出界、实际间隙和允许间隙;optimality_method、optimality_reason
说明认证方法或未认证原因。未修复但仅容差可行的候选也会保留 feasible,
不会因后端返回 Optimal 就变为 optimal;最终结论和后端信息的读取方式见结果与诊断。
backend_objectives 保存修复前的线性化目标值,便于与最终原图目标比较。
solution.best_bound、solution.gap、solution.solve_time 提供后端报告的单目标界限、
相对间隙比值和搜索运行秒数,对应诊断的 backend_best_bound、backend_gap、
backend_solve_time_s。它们未经独立认证,不替代 optimality_bound 或 optimality_gap。
后端间隙以修正前的后端候选目标计算,可能与最终交付赋值不同;不可用时返回 None。
多目标模型没有单一后端界限或间隙,只按阶段提供运行记录。
backend_attempts 按运行顺序记录原始 status、status_code、
primal_feasibility_tolerance、dual_feasibility_tolerance、mip_feasibility_tolerance、
small_matrix_value,以及 requested_numerics、phase、numerical_warnings 和
infeasibility_recheck、verification_recheck。顶层 backend_status_code 对应最后一次运行,
infeasibility_rechecked、verification_rechecked 分别表示是否因不可行报告、
原模型验解失败而执行过严格容差复核。
每次运行还记录 objective_index、objective_value、best_bound、gap 和 solve_time_s。
目标值和界限已恢复为原目标的最小化或最大化方向;缺失或非有限值返回 None。
没有实际进入 HiGHS 时,原始状态和状态码为 None,运行记录为空。
运行记录还包含 mip_strict_numerics 与 mip_proof_feasibility_tolerance,后者描述
预处理和 LP 原始可行性计算的策略精度;mip_lp_dual_tolerance 记录对应 dual 策略。
这些 MIP 内部值根据固定后端策略推导,mip_precision_source="pinned_backend_policy"、
mip_subsolver_options_observed=False 明确表示未直接观测运行中的内部 LP 对象。
顶层数值选项则由实际 Highs 对象读回。
backend_repository、backend_revision、backend_version、backend_githash
记录依赖来源及实际内核身份,避免只凭版本字符串判断是否包含修复。
原模型验证仍失败时抛出 RuntimeError,可读取异常的 .diagnostics。
其中 verification_failures 至多包含 64 个失败项,提供 kind、expression_id、name、
lhs、rhs 和 residual;compiled_constraint_index 是编译后的约束序号。
用户原始模型的约束宜通过名称和表达式 ID 定位。
整数取整可能使关联连续变量违反原约束。独立 OptX 可固定取整后的整数,在受限邻域内联合
修正连续变量,然后重新检查全部原约束、布尔条件和变量域;不提高交付容差,也不改变主搜索
选项。修正目标留出数值余量,修正阶段共享剩余预算,最多使用两秒后端运行时间。
verification 中的 completion_attempted、completion_succeeded、completion_status、
completion_time_s 记录这一步。修正不能通过全量验解时仍拒收候选。
solve_cpsat · OR-Tools CP-SAT¶
from optagent import CpSatConfig
solution = model.solve_cpsat(
config=CpSatConfig(num_search_workers=4, random_seed=1),
time_limit_s=30.0,
)
CpSatConfig 参数 |
说明 |
|---|---|
max_time_in_seconds |
未显式传入 time_limit_s 时的总预算来源 |
num_search_workers |
CP-SAT 工作线程设置 |
random_seed |
后端随机种子 |
relative_gap_limit / absolute_gap_limit |
相对 / 绝对间隙限制 |
log_search_progress / log_to_stdout |
后端日志设置 |
| 其他关键字参数 | 传递给 CP-SAT 原生参数 |
配置中值为 None 的选项不传递。显式 time_limit_s 优先,未设置时依次使用配置中的时间限制和 30 秒默认值。
solve_mathopt · OR-Tools MathOpt¶
from optagent import MathOptConfig
solution = model.solve_mathopt(
config=MathOptConfig(solver_type="GSCIP", threads=4),
time_limit_s=30.0,
)
MathOptConfig 参数 |
说明 |
|---|---|
solver_type |
默认 "GSCIP",所选后端须可用且支持模型 |
time_limit |
秒数或 datetime.timedelta;显式总预算未设置时采用 |
threads |
后端线程设置 |
relative_gap_tolerance / absolute_gap_tolerance |
相对 / 绝对间隙容差 |
| 其他关键字参数 | 传递给 MathOpt 原生求解参数 |
CP-SAT 和 MathOpt 的顶层入口不接受 objective_threshold。预算覆盖整个转换、求解与验证流程;验证前超时返回 UNKNOWN,没有可读变量值。
检查配置与结果¶
CpSatConfig.to_parameters()、MathOptConfig.to_parameters() 和 OptxConfig.to_options() 返回已设置选项的字典。MathOpt 的后端选择单独保存在 solver_type 中,不在 to_parameters() 字典内。
结果字段与状态处理见结果与诊断。