Files
iAOP/templates/ti-cl4/recipe-optim/_sanity_check.py
T

62 lines
2.0 KiB
Python

# -*- coding: utf-8 -*-
"""Ti-2 配方优化问题建模 自检脚本(Issue #78)。
不依赖 unittest,直接加载模板资产并做能力点断言,便于 CI / 部署期一键核对。
"""
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from problem import ConstraintKind, OptimizationProblem, load_problem # noqa: E402
CONFIG = os.path.join(os.path.dirname(os.path.abspath(__file__)),
"config", "recipe_optim.template.yaml")
def main() -> int:
failures = []
# 1) 模板能加载
p = load_problem(CONFIG)
if not isinstance(p, OptimizationProblem):
failures.append("load_problem 未返回 OptimizationProblem")
# 2) 4 类约束齐全
kinds = {c.kind for c in p.constraints}
expected = {ConstraintKind.BOX, ConstraintKind.LINEAR,
ConstraintKind.RATIO, ConstraintKind.FORBIDDEN}
if kinds != expected:
failures.append(f"约束种类不齐: {kinds} != {expected}")
# 3) 静态校验通过
errs = p.validate()
if errs:
failures.append(f"validate 未通过: {errs}")
# 4) 可行性判定:合法取值可行、禁止组合不可行
ok = p.is_feasible({"clf_temp": 850, "cl2_ratio": 1.0,
"feed_rate": 450, "catalyst": "A"})
bad = p.is_feasible({"clf_temp": 950, "cl2_ratio": 1.0,
"feed_rate": 450, "catalyst": "A"})
if not ok:
failures.append("合法取值被判为不可行")
if bad:
failures.append("越界取值(950℃)未被识别为不可行")
# 5) 序列化往返无损
rt = OptimizationProblem.from_dict(p.to_dict())
if [v.name for v in rt.variables] != [v.name for v in p.variables]:
failures.append("序列化往返丢失变量")
if failures:
print("❌ recipe-optim 自检失败:")
for f in failures:
print(" -", f)
return 1
print("✅ recipe-optim 自检通过(5 能力点)")
return 0
if __name__ == "__main__":
sys.exit(main())