调度问题示例¶
作业调度(Job Shop)— CP-SAT¶
使用 CP-SAT 原生后端求解 2 作业 × 2 机器的作业调度问题。
from optagent import ExactBackendName, ModelBuilder, Orchestrator, OrchestratorConfig, OrchestratorSolver, PhaseConfig
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")
program = builder.freeze()
result = Orchestrator().run(
program,
config=OrchestratorConfig(
required_backend=ExactBackendName.CP_SAT_NATIVE,
strict_backend=True,
phases=[PhaseConfig(name="cp_sat_job_shop", solver=OrchestratorSolver.CP_SAT, budget_iterations=30)],
),
)
运行方式:
流水线调度(Flow Shop)— CP-SAT¶
使用 CP-SAT 求解切割 → 钻孔 → 包装的流水线调度问题。
from optagent import ExactBackendName, ModelBuilder, Orchestrator, OrchestratorConfig, OrchestratorSolver, PhaseConfig
builder = ModelBuilder(metadata={"case": "flow_shop_cp_sat"})
seq = builder.sequence_var(size=3, default=[2, 1, 0], name="machine_order")
cut = builder.interval_var(start=0, length=2, lb_start=0, ub_start=5, lb_length=2, ub_length=2, name="cut")
drill = builder.interval_var(start=0, length=3, lb_start=0, ub_start=6, lb_length=3, ub_length=3, name="drill")
pack = builder.interval_var(start=0, length=1, lb_start=0, ub_start=8, lb_length=1, ub_length=1, name="pack")
builder.constraint(builder.no_overlap(seq, cut, drill, pack), name="machine_capacity")
builder.constraint(builder.precedence(cut, drill, lag=0), name="cut_before_drill")
builder.constraint(builder.precedence(drill, pack, lag=0), name="drill_before_pack")
builder.minimize(builder.interval_end(pack), name="makespan")
program = builder.freeze()
result = Orchestrator().run(
program,
config=OrchestratorConfig(
required_backend=ExactBackendName.CP_SAT_NATIVE,
strict_backend=True,
phases=[PhaseConfig(name="cp_sat_flow_shop", solver=OrchestratorSolver.CP_SAT, budget_iterations=20)],
),
)
运行方式:
使用预设求解调度问题¶
除了手动配置编排器,还可以直接使用预设:
from optagent import BuiltInStrategyPreset, ModelBuilder, Orchestrator
builder = ModelBuilder(metadata={"case": "scheduling_preset"})
machine_a = builder.sequence_var(size=3, default=[0, 1, 2], name="machine_a")
machine_b = builder.sequence_var(size=3, default=[0, 1, 2], name="machine_b")
# ... 定义 interval_var 和约束 ...
program = builder.freeze()
# 使用调度预设 — 自动配置进化搜索 + 局部优化 + 精确修复
result = Orchestrator().run(program, preset=BuiltInStrategyPreset.SCHEDULING_EVOLUTIONARY_REPAIR)
可用的调度预设:
| 预设 | 适用场景 | 特点 |
|---|---|---|
SCHEDULING_FOCUS |
快速可行解 | 单阶段禁忌搜索 |
SCHEDULING_EVOLUTIONARY_REPAIR |
高质量解 | 进化搜索 + 精确修复 |
SCHEDULING_MEMETIC_QUALITY |
最优质量解 | 记忆算法 |
建模要点
sequence_var:定义机器上的作业顺序interval_var:定义每个工序的时间区间no_overlap:同一机器上的工序不能重叠precedence:工序间的先后顺序约束