跳转至
OptAgent 1.2.0

快速入门

快速入门用三个小例子说明 OptAgent 的三条公开调用路径。完整代码维护在 公开示例仓库的固定提交中。

1. 统一建模与 solve

先使用 ModelBuilder 描述变量、约束和目标,再调用通用入口 solve(...)

examples/quickstart/unified_solve.py
from __future__ import annotations

from optagent import ModelBuilder, solve


def build_model() -> ModelBuilder:
    builder = ModelBuilder(metadata={"case": "quickstart_unified_solve"})
    choose_a = builder.bool_var(name="choose_a")
    choose_b = builder.bool_var(name="choose_b")
    builder.constraint(choose_a + choose_b <= 1, name="capacity")
    builder.maximize(choose_a * 3 + choose_b * 2, name="profit")
    return builder


def main() -> None:
    solution = solve(build_model(), time_limit_s=10, seed=7, threads=1, log_level="off")
    print({"status": solution.status.value, "objective": solution.objective_values})


if __name__ == "__main__":
    main()

完整文件:unified_solve.py

这条路径适合先验证问题表达,也适合目标或约束包含外部函数的模型。它不 自动等价于某个精确后端。

2. 线性模型的 solvesolve_optx

同一个线性模型可以先通过通用 solve(...) 验证,也可以明确选择 OptX 精确 路径。两条调用的求解语义不同:前者是通用搜索路径,后者要求模型完整落在 OptX 支持的线性 / 混合整数表达范围内。

examples/linear/quickstart_linear_routes.py
from __future__ import annotations

from optagent import ModelBuilder, OptxConfig, solve, solve_optx


def build_model() -> ModelBuilder:
    builder = ModelBuilder(metadata={"case": "quickstart_linear_routes"})
    worker_a = builder.bool_var(name="worker_a")
    worker_b = builder.bool_var(name="worker_b")
    builder.constraint(worker_a + worker_b <= 1, name="capacity")
    builder.maximize(worker_a * 8 + worker_b * 6, name="profit")
    return builder


def main() -> None:
    heuristic_solution = solve(build_model(), time_limit_s=10, seed=7, threads=1, log_level="off")
    exact_solution = solve_optx(
        build_model(),
        config=OptxConfig(time_limit_s=10, threads=1),
    )
    print(
        {
            "solve": heuristic_solution.objective_values,
            "solve_optx": exact_solution.objective_values,
        }
    )


if __name__ == "__main__":
    main()

完整文件:quickstart_linear_routes.py

3. 调度模型的统一求解

调度模型也可以直接使用统一的 solve(...) 入口,不需要额外安装第三方求解器。

examples/scheduling/job_shop_small.py
from __future__ import annotations

from pathlib import Path
import sys

from optagent import ModelBuilder, solve

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from _common import print_solution


def build_model() -> tuple[object, dict[str, int]]:
    builder = ModelBuilder(metadata={"case": "job_shop_small"})
    machine_a = builder.sequence_var(size=2, default=[0, 1], name="machine_a")
    machine_b = builder.sequence_var(size=2, default=[0, 1], name="machine_b")

    job1_a = builder.interval_var(start=0, length=2, lb_start=0, ub_start=8, lb_length=2, ub_length=2, name="job1_a")
    job1_b = builder.interval_var(start=0, length=3, lb_start=0, ub_start=10, lb_length=3, ub_length=3, name="job1_b")
    job2_b = builder.interval_var(start=0, length=2, lb_start=0, ub_start=8, lb_length=2, ub_length=2, name="job2_b")
    job2_a = builder.interval_var(start=0, length=2, lb_start=0, ub_start=10, lb_length=2, ub_length=2, name="job2_a")

    builder.constraint(builder.no_overlap(machine_a, job1_a, job2_a), name="machine_a_capacity")
    builder.constraint(builder.no_overlap(machine_b, job1_b, job2_b), name="machine_b_capacity")
    builder.constraint(builder.precedence(job1_a, job1_b, lag=0), name="job1_flow")
    builder.constraint(builder.precedence(job2_b, job2_a, lag=0), name="job2_flow")
    builder.minimize(builder.max(builder.interval_end(job1_b), builder.interval_end(job2_a)), name="makespan")
    return builder.freeze(), {"machine_a": machine_a.node_id, "machine_b": machine_b.node_id}


def main() -> None:
    program, sequence_ids = build_model()
    solution = solve(program, time_limit_s=10.0, seed=7, threads=1, log_level="on")
    print_solution("small job shop solved by unified solve", solution, extra={"machine_sequences": sequence_ids})


if __name__ == "__main__":
    main()

完整文件:job_shop_small.py

该示例使用 interval_varno_overlapprecedence 表达基础 Job Shop, 最后调用 solve(...)。典型调度问题页会进一步介绍何时使用 SchedulingModel 专用接口。

下一步