# ============================================================ # 引擎抽象接口(moduleId: engines-base, 可重生 ✅) # 对应 plan.md §9.1 ISchedulingEngine:多引擎可插拔的统一契约 # ============================================================ from __future__ import annotations # 前向类型引用 from abc import ABC, abstractmethod # 抽象基类工具 from typing import Any # 类型标注 from pydantic import BaseModel, Field # 入参契约校验 from server.contracts import ScheduleResult # 引擎输出契约 class EngineParams(BaseModel): """引擎入参:一次排产请求的全部参数(与 legacy runScheduling params 对齐)。""" orderIds: list[int] = Field(default_factory=list) # 目标订单 ID(空=全部待排) engineType: str = "RULE" # 请求的引擎类型(RULE/CP/GA/HYBRID) strategyTemplate: str = "COMPREHENSIVE" # 策略模板(排序规则) planningHorizonDays: int = 14 # 计划展望期(天) startDate: str | None = None # 排产起始日 YYYY-MM-DD(None=明天) constraints: dict[str, bool] = Field( # 约束开关(M1 实现物料齐套;其余开关保留) default_factory=lambda: {"materialKit": True, "equipment": True, "personnel": True, "changeover": True}) triggerType: str = "MANUAL" # 触发类型(手动/自动滚动) name: str | None = None # 版本名称(可选) class ISchedulingEngine(ABC): """排产引擎统一接口(§9.1):输入订单/主数据/约束,输出版本+工单+冲突+KPI。""" # 引擎标识(子类覆写) name: str = "BASE" # 是否支持时限内产出可行解(anytime,M5 的 CP/LNS 用) supports_anytime: bool = False @abstractmethod def solve(self, world: dict[str, Any], params: EngineParams, next_id) -> ScheduleResult: """执行排产(权力等级 P1:只写传入的 world 字典,落盘由调用方决定)。 Args: world: 世界状态字典(引擎向其中追加版本/PO/WO/冲突/日志) params: 排产参数(EngineParams) next_id: ID 发号函数 next_id(kind)->int(由 WorldStore 提供) Returns: ScheduleResult 排产结果摘要(含证据引用) """ ... # 由具体引擎实现