修复测试模型路径并完善四路八路回归与文档
- 按文件哈希区分当前八路工程和历史 Amesim 基准,修复测试与清单中的旧路径。 - 四路审计从 JSON 按需生成 XML,八路新增只核对模式,并显式使用 UTF-8 与 LF。 - 将缺失高刚度夹具的测试替换为当前八路完整 BDF 运行,明确未恢复原 RK45 专项覆盖。 - 更新前端大型工程测试、历史活动回放入口、数据说明、现行规范和相关报告。 验证:全量后台 374 项通过、1 项条件跳过;前端 11 项通过、历史独立服务用例 1 项跳过;四路八路 AME 审计通过。 环境、缓存和运行产物保持忽略;本次未实施工程 JSON 字段精简。
This commit is contained in:
1 parent
44b6ea74ab
commit
b6c22a54f8
32 files changed
+318
-153
No files matched your search
@@ -4,8 +4,6 @@
|
||||
|
||||
# Regression manifests hash these files as raw bytes. Keep their checkout
|
||||
# representation identical on Windows and Linux so hashes remain portable.
|
||||
tests/fixtures/legacy/test-mql-8.xml text eol=lf
|
||||
tests/fixtures/legacy/test-mql-8.json text eol=lf
|
||||
tests/baselines/simulation/test_mql_full_branches/sources/test_mql-full-branches-01-04.xml text eol=lf
|
||||
tests/baselines/simulation/**/*.json text eol=lf
|
||||
|
||||
@@ -14,4 +12,3 @@ tests/baselines/simulation/**/sources/* text eol=lf
|
||||
# Browser projects and relocated native references.
|
||||
tests/data/*.json text eol=lf
|
||||
tests/baselines/native/*.json text eol=lf
|
||||
tests/fixtures/amesim/*.xml text eol=lf
|
||||
@@ -16,7 +16,15 @@ DATA_DIR = (
|
||||
|
||||
SIMULATION_RUNS_DIR = DATA_DIR / "simulation-runs"
|
||||
SIMULATION_BASELINES_DIR = PROJECT_ROOT / "tests" / "baselines"
|
||||
AMESIM_TEST_MQL_ARCHIVE_PATH = PROJECT_ROOT / "AmesimModels" / "test_mql.ame"
|
||||
# Current browser/solver input and the matching AME drawing (September 2026).
|
||||
CURRENT_MQL8_PROJECT_PATH = PROJECT_ROOT / "tests" / "data" / "test-mql-8-corrected.json"
|
||||
CURRENT_MQL8_AME_PATH = PROJECT_ROOT / "tests" / "data" / "test_mql.ame"
|
||||
|
||||
# Frozen August reference: its AME bytes differ from the current drawing.
|
||||
HISTORICAL_MQL8_AME_PATH = PROJECT_ROOT / "tests" / "data" / "AmesimModels" / "test_mql.ame"
|
||||
HISTORICAL_MQL8_PROJECT_PATH = SIMULATION_BASELINES_DIR / "simulation" / "test_mql_8" / "sources" / "test-mql-8.json"
|
||||
HISTORICAL_MQL8_XML_PATH = HISTORICAL_MQL8_PROJECT_PATH.with_suffix(".xml")
|
||||
AMESIM_TEST_MQL_ARCHIVE_PATH = HISTORICAL_MQL8_AME_PATH
|
||||
MODELICA_TESTMODEL_RESULT_PATH = (
|
||||
PROJECT_ROOT / "ModelicaModels" / "Simulation" / "Testmodel_res.csv"
|
||||
)
|
||||
@@ -1,6 +1,6 @@
|
||||
# 工程版本警告与统一参数输入验收
|
||||
|
||||
报告版本:1.0.0;日期:2026-09-12;基线:`22579e5` 加本次工作区改动。
|
||||
报告版本:1.0.1;日期:2026-09-12;基线:`22579e5` 加本次工作区改动。
|
||||
|
||||
本次落实旧组件版本警告和参数输入语义统一。验收案例为 `tests/data/test-mql-8-corrected.json`,157 个组件、178 条连接、1092 个已保存参数。测试没有改动四路/八路基准文件、C 方程、雅可比算法或求解精度。
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
|
||||
全量检查的缺失项为两组测试仍指向不存在的 `AmesimModels/test_mql.ame`,以及缺少 `tests/fixtures/high_stiffness_explicit_rk45.xml`。这些测试/夹具不在本次实现改动内,没有伪造数据或改成通过。原始日志保留。没有重新执行 Amesim 对照。Linux 实测完成;Windows 使用通用 Python/浏览器实现,没有新增平台专用调用,但本次没有 Windows 实机验收。
|
||||
|
||||
## 缺失输入后续修复 / 2026-09-12
|
||||
|
||||
用户确认移动/删除了夹具后,已按实际文件哈希修复历史 AME 路径;高刚度 XML 未找到,按用户授权改为当前八路完整 BDF 测试。全量后台重新执行 375 项,374 通过、1 条原条件跳过,0 失败/错误。原 RK45 专项未恢复,不将本次替代用例算成原覆盖。另修复前端/审计对已删除 JSON/XML 的依赖,画布复测 11 项通过。上述表格保留前次原始执行结果;文件映射、报告依据及本次测试日志见 [路径修复报告](2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
## 版本检查的独立耗时
|
||||
|
||||
在 Chromium 内执行正式 `projectCompatibility.ts` 中的目录索引、版本比较及提示文字生成函数。目录仅建立一次内存 Map,通过 WeakMap 按目录数组复用;每次扫描节点,无逐组件网络请求或文件扫描。预热后每组 200 个样本、每样本 10 次调用;时间分辨率约 0.1 ms,通过批量计时减小量化误差。首次索引建立约 0.10 ms。
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# 测试输入路径修复与八路替代验证
|
||||
|
||||
报告版本:1.0.0;日期:2026-09-12;基线:`44b6ea7` 加本次改动。
|
||||
|
||||
用户确认曾移动 AME/JSON、删除 fixture,并要求找回实际路径;找不到专项 XML 时先改用当前八路系统。此次修复了测试入口和文档引用,四路/八路工程及 AME 内容均未修改。全量后台检查恢复为 OK;原高刚度 RK45 专项没有被伪装成已恢复。
|
||||
|
||||
## 当前文件与身份
|
||||
|
||||
后续浏览器建模和优化仍用 [八路 corrected JSON](../../tests/data/test-mql-8-corrected.json) 与 [当前八路 AME](../../tests/data/test_mql.ame)。备用为 [四路 corrected JSON](../../tests/data/test-mql-4-corrected.json) 与 [四路 AME](../../tests/data/test_mql_4.ame)。方便后续删改的目录索引见 [tests/data/README.md](../../tests/data/README.md)。
|
||||
|
||||
| 文件(仓库相对路径) | 字节数 | SHA-256 |
|
||||
| --- | ---: | --- |
|
||||
| `tests/data/test-mql-8-corrected.json` | 271259 | `670977bef67e62d9c66e8af497bada208bd72a7301be45128d185d47282cf288` |
|
||||
| `tests/data/test_mql.ame` | 21698560 | `1ff0ea4284b9248260eeceb8b27cd0bc14dbccb43554ab8c0b49900d0b944c3d` |
|
||||
| `tests/data/test-mql-4-corrected.json` | 457639 | `542494eed8e235cb36eae5f80a0776b812e547d9215fa370949b0882834ebc8b` |
|
||||
| `tests/data/test_mql_4.ame` | 13578240 | `99a071896671d634d651a7b21f487662dd7c122af8fd3d60ead404a5afa53ed4` |
|
||||
| `tests/data/AmesimModels/test_mql.ame` | 21708800 | `cbc3aadd4569a49b3a63e5d66d4143ec16126c0f950df73fb637e07673c20fbb` |
|
||||
| `tests/baselines/simulation/test_mql_8/sources/test-mql-8.json` | 272592 | `b44bf540ccd1c293fe2af2b9b9052b540abf83961ad955a0f6a4ab40fbe0bb18` |
|
||||
| `tests/baselines/simulation/test_mql_8/sources/test-mql-8.xml` | 104110 | `0a2d9331df9eb5974daec25a61c1238ba32b1742d933ffc8b16ce316c5627b0b` |
|
||||
|
||||
历史 AME 原路径为 `AmesimModels/test_mql.ame`,现为 `tests/data/AmesimModels/test_mql.ame`,其身份与原测试要求完全一致。对应历史 JSON/XML 已在 `tests/baselines/simulation/test_mql_8/sources/`。本次只修复 manifest 中的 AME 路径,没有改动历史哈希、golden、采样曲线或耗时。
|
||||
|
||||
被删除的 legacy 八路 JSON 的历史 SHA 为 `4f1bf698519ba21429a11a83653adc7e52191f2d2b51fca943ee0b84f62feebd`;现存 sources JSON 是 `b44bf540…`。两者不是同一字节文件。普通画布测试因此转到当前 corrected 工程,历史基准读取则保持自己的 sources/AME 配对。
|
||||
|
||||
## 测试及报告来源
|
||||
|
||||
| 测试 / 工具 | 原报告或规范中的要求、用途 | 本次处理 |
|
||||
| --- | --- | --- |
|
||||
| `tests/test_test_mql_ame_contract.py` | [2026-08-17 日志 22:35](../update-log/更新日志-2026-08-17.md):锁定 XML/JSON 双哈希和配置;[2026-08-18 日志 07:58、23:10](../update-log/更新日志-2026-08-18.md):独立 AME 防漂移、单位/参数/精确端口、manifest 来源绑定 | 指向历史 AME 和历史 sources,保留原物理、哈希和结果断言 |
|
||||
| `tests/test_amesim_results.py` | [2026-08-18 日志](../update-log/更新日志-2026-08-18.md):AME 二进制结果及变量、时间轴读取,支撑外部物理基准 | 只修复历史 AME 路径,已保存结果继续原样核对 |
|
||||
| 八路/四路 AME 审计脚本 | [八路模型修正](test-mql-8模型对照与修正-2026-09-11.md)、[四路模型复核](test-mql-4模型复核与输入修正-2026-09-11.md)、[管流求根与四路网页验证](牛顿管流求根与四路网页验证-2026-09-11.md):逐组件、参数和参考端口核对 | 当前 JSON 作为工程输入,AME 图纸独立作为参照;不再依赖已删除 legacy JSON 或独立四路 XML |
|
||||
| `frontend/tests/e2e/fit-view.spec.ts` | [2026-08-17 日志 20:01、22:48](../update-log/更新日志-2026-08-17.md):大型工程导入、视口、端点、结果系统图线桥 | 改用当前 corrected 八路;按其 P4 布局选取实际交叉边;兼容新版本提示,仍检查展开日志里的加载/恢复成功 |
|
||||
| `frontend/tests/e2e/simulation-live-mql8.spec.ts` | [八路修正报告的测试范围说明](test-mql-8模型对照与修正-2026-09-11.md):这是 August Python 内部活动心跳流程,不是当前原生验收入口 | 改为读取历史 sources JSON;新证据写入忽略目录,避免覆盖历史报告。普通 4173 配置明确跳过;独立 live 配置依然保留,未重新验收旧遥测流程 |
|
||||
| 原 `tests/test_high_stiffness_explicit_rk45.py` | [前次输入合同验收](2026-09-12-project-contract-acceptance.md) 披露该夹具缺失;旧测试自身要求刚度 XML 的短时 RK45 事件/重启。未找到另一个单独规定该文件的现行报告;历史运行源码清单出现其测试名不等于恢复了夹具 | XML 未找到,按本次用户授权改为 `tests/test_current_mql8_simulation.py`,用当前八路完整 BDF 运行验证 |
|
||||
| 后续优化案例 | [现行优化验证约定](../standard/optimization-benchmark-model.md) | 维持 corrected 八路优先;四路只作明确的退路,历史冻结基准不能混入当前性能比较 |
|
||||
|
||||
前次所谓“三处旧夹具缺失”是三个报错位置,并不代表三个不同文件。两处依赖同一份被移动的历史 AME,另一处依赖已删除的高刚度 XML。补查还发现前端/审计依赖的 legacy JSON 和独立四路 XML 已删除,一并消除了活动路径依赖。
|
||||
|
||||
相关历史日志、模型报告、物性资料路径、native README、数据索引和现行规范已加当前位置或迁移说明。历史 `goldens/`、`runs/`、已归档审计 JSON 中的旧路径和源码状态保留为当时证据,当前位置由 manifest、数据索引和新增历史基准 README 说明。
|
||||
|
||||
## 实现及验收边界
|
||||
|
||||
- 共享路径集中在 `app/simulation/paths.py`,区分当前八路与 August 历史八路;前端用相对模块 URL 定位工程;审计脚本显式使用 UTF-8 读写文本,并固定写出 LF,避免 Windows 系统默认编码影响中文 JSON。
|
||||
- 八路 `--check` 逐项检查 AME 的 157 个元件、1092 个公开参数、178 条连接以及时间配置,参数/端口差异均为 0。证据写入 `test/model-audit/mql8/`,不改工程文件。
|
||||
- 四路 `--check` 从 JSON 经正式 CLI 输入转换生成内存 XML,再对照独立 AME 图纸,81 个元件、582 个参数、90 条连接通过;原 XML 缺失不再阻塞审计。无需另保存一份需同步维护的 fixture XML。
|
||||
- 新八路运行测试沿正式 JSON → SI XML → 原生 C 路径执行完整 0~10 s,使用工程保存的 BDF、step 0.01、max_step 1e30 和后端 rtol 1e-8。检查终态、事件/重启、时间单调、规则采样点完整性、各列长度和所有值有限,并检查源文件未变。这不等于原 RK45 高刚度覆盖,也不单凭运行成功判定 Amesim 曲线一致。
|
||||
- 更新 `.gitattributes` 与配套测试,使用现有历史 sources 和当前 JSON 的 LF 规则,避免 Windows checkout 改变受哈希保护的文本字节。
|
||||
|
||||
| 验证 | 结果 |
|
||||
| --- | --- |
|
||||
| AME 读取、历史契约、当前八路定向运行 | 11 项通过,4.988 s |
|
||||
| 全量后台 `unittest discover` | 375 项:374 通过、1 条原条件跳过,57.360 s;0 失败/错误 |
|
||||
| 跳过的后台项目 | Linux 完整发布锁版本实机对照,按原有 `SYSTEM_SIMULATION_VERIFY_LOCKED_ENV=1` 开关控制;不是夹具缺失 |
|
||||
| 当前四路/八路 AME 审计 | 均通过;另外在临时副本故意修改参数、端口,四个错误输入均被拒绝 |
|
||||
| 前端定向复测 | 11 项通过,31.4 s;历史真实后端活动回放 1 项因普通配置跳过 |
|
||||
| 文件身份 | 上表 7 个输入均逐字节等于本次改动前 HEAD,模型未被审计覆盖 |
|
||||
|
||||
前端首次扩展检查中,两项仍期待加载信息占据最后一条摘要;新合同会追加旧工程单位提示。现在同时检查最新提示和展开日志中的加载/恢复成功。另一个线桥断言使用旧 P4 布局中已经不相交的边,已换成 corrected 工程实际相交的 P4 #5 边,仍要求生成线桥。第一次还误用普通无后端配置运行了历史 live 测试;独立服务要求现已显式标记,不能将该跳过记为真实浏览器求解通过。
|
||||
|
||||
本次没有重跑 Amesim 官方程序,没有新增八路网页求解耗时结论;前端是模拟 API 的画布回归,实际八路完整求解由后台测试完成。全量后台包含现有四路冻结 Amesim 曲线比较。Linux 实测完成,Windows 路径/换行兼容保持,但没有 Windows 实机环境验收。
|
||||
|
||||
## 复现与产物
|
||||
|
||||
从仓库根执行(Windows 将解释器替换为 `.venv-win\Scripts\python.exe`):
|
||||
|
||||
```bash
|
||||
.venv/bin/python tools/audit_test_mql8_model.py --check
|
||||
.venv/bin/python tests/model_audit/audit_mql4_model.py --check
|
||||
.venv/bin/python -m unittest tests.test_current_mql8_simulation -v
|
||||
.venv/bin/python -m unittest discover -s tests -v
|
||||
```
|
||||
|
||||
在 `frontend/` 中用项目 Node 环境执行 `npm run test:e2e -- fit-view.spec.ts simulation-live-mql8.spec.ts`;Linux 浏览器依赖沿用 `.venv/native/browser-libs/`。需要当前真实网页/HTTP/C 验收时,使用 `tests/manual/browser_native_simulation.mjs` 和 corrected JSON;不以历史 Python 心跳脚本代替。
|
||||
|
||||
本次原始日志和身份摘要位于被 Git 忽略的 `test/model-path-refresh-20260912/`:`summary.json`、`targeted.log`、`backend-all.log`、`audit-mql4.log`、`audit-mql8.log`、`audit-negative.log`、`frontend.log`(首次诊断)、`frontend-final.log`(最终复测)。临时 XML/AME 审计证据位于 `test/model-audit/`。环境、缓存、测试产物均未纳入 Git;本次未提交或推送。
|
||||
|
||||
临时前端服务已退出;收尾检查 4173、5173、8000 均无监听。`git diff --check` 与本轮新增文档链接检查通过。
|
||||
@@ -1,5 +1,7 @@
|
||||
# Amesim 与 C 计算顺序差异核查
|
||||
|
||||
> 路径复核 / 2026-09-12:本文引用的旧 `tests/data/test-mql-8.json` 已删除,保留当时实验描述;后续实验输入统一为 `tests/data/test-mql-8-corrected.json`,对应 `tests/data/test_mql.ame`。 详见 [路径修复记录](2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
日期:2026-09-10。分支:`system-optimization`;核查时提交:`0dcb465`。
|
||||
|
||||
本次对照当前 `tests/data/test-mql-8.json`、Amesim 2404 的生成代码和本机组件源码,并在 `test/amesim-order-study/` 中进行独立实验。正式模型、C 生成器、数值内核、积分器和雅可比策略均未修改。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# C 计算依赖排序验证(2026-09-10)
|
||||
|
||||
> 路径复核 / 2026-09-12:本文引用的旧 `tests/data/test-mql-8.json` 已删除,保留当时实验与耗时;后续验证使用 `tests/data/test-mql-8-corrected.json`,不得把换了输入后的耗时直接与本文计算优化比例。 详见 [路径修复记录](2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
在 `system-optimization` 分支完成已知来源识别、依赖排序和局部循环划分,接入默认 C 编译入口使用的扩展生成路径。未修改管路内部求根、积分器、雅可比策略或用户模型接线。
|
||||
|
||||
## 本轮实现
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Python 数值实现退役记录(2026-09-10)
|
||||
|
||||
> 路径复核 / 2026-09-12:本文当时使用的 `tests/data/test-mql-8.json` 已删除;当前活动输入为 `tests/data/test-mql-8-corrected.json`,按其实际保存配置运行。August 冻结基准仍在 `tests/baselines/simulation/test_mql_8/sources/`,对应 AME 为 `tests/data/AmesimModels/test_mql.ame`。 详见 [路径修复记录](2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
网页与 CLI 统一采用 C 数值内核。删除旧 Python 积分器及模型数值实现;Python 保留输入校验、模型元数据、C 生成、构建缓存、任务与结果管理。
|
||||
|
||||
## 删除与保留
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
状态:22 个模型已在临时 AMESim 库完成第一版公开,持续校准中
|
||||
|
||||
适用模型:`AmesimModels/test_mql.ame` / `app.simulation.examples.test_mql.system`
|
||||
适用模型:`tests/data/AmesimModels/test_mql.ame` / `app.simulation.examples.test_mql.system`
|
||||
|
||||
配套规范:[`component-model-authoring-spec-v1.md`](../standard/component-model-authoring-spec-v1.md)
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
仓库中已经包含该模型所需的说明和算例数据:
|
||||
|
||||
- `AmesimModels/help/pneumatic_library_manual/03_gas_properties.pdf` 第 3.3 节
|
||||
- `tests/data/AmesimModels/help/pneumatic_library_manual/03_gas_properties.pdf` 第 3.3 节
|
||||
给出 AMESim Pneumatic Library 的气体物性层级和 Peng-Robinson 状态方程。
|
||||
- `AmesimModels/help/pneumatic_library_manual/lib_pneumatic.pdf` 第 87--88 页
|
||||
- `tests/data/AmesimModels/help/pneumatic_library_manual/lib_pneumatic.pdf` 第 87--88 页
|
||||
给出 293.15 K、1 barA 下的氦气参考物性。
|
||||
- `AmesimModels/test_mql.ame` 中的 `PNGD00` 实例明确选择
|
||||
- `tests/data/AmesimModels/test_mql.ame` 中的 `PNGD00` 实例明确选择
|
||||
`fluidType=12`(helium)和 `eosType=6`(Peng-Robinson)。
|
||||
- `app/simulation/core/peng_robinson.py` 已实现纯物质 Peng-Robinson 方程,
|
||||
并定义了 `HELIUM_PR`。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# test-mql-4 模型复核与输入修正(2026-09-11)
|
||||
|
||||
> 路径复核 / 2026-09-12:下文独立四路 XML 已删除。当前工程仍为 `tests/data/test-mql-4-corrected.json`;审计脚本从该 JSON 临时生成 XML,并在 `--check` 中独立核对 AME 参数与端口。历史 XML 哈希和生成记录保留为当时证据。 详见 [路径修复记录](2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
目录整理补充:`tests/data` 的 JSON/XML 仅保留浏览器可导入的四路、八路 corrected JSON;参考曲线、旧工程和后端 XML 已迁到 `tests/baselines` / `tests/fixtures`,本文当前路径同步更新,文件内容及来源哈希不变。详见 [数据目录说明](../../tests/data/README.md)。
|
||||
|
||||
本次从 `tests/data/test_mql_4.ame` 的原始 `.cir` 图纸重新核对元件、参数和端口连接,生成了可导入网页的 `tests/data/test-mql-4-corrected.json`,并同步 `tests/fixtures/amesim/test-mql-4-corrected.xml`。两份输入均有 81 个元件、90 条连接、582 个公开参数,对应 64 个动态状态;生成结果的每个公开参数和连接端口均已按同一元件映射与 AME 图纸逐项比较。生成的 XML 通过后端语法和语义校验,无错误、无警告。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# test-mql-8 当前 AME 归档与完整曲线核查
|
||||
|
||||
> 路径复核 / 2026-09-12:本报告当前 AME/JSON 路径仍有效;文中 SHA 开头 `cbc3aadd` 的另一个历史 AME 位于 `tests/data/AmesimModels/test_mql.ame`,只与 August 冻结基准配套。 详见 [路径修复记录](2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
2026-09-11。只读解析当前输入、AME 归档和已完成的原生运行,不重新求解、编译或修改模型。
|
||||
|
||||
**当前八路归档的数据身份、公开参数和初始状态相互对应,可以作为已保存曲线的观察参考。完整曲线仍有差异,不能判为一致;Amesim 没有可信 CPU/墙钟耗时,速度比较明确 `skip`。** 归档名义容差为 1e-7,本轮原生为 1e-8,亦不构成同精度的性能比较。
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# test-mql-8 模型对照与修正(2026-09-11)
|
||||
|
||||
目录整理补充:`tests/data` 的 JSON/XML 仅保留浏览器可导入的四路、八路 corrected JSON;参考曲线、旧工程和后端 XML 已迁到 `tests/baselines` / `tests/fixtures`,本文当前路径同步更新,文件内容及来源哈希不变。详见 [数据目录说明](../../tests/data/README.md)。
|
||||
> 路径复核 / 2026-09-12:下文修正前 legacy JSON 已删除;现存历史基准 JSON 的哈希不同,不能代替那份原输入。当前审计改读 `tests/data/test-mql-8-corrected.json`,使用 `--check` 与 `tests/data/test_mql.ame` 复核而不覆盖工程。 详见 [路径修复记录](2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
已依据 `tests/data/test_mql.ame` 的真实图纸生成 `tests/data/test-mql-8-corrected.json`,保留原 `test-mql-8.json` 供审计。修正版包含参数、逐端口连接和仿真最大步长的对齐。静态校验通过。rtol=1e-7 的首次求解在 120 s 限额内推进到 5.144858167 s 后超时;后续按用户确认的全局 rtol=1e-8,以同一执行模型和内核完成了完整 10 s 单次运行。本轮未运行 Amesim 官方程序,也未进行八路 Amesim 曲线对比。
|
||||
2026-09-11 目录整理记录(后续位置以上方复核说明为准):`tests/data` 的 JSON/XML 仅保留浏览器可导入的四路、八路 corrected JSON;参考曲线、旧工程和后端 XML 已迁到 `tests/baselines` / `tests/fixtures`,本文当前路径同步更新,文件内容及来源哈希不变。详见 [数据目录说明](../../tests/data/README.md)。
|
||||
|
||||
已依据 `tests/data/test_mql.ame` 的真实图纸生成 `tests/data/test-mql-8-corrected.json`,当时保留原 `test-mql-8.json` 供审计(现已删除)。修正版包含参数、逐端口连接和仿真最大步长的对齐。静态校验通过。rtol=1e-7 的首次求解在 120 s 限额内推进到 5.144858167 s 后超时;后续按用户确认的全局 rtol=1e-8,以同一执行模型和内核完成了完整 10 s 单次运行。本轮未运行 Amesim 官方程序,也未进行八路 Amesim 曲线对比。
|
||||
|
||||
## 来源与核查方法
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 牛顿管流求根、AME 输入复核与网页验证(2026-09-11)
|
||||
|
||||
> 路径复核 / 2026-09-12:当前交付工程仍为四路/八路 corrected JSON;独立四路 XML 夹具已删除,改为从 JSON 按需导出。下文速度和曲线记录是原验收结果。 详见 [路径修复记录](2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
目录整理补充:`tests/data` 的 JSON/XML 仅保留浏览器可导入的四路、八路 corrected JSON;参考曲线、旧工程和后端 XML 已迁到 `tests/baselines` / `tests/fixtures`,本文当前路径同步更新,文件内容及来源哈希不变。详见 [数据目录说明](../../tests/data/README.md)。
|
||||
|
||||
本轮在 `5d5a2e1843bc10cf7764c77cc2c1182c21a68df5` 的物性复用实现上,补全局部管流牛顿求根的区间保护和二分回退;按用户确认,将网页/API 与 Python CLI 默认相对误差限改为 `1e-8`。四路输入先按 AME 图纸核对,再做实际原生计算和浏览器验证。环境依赖、生成程序和运行数据均留在 Git 忽略目录,没有提交或推送 Git。
|
||||
@@ -26,7 +28,7 @@ PNL00R 原有直接层流分支继续保留。物性状态复用、物理方程
|
||||
|
||||
## 先核对模型,再比较数值
|
||||
|
||||
交付输入为 [四路 JSON](../../tests/data/test-mql-4-corrected.json)、[同步 XML](../../tests/fixtures/amesim/test-mql-4-corrected.xml) 和 [八路修正版 JSON](../../tests/data/test-mql-8-corrected.json)。完整差异分别见 [四路复核](test-mql-4模型复核与输入修正-2026-09-11.md) 与 [八路修正](test-mql-8模型对照与修正-2026-09-11.md)。
|
||||
交付输入为 [四路 JSON](../../tests/data/test-mql-4-corrected.json)、当时同步的 XML(现从四路 JSON 按需导出,见 [当前输入说明](../../tests/data/README.md)) 和 [八路修正版 JSON](../../tests/data/test-mql-8-corrected.json)。完整差异分别见 [四路复核](test-mql-4模型复核与输入修正-2026-09-11.md) 与 [八路修正](test-mql-8模型对照与修正-2026-09-11.md)。
|
||||
|
||||
四路 AME 为 `tests/data/test_mql_4.ame`。其 `.cir` 包含 63 个组件和 18 条建模管线,展开为 81 个公开元件、90 条连接、582 项公开参数、64 个动态状态。修正遗留管阻 `amesim_pnl00r_4.rr` 为 `1e-5`,并将 25 条涉及等价端口编号/阻力方向的连线与 AME 编号逐项对齐。
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 现行规范索引
|
||||
|
||||
索引版本:1.1.0;整理/复核日期:2026-09-12。
|
||||
索引版本:1.1.1;整理/复核日期:2026-09-12。
|
||||
|
||||
新增组件从[注册流程](component-registration-workflow-v1.md)开始,再按涉及的能力读取专项规范。[注册示例](component-registration-example-v1.md)包含实际失败阶段、修订对照和复现方法。本目录保存现行版本,修订时更新正文版本、日期及变更说明;历史实现报告仍在 `docs/other/`,不覆盖其历史结论。
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
| 文件 | 文档版本 / 核对日期 | 本轮调整 |
|
||||
| --- | --- | --- |
|
||||
| [System XML v3](system-xml-v3.md) | 1.1.0 / 2026-09-12 | 求解方法、示例可执行边界、参数输入及连接检查层次 |
|
||||
| [优化基准模型](optimization-benchmark-model.md) | 1.0.0 / 2026-09-12 | 真实计时字段、预热、网页保存/CSV 与原始数据口径 |
|
||||
| [优化基准模型](optimization-benchmark-model.md) | 1.1.0 / 2026-09-12 | 计时口径、当前/历史输入隔离、按需 XML 与可执行测试入口 |
|
||||
|
||||
以上版本仅表示文档,XML Schema 和用户指定的八路基准未改变。
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 优化验证的模型、数据和计时口径
|
||||
|
||||
文档版本:1.0.0;核对日期:2026-09-12;代码基线:`22579e5`。本轮补充实际计时字段和运行入口,保留用户指定的八路优先及精度要求。
|
||||
文档版本:1.1.0;核对日期:2026-09-12;本次路径修订基线:`44b6ea7`。本轮补充实际计时字段和运行入口,保留用户指定的八路优先及精度要求。
|
||||
|
||||
本约定记录用户于 2026-09-11 明确的长期偏好,适用于后续仿真正确性检查与性能优化。
|
||||
|
||||
@@ -10,6 +10,15 @@
|
||||
|
||||
只有八路模型确实跑不通,而且短期内没有可行修复时,才退回 `tests/data/test-mql-4-corrected.json` 与 `tests/data/test_mql_4.ame`。报告必须记录八路失败的实际终点、诊断、已排查内容及退回原因;四路结果不能代替八路验收。
|
||||
|
||||
## 当前入口与历史基准隔离(2026-09-12 补充)
|
||||
|
||||
- 当前八路核对:`.venv/bin/python tools/audit_test_mql8_model.py --check`。读取 corrected JSON 与当前 AME,证据写入 `test/model-audit/mql8/`,不修改工程。
|
||||
- 当前四路核对:`.venv/bin/python tests/model_audit/audit_mql4_model.py --check`。XML 从四路 JSON 在内存中生成,再独立对照 AME 的参数与精确端口连接,不依赖已删除的 XML 夹具。
|
||||
- 当前八路运行:`.venv/bin/python -m unittest tests.test_current_mql8_simulation -v`。完整使用工程所存区间和配置,验证原生执行、事件、采样完整性与数值有限。该项代替已删除的高刚度 XML 测试,不宣称覆盖原 RK45 专项或证明与 Amesim 曲线一致。
|
||||
- 2026 年 8 月冻结输入在 `tests/baselines/simulation/test_mql_8/sources/`,对应 `tests/data/AmesimModels/test_mql.ame`。其字节数、SHA 和数值配置仍按 manifest 校验;历史记录中的旧路径不作为活动入口。普通前端大型画布测试使用当前 corrected JSON,历史 Python 活动遥测回放保持显式启用。
|
||||
|
||||
Windows 对应使用 `.venv-win\Scripts\python.exe` 调用相同脚本;路径由仓库根解析。详细文件映射、报告来源及本次实际平台见 [路径修复记录](../other/2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
## 先核对实际数据,再计时
|
||||
|
||||
逐元件、逐端口、逐参数检查拓扑和物理量,尤其是参考口、表压与绝对压力、SI 换算、力和流量方向、初始化及信号时刻。完整区间实际结果、守恒、事件和所需曲线按明确口径核查。存在数值差异时仍可按用户要求测量并记录运行成本,但必须将其标为性能观察,不能据此宣布正确性验收通过。完成运行和数值有限只证明可运行,不能直接判定曲线一致。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 更新日志 2026-08-17
|
||||
|
||||
> 路径复核 / 2026-09-12:本文八路冻结基准的 AME 现位于 `tests/data/AmesimModels/test_mql.ame`,对应 JSON/XML 位于 `tests/baselines/simulation/test_mql_8/sources/`;保留原哈希、数值结果和当时测试结论。后续性能测试另用 corrected 八路工程,见 [文件映射与复测记录](../other/2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
## 11:15
|
||||
|
||||
- 复测复杂系统 XML:磁盘文件的终止时间为 `0.81 s`,原样运行正常完成;仅在内存中延长至 `2.10 s` 后也正常越过此前报告的 `2.05 s` 慢区并结束,没有发生重试、回退或无进度卡死。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 更新日志 2026-08-18
|
||||
|
||||
> 路径复核 / 2026-09-12:本文八路冻结基准的 AME 现位于 `tests/data/AmesimModels/test_mql.ame`,对应 JSON/XML 位于 `tests/baselines/simulation/test_mql_8/sources/`;保留原哈希、数值结果和当时测试结论。后续性能测试另用 corrected 八路工程,见 [文件映射与复测记录](../other/2026-09-12-test-input-path-refresh.md)。
|
||||
|
||||
## 02:28
|
||||
|
||||
- 完成 P0 基础回归闭环,并推进 OPT-01:将 760 个兼容代数槽压缩为 440 个逻辑坐标,逻辑消去 320 个 effort 别名;全局 RHS 微基准约提升 12.9%,Python 调用数约下降 36.8%。
|
||||
|
||||
@@ -10,3 +10,10 @@
|
||||
93 项后端回归、收尾 37 项缓存专项(部分重叠)、前端构建和 12 项超时/看门狗测试通过。Windows 换行做了模拟回归,未实机验证 Windows 锁实现。正常 5173/8000 服务保持停止,临时验证服务已停止;传输压缩仍仅归档备份。本轮未安装环境、提交或推送 Git。
|
||||
|
||||
实现、缓存目录、容量边界、阶段成本和原始记录见 [完整报告](../other/按需编译与分层缓存优化-2026-09-12.md)。
|
||||
|
||||
## 22:41(北京时间):测试输入路径修复
|
||||
|
||||
- 找到历史 AME 于 `tests/data/AmesimModels/test_mql.ame`,与 August 清单哈希一致;历史 JSON/XML 位于 `tests/baselines/simulation/test_mql_8/sources/`。两组历史测试和 manifest 已更新,未混用当前 AME 或重写历史数值证据。
|
||||
- 高刚度 XML 未找到,按用户授权改用当前 corrected 八路完整 10 s BDF 测试;独立四路 XML 改为从 JSON 临时生成。四路/八路 AME 参数和端口复核通过,两个工程内容未改。
|
||||
- 全量后台 375 项中 374 通过、1 条原条件跳过(57.360 s),原三处缺失错误消除。前端画布 11 项通过(31.4 s),独立服务的历史活动回放在普通配置显式跳过;未宣称重跑了当前网页求解或 Amesim。
|
||||
- 已更新现行规范、数据说明、审计入口及相关历史报告的迁移说明。文件身份、报告依据、替代覆盖限制与复现命令见 [完整记录](../other/2026-09-12-test-input-path-refresh.md)。未安装环境、提交或推送 Git。
|
||||
@@ -23,7 +23,7 @@ type ImportedProject = {
|
||||
};
|
||||
|
||||
const MQL_8_PROJECT_PATH = fileURLToPath(
|
||||
new URL("../../../tests/fixtures/legacy/test-mql-8.json", import.meta.url),
|
||||
new URL("../../../tests/data/test-mql-8-corrected.json", import.meta.url),
|
||||
);
|
||||
const mql8Project = JSON.parse(
|
||||
readFileSync(MQL_8_PROJECT_PATH, "utf8"),
|
||||
@@ -337,7 +337,7 @@ test("加载本地工程后自动适配建模画布", async ({ page }) => {
|
||||
exact: true,
|
||||
});
|
||||
await expect(consolePanel.locator(".simulation-console-dock-summary")).toContainText(
|
||||
"工程已加载",
|
||||
"已按旧工程规则读取参数",
|
||||
);
|
||||
await expect(consolePanel.locator(".simulation-console-dock-log")).toHaveCount(0);
|
||||
await page.getByRole("button", { name: "展开仿真控制台" }).click();
|
||||
@@ -480,7 +480,7 @@ test("恢复自动保存工程后自动适配建模画布", async ({ page }) =>
|
||||
exact: true,
|
||||
});
|
||||
await expect(consolePanel.locator(".simulation-console-dock-summary")).toContainText(
|
||||
"已恢复上次自动保存的工程",
|
||||
"已按旧工程规则读取参数",
|
||||
);
|
||||
await expect(consolePanel.locator(".simulation-console-dock-log")).toHaveCount(0);
|
||||
await page.getByRole("button", { name: "展开仿真控制台" }).click();
|
||||
@@ -687,9 +687,11 @@ test("结果页系统图为真实大型工程的非连接交叉线显示线桥",
|
||||
await expect(
|
||||
page.locator(".results-system-canvas .react-flow__node"),
|
||||
).toHaveCount(mql8Project.nodes.length);
|
||||
// In the AME-corrected layout P4 #5 crosses the non-connected vertical line.
|
||||
// P4 #1 used by the old fixture no longer has that crossing after rotation.
|
||||
await expect(
|
||||
page.locator(
|
||||
'.results-system-canvas .react-flow__edge[data-id="edge-amesim_p4node2_1-port_2-amesim_pnl0001_13-port_2-1786972847258"] .react-flow__edge-path',
|
||||
'.results-system-canvas .react-flow__edge[data-id="edge-amesim_p4node2_5-port_3-amesim_pnl0001_17-port_2-1786949374542"] .react-flow__edge-path',
|
||||
),
|
||||
).toHaveAttribute("d", / Q /);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { expect, test, type Page } from "@playwright/test";
|
||||
import { createHash } from "node:crypto";
|
||||
import { readFileSync, statSync, writeFileSync } from "node:fs";
|
||||
import { mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
||||
import { dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
type CompactProgressEvent = {
|
||||
@@ -42,12 +43,14 @@ type BrowserStreamEvidence = {
|
||||
parseErrors: string[];
|
||||
};
|
||||
|
||||
// Historical Python activity replay, opt-in only. Current native acceptance uses
|
||||
// tests/manual/browser_native_simulation.mjs with the corrected eight-branch JSON.
|
||||
const PROJECT_PATH = fileURLToPath(
|
||||
new URL("../../../tests/fixtures/legacy/test-mql-8.json", import.meta.url),
|
||||
new URL("../../../tests/baselines/simulation/test_mql_8/sources/test-mql-8.json", import.meta.url),
|
||||
);
|
||||
const EVIDENCE_PATH = fileURLToPath(
|
||||
new URL(
|
||||
"../../../tests/baselines/simulation/test_mql_8/runs/2026-08-18-production-browser-live-activity-v1-0.2.json",
|
||||
"../../../test/live-browser-mql8/latest-evidence.json",
|
||||
import.meta.url,
|
||||
),
|
||||
);
|
||||
@@ -206,6 +209,11 @@ function retainMoreCompleteEvidence(
|
||||
return retained;
|
||||
}
|
||||
|
||||
test.skip(
|
||||
({ baseURL }) => baseURL !== "http://127.0.0.1:14173",
|
||||
"Historical activity replay requires --config playwright.live.config.ts and its separate backend; current native acceptance has a separate entry.",
|
||||
);
|
||||
|
||||
test("test-mql-8 在真实浏览器流式链路完成 0.2 s BDF 仿真", async ({
|
||||
page,
|
||||
}, testInfo) => {
|
||||
@@ -514,7 +522,7 @@ test("test-mql-8 在真实浏览器流式链路完成 0.2 s BDF 仿真", async (
|
||||
servingMode: "isolated-vite-dev-proxy",
|
||||
},
|
||||
source: {
|
||||
path: "tests/fixtures/legacy/test-mql-8.json",
|
||||
path: "tests/baselines/simulation/test_mql_8/sources/test-mql-8.json",
|
||||
bytes: statSync(PROJECT_PATH).size,
|
||||
sha256: createHash("sha256").update(projectBytes).digest("hex"),
|
||||
},
|
||||
@@ -562,6 +570,7 @@ test("test-mql-8 在真实浏览器流式链路完成 0.2 s BDF 仿真", async (
|
||||
},
|
||||
};
|
||||
const serializedEvidence = `${JSON.stringify(evidence, null, 2)}\n`;
|
||||
mkdirSync(dirname(EVIDENCE_PATH), { recursive: true });
|
||||
writeFileSync(EVIDENCE_PATH, serializedEvidence, "utf8");
|
||||
await testInfo.attach("mql8-live-browser-evidence", {
|
||||
body: Buffer.from(serializedEvidence),
|
||||
|
||||
+1
-1
@@ -99,7 +99,7 @@ BDF 默认使用结构着色差分,无需环境变量或网页选项。修正
|
||||
|
||||
## AME 对齐后的工程输入
|
||||
|
||||
当前用户运行请使用 `tests/data/test-mql-4-corrected.json` 或 `tests/data/test-mql-8-corrected.json`。四路执行 XML 位于 `tests/fixtures/amesim/`,与其 JSON 同步;原八路 JSON 已移入 `tests/fixtures/legacy/` 供差异审计。`test-mql-4-amesim-reference.json` 是曲线基准,不是工程输入。模型复核、P4 端口图形修正、默认 `rtol=1e-8` 的验收和速度记录见 [本轮验证报告](../docs/other/牛顿管流求根与四路网页验证-2026-09-11.md)。
|
||||
当前用户运行请使用 `tests/data/test-mql-4-corrected.json` 或 `tests/data/test-mql-8-corrected.json`。执行 XML 从当前 JSON 按需生成;原独立四路 XML 和 legacy 八路夹具已删除。历史八路 JSON/XML 在 `tests/baselines/simulation/test_mql_8/sources/`,其 AME 在 `tests/data/AmesimModels/test_mql.ame`,仅用于冻结基准核对,不能与当前 corrected 输入混用。路径、生成方式和测试入口见 [测试文件说明](../tests/data/README.md)。`test-mql-4-amesim-reference.json` 是曲线基准,不是工程输入。模型复核、P4 端口图形修正、默认 `rtol=1e-8` 的验收和速度记录见 [本轮验证报告](../docs/other/牛顿管流求根与四路网页验证-2026-09-11.md)。
|
||||
|
||||
后续优化和网页计时默认使用修正后的八路工程;仅当八路无法运行且短期不能解决时退回四路。选择规则见 [优化验证约定](../docs/standard/optimization-benchmark-model.md),当前效率、迭代触顶与网页分阶段记录见 [八路评估报告](../docs/other/八路模型计算效率与网页阶段计时-2026-09-11.md)。
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# 八路历史冻结基准
|
||||
|
||||
路径复核:2026-09-12,版本 1.0.0。
|
||||
|
||||
本目录保存 2026 年 8 月回归输入和结果。当前可读取的来源为 [JSON](sources/test-mql-8.json)、[XML](sources/test-mql-8.xml) 及 [历史 AME](../../../data/AmesimModels/test_mql.ame),以 [manifest](manifest.json) 中的字节数和 SHA 为准。
|
||||
|
||||
`goldens/`、`runs/` 中的路径与源码状态是历史运行记录,不重新计算或覆盖;其中旧 `AmesimModels/test_mql.ame` 对应上述历史 AME。`tests/data/test_mql.ame` 是另一份当前归档,不能仅凭同名代入历史比较。显式启用的前端历史活动回放现在把新证据写到被忽略的 `test/live-browser-mql8/`,不会覆盖冻结运行报告。
|
||||
|
||||
普通功能/性能测试使用 [当前八路 corrected JSON](../../../data/test-mql-8-corrected.json)。相关测试与原报告的关系见 [路径修复记录](../../../../docs/other/2026-09-12-test-input-path-refresh.md)。
|
||||
@@ -8,7 +8,7 @@
|
||||
"bytes": 104110,
|
||||
"xmlIsAuthoritative": true,
|
||||
"referenceArchive": {
|
||||
"path": "AmesimModels/test_mql.ame",
|
||||
"path": "tests/data/AmesimModels/test_mql.ame",
|
||||
"sha256": "cbc3aadd4569a49b3a63e5d66d4143ec16126c0f950df73fb637e07673c20fbb",
|
||||
"bytes": 21708800,
|
||||
"role": "authoritativePhysicalBaseline",
|
||||
|
||||
@@ -12,7 +12,7 @@ Python 输出只有通过 AMESim baseline 对比后才能作为数值一致性
|
||||
|
||||
## 模型与源数据
|
||||
|
||||
- AMESim 源模型:`AmesimModels/test_mql.ame`
|
||||
- AMESim 源模型:`tests/data/AmesimModels/test_mql.ame`
|
||||
- Python 系统类:`app.simulation.examples.test_mql.system.TestMqlSystem`
|
||||
- 结构运行入口:`app.simulation.examples.test_mql.run`
|
||||
- 132 状态比较入口:`app.simulation.examples.test_mql.run_full_state_comparison`
|
||||
|
||||
+19
-15
@@ -1,26 +1,30 @@
|
||||
# 浏览器四路、八路测试工程
|
||||
|
||||
本目录中的 JSON/XML 仅保留以下两个可由网页“导入工程 JSON”识别的工程文件。已逐项核对对应 AME 图纸的元件、公开物理参数及端口连接;AME 单位与工程 SI 单位之间的换算已纳入检查。
|
||||
版本:1.1.0;路径复核日期:2026-09-12。
|
||||
|
||||
| 浏览器工程 | Amesim 原文件 | 元件 / 参数 / 连接 |
|
||||
本目录直接保留两个可由网页“导入工程 JSON”识别的工程。已重新逐项核对对应 AME 图纸的元件、公开物理参数及端口连接,包含 AME 单位到 SI 单位的换算。
|
||||
|
||||
| 浏览器工程(后续删改入口) | 对应 Amesim 原文件 | 元件 / 参数 / 连接 |
|
||||
|---|---|---|
|
||||
| [test-mql-4-corrected.json](test-mql-4-corrected.json) | [test_mql_4.ame](test_mql_4.ame) | 81 / 582 / 90 |
|
||||
| [test-mql-8-corrected.json](test-mql-8-corrected.json) | [test_mql.ame](test_mql.ame) | 157 / 1092 / 178 |
|
||||
|
||||
网页当前只支持导入工程 JSON;XML 可从网页下载,用作后端输入。网页使用原生 BDF 和当前默认 `rtol=1e-8`,与 AME 内部积分器及历史数值设置不能视为相同。这里的参数对齐指模型物理参数与初值,不声称不同仿真器所有数值输出完全一致。
|
||||
后续优化优先使用八路 corrected 工程;只有八路无法运行且短期不能修复时,再退回四路。具体要求见 [优化验证约定](../../docs/standard/optimization-benchmark-model.md)。网页使用原生 BDF、当前默认 `rtol=1e-8`;物理参数对齐不意味着与 AME 积分算法、历史数值设置和输出完全相同。
|
||||
|
||||
后续优化测试优先使用八路 corrected 工程;仅当八路跑不通且短期无法解决时,再使用四路。具体记录要求见 [优化验证约定](../../docs/standard/optimization-benchmark-model.md)。
|
||||
XML 不作为另一份手工维护的工程。需要时从网页下载,或用原生输入转换入口从 JSON 生成。四路审计 `--check` 在内存中生成 XML;八路审计的 XML 证据放在被 Git 忽略的 `test/model-audit/mql8/corrected.xml`。
|
||||
|
||||
2026-09-11 整理时,两份工程内容保持不变。其他 JSON/XML 已按用途移出本目录,移动前后字节数及 SHA256 相同:
|
||||
## 历史基准与辅助文件
|
||||
|
||||
| 原文件 | 当前路径 | 用途 |
|
||||
|---|---|---|
|
||||
| native-python-reference.json | [原生数值基准](../baselines/native/native-python-reference.json) | 50 网络冻结参考 |
|
||||
| test-mql-4-amesim-reference.json | [四路 Amesim 曲线基准](../baselines/simulation/test_mql_4/test-mql-4-amesim-reference.json) | 72 曲线、57 时刻 |
|
||||
| test-mql-4-corrected.xml | [四路执行 XML](../fixtures/amesim/test-mql-4-corrected.xml) | 与四路 JSON 同步的后端输入 |
|
||||
| test-mql-8.json / test-mql-8.xml | [旧 JSON](../fixtures/legacy/test-mql-8.json) / [旧 XML](../fixtures/legacy/test-mql-8.xml) | 修正前输入及布局来源 |
|
||||
| test_mql-full-branches-01-04.xml | [历史分支基准输入](../baselines/simulation/test_mql_full_branches/sources/test_mql-full-branches-01-04.xml) | 历史回归清单绑定的输入 |
|
||||
| native-skill-test.xml | [原生通用测试输入](../fixtures/native-skill-test.xml) | 原生编译、执行与 CI 检查 |
|
||||
| fixtures/high_stiffness_explicit_rk45.xml | [高刚度 RK45 输入](../fixtures/high_stiffness_explicit_rk45.xml) | 独立刚度回归用例 |
|
||||
| 当前路径 | 用途与限制 |
|
||||
|---|---|
|
||||
| [AmesimModels/test_mql.ame](AmesimModels/test_mql.ame) | 2026-08-18 冻结基准的 AME,SHA 开头 `cbc3aadd`;与本目录当前 AME 的 `1ff0ea42` 不同 |
|
||||
| [历史八路 JSON](../baselines/simulation/test_mql_8/sources/test-mql-8.json) / [XML](../baselines/simulation/test_mql_8/sources/test-mql-8.xml) | 与上述历史 AME 对应;由 [manifest](../baselines/simulation/test_mql_8/manifest.json) 锁定身份,不能替换为当前 corrected 工程 |
|
||||
| [原生数值基准](../baselines/native/native-python-reference.json) | 50 个网络的冻结参考,不是浏览器工程 |
|
||||
| [四路 Amesim 曲线基准](../baselines/simulation/test_mql_4/test-mql-4-amesim-reference.json) | 72 条曲线、57 个时刻,不是浏览器工程 |
|
||||
| [历史分支 XML](../baselines/simulation/test_mql_full_branches/sources/test_mql-full-branches-01-04.xml) | 另一份历史回归清单绑定的输入 |
|
||||
| [原生通用 XML](../fixtures/native-skill-test.xml) | 原生编译、执行与 CI 检查 |
|
||||
| [参数表达式用例](../fixtures/parameter-expressions.json) | 前后端共享的参数语义测试数据,不是浏览器工程 |
|
||||
|
||||
AME 原文件及本目录中其他类型的资料保持原位。历史运行记录保留当时路径;活动测试、审计脚本、CI 和当前交付说明已更新到新路径。
|
||||
2026-09-11 整理后,用户又移动/删除了部分文件。原 `tests/fixtures/amesim/test-mql-4-corrected.xml`、`tests/fixtures/legacy/test-mql-8.json/.xml`、`tests/fixtures/high_stiffness_explicit_rk45.xml` 当前均不存在。历史八路 sources 中的 JSON 也不是被删除 legacy JSON 的逐字节副本,不能冒充恢复了原文件。
|
||||
|
||||
高刚度 RK45 专项按用户决定改用 [当前八路完整运行测试](../test_current_mql8_simulation.py)。它验证当前 BDF 路径,不代表恢复了原 RK45 高刚度覆盖。文件身份、相关报告来源及验证结果见 [路径修复报告](../../docs/other/2026-09-12-test-input-path-refresh.md)。冻结运行记录中的旧路径是当时来源记录,当前位置以本说明和 manifest 为准。
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Audit the AME diagram against the corrected XML; emit an aligned browser project.
|
||||
"""Audit the AME diagram against the current browser project; generate XML on demand.
|
||||
|
||||
Run from the repository root with .venv/bin/python. Does not run Amesim or use
|
||||
the stale eight-branch compiled/result cache inside the four-branch archive.
|
||||
@@ -27,9 +27,9 @@ from tests.test_test_mql_ame_contract import (
|
||||
_public_model_type, _expected_parameters, _value_fields,
|
||||
)
|
||||
|
||||
OUT = ROOT / 'test/solver-newton-20260911/mql4'
|
||||
OUT = ROOT / 'test/model-audit/mql4'
|
||||
AME = ROOT / 'tests/data/test_mql_4.ame'
|
||||
XML = ROOT / 'tests/fixtures/amesim/test-mql-4-corrected.xml'
|
||||
XML = OUT / 'aligned-input.xml'
|
||||
REFERENCE = ROOT / 'tests/baselines/simulation/test_mql_4/test-mql-4-amesim-reference.json'
|
||||
PROJECT = ROOT / 'tests/data/test-mql-4-corrected.json'
|
||||
|
||||
@@ -147,9 +147,17 @@ def audit_source():
|
||||
}
|
||||
|
||||
|
||||
def project_xml():
|
||||
# The separately maintained XML fixture was deleted. Use the same input
|
||||
# conversion as the native CLI; the AME remains the independent authority.
|
||||
from app.simulation.native_codegen.input import load_input
|
||||
xml, _ = load_input(PROJECT)
|
||||
return xml
|
||||
|
||||
|
||||
def xml_model(root=None):
|
||||
if root is None:
|
||||
root = ET.parse(XML).getroot()
|
||||
root = ET.fromstring(project_xml())
|
||||
nodes = {item.attrib['id']: {
|
||||
'modelType': item.attrib['type'],
|
||||
'modelVersion': item.attrib['modelVersion'],
|
||||
@@ -257,8 +265,9 @@ def check_project_contract(project, xml_root):
|
||||
|
||||
|
||||
def generate_project(source, source_edges, target, target_edges, xml_root, mapping):
|
||||
layout_source = ROOT / 'tests/fixtures/legacy/test-mql-8.json'
|
||||
layout = json.loads(layout_source.read_text())
|
||||
layout_source = PROJECT
|
||||
layout = json.loads(layout_source.read_text(encoding='utf-8'))
|
||||
layout_sha = sha(layout_source)
|
||||
layout_nodes = {node['id']: node for node in layout['nodes']}
|
||||
reverse_mapping = {value: key for key, value in mapping.items()}
|
||||
nodes = []
|
||||
@@ -331,14 +340,14 @@ def generate_project(source, source_edges, target, target_edges, xml_root, mappi
|
||||
project = {'projectSchemaVersion': 1, 'name': 'test-mql-4-AME-aligned', 'nodes': nodes,
|
||||
'edges': edges, 'simulation': simulation}
|
||||
check_project_contract(project, xml_root)
|
||||
PROJECT.write_text(json.dumps(project, indent=2, ensure_ascii=False) + '\n')
|
||||
PROJECT.write_text(json.dumps(project, indent=2, ensure_ascii=False) + '\n', encoding='utf-8', newline='\n')
|
||||
generated_xml = OUT / 'aligned-input.xml'
|
||||
xml_root.attrib['name'] = project['name']
|
||||
ET.indent(xml_root)
|
||||
ET.ElementTree(xml_root).write(generated_xml, encoding='utf-8', xml_declaration=True)
|
||||
XML.write_bytes(generated_xml.read_bytes())
|
||||
# Check the delivered JSON itself, including every exact endpoint and number.
|
||||
json_nodes = {node['id']: node['data'] for node in json.loads(PROJECT.read_text())['nodes']}
|
||||
json_nodes = {node['id']: node['data'] for node in json.loads(PROJECT.read_text(encoding='utf-8'))['nodes']}
|
||||
for source_id, project_id in mapping.items():
|
||||
assert json_nodes[project_id]['parameters'] == source[source_id]['parameters']
|
||||
expected_edges = {tuple(sorted(((mapping[a], ap), (mapping[b], bp)))) for ((a, ap), (b, bp)) in source_edges}
|
||||
@@ -354,34 +363,44 @@ def generate_project(source, source_edges, target, target_edges, xml_root, mappi
|
||||
'nodeCount': len(nodes), 'edgeCount': len(edges), 'parameterCount': sum(len(n['data']['parameters']) for n in nodes),
|
||||
'allMappedParametersExactlyMatchAme': True, 'allMappedConnectionPortsExactlyMatchAme': True,
|
||||
'parameterChangesFromLegacyXml': parameter_changes, 'connectionPortChangesFromLegacyXml': changed_connections,
|
||||
'layoutMetadataSource': {'path': str(layout_source.relative_to(ROOT)), 'sha256': sha(layout_source)},
|
||||
'layoutMetadataSource': {'path': str(layout_source.relative_to(ROOT)), 'sha256': layout_sha},
|
||||
'simulation': simulation,
|
||||
'simulationSettingsNote': 'AME archive stores historical fixed-step settings. This JSON uses native BDF; rtol is supplied by the backend and is not stored in the project. Initial validation used 1e-7; the backend default was subsequently changed to 1e-8. The earlier official Standard variable-step reference remains tolerance 1e-7. Inspect actual run diagnostics; solver algorithms are not identical.'}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--check', action='store_true', help='Validate delivered JSON/XML only; do not generate or write files.')
|
||||
parser.add_argument('--check', action='store_true', help='Check current JSON parameters and exact connection ports against AME; generate XML in memory, without file writes.')
|
||||
arguments = parser.parse_args()
|
||||
if arguments.check:
|
||||
print(json.dumps(check_project_contract(json.loads(PROJECT.read_text()), ET.parse(XML).getroot()), indent=2))
|
||||
target, target_edges, xml_root = xml_model()
|
||||
result = check_project_contract(json.loads(PROJECT.read_text(encoding='utf-8')), xml_root)
|
||||
source, source_edges, _ = audit_source()
|
||||
mapping = find_mapping(source, source_edges, target, target_edges, ports=True)
|
||||
if mapping is None or len(source) != len(target) or len(source_edges) != len(target_edges):
|
||||
raise ValueError('Current JSON differs from AME in components, parameters or connection ports.')
|
||||
for source_id, target_id in mapping.items():
|
||||
if source[source_id]['parameters'] != target[target_id]['parameters']:
|
||||
raise ValueError(f'{target_id}: parameters do not exactly match AME.')
|
||||
result['ameParametersAndConnectionPortsMatch'] = True
|
||||
result['executionXmlSource'] = str(PROJECT.relative_to(ROOT))
|
||||
print(json.dumps(result, indent=2))
|
||||
return
|
||||
OUT.mkdir(parents=True, exist_ok=True)
|
||||
source, source_edges, audit = audit_source()
|
||||
legacy_xml = OUT / 'legacy-corrected-input.xml'
|
||||
if not legacy_xml.exists():
|
||||
legacy_xml.write_bytes(XML.read_bytes())
|
||||
XML.write_bytes(project_xml())
|
||||
(OUT / 'input-before-audit.xml').write_bytes(XML.read_bytes())
|
||||
target, target_edges, xml_root = xml_model()
|
||||
mapping = find_mapping(source, source_edges, target, target_edges)
|
||||
audit['correctedXml'] = {'path': str(XML.relative_to(ROOT)), 'sha256': sha(XML),
|
||||
'parameterAndComponentTopologyIsomorphic': mapping is not None}
|
||||
ref = json.loads(REFERENCE.read_text())
|
||||
ref = json.loads(REFERENCE.read_text(encoding='utf-8'))
|
||||
audit['reference'] = {'path': str(REFERENCE.relative_to(ROOT)), 'sha256': sha(REFERENCE),
|
||||
'source': ref['source'], 'timeCount': len(ref['times']), 'seriesCount': len(ref['series']),
|
||||
'ameHashMatches': ref['originalAmeSha256'] == sha(AME),
|
||||
'xmlHashMatches': ref['xmlSha256'] == sha(XML),
|
||||
'newAmesimRunPerformed': False}
|
||||
(OUT / 'source-model.json').write_text(json.dumps({'nodes': source, 'edges': source_edges}, indent=2, ensure_ascii=False) + '\n')
|
||||
(OUT / 'source-model.json').write_text(json.dumps({'nodes': source, 'edges': source_edges}, indent=2, ensure_ascii=False) + '\n', encoding='utf-8', newline='\n')
|
||||
if not mapping:
|
||||
mapping = find_mapping(source, source_edges, target, target_edges, parameters=False)
|
||||
if mapping:
|
||||
@@ -394,8 +413,8 @@ def main():
|
||||
audit['generatedProject'] = generate_project(source, source_edges, target, target_edges, xml_root, mapping)
|
||||
audit['correctedXml']['scope'] = 'Input XML snapshot before this generation; generatedProject describes the delivered corrected files.'
|
||||
audit_text = json.dumps(audit, indent=2, ensure_ascii=False) + '\n'
|
||||
(OUT / 'model-audit.json').write_text(audit_text)
|
||||
(ROOT / 'tests/model_audit/test-mql-4-audit.json').write_text(audit_text)
|
||||
(OUT / 'model-audit.json').write_text(audit_text, encoding='utf-8', newline='\n')
|
||||
(ROOT / 'tests/model_audit/test-mql-4-audit.json').write_text(audit_text, encoding='utf-8', newline='\n')
|
||||
print(json.dumps({key: value for key, value in audit.items() if key not in {'componentMapping', 'members', 'globals'}}, indent=2))
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock
|
||||
|
||||
from app.simulation.paths import HISTORICAL_MQL8_AME_PATH
|
||||
from app.simulation.reporting.amesim_results import (
|
||||
_resolve_result_members,
|
||||
load_test_mql_amesim_results,
|
||||
)
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
TEST_MQL_AME = REPO_ROOT / "AmesimModels" / "test_mql.ame"
|
||||
TEST_MQL_AME = HISTORICAL_MQL8_AME_PATH
|
||||
|
||||
|
||||
class AmesimResultsTests(unittest.TestCase):
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
"""Current eight-branch execution regression.
|
||||
|
||||
The deleted high_stiffness_explicit_rk45.xml is not reconstructed or renamed.
|
||||
Per the user decision on 2026-09-12, exercise the corrected eight-branch JSON
|
||||
through the real XML/native path. This does not claim the former RK45 coverage.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import math
|
||||
import unittest
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
from app.main import run_system_xml_simulation
|
||||
from app.simulation.native_codegen.input import load_input
|
||||
from app.simulation.paths import CURRENT_MQL8_PROJECT_PATH
|
||||
|
||||
|
||||
class CurrentMql8SimulationTests(unittest.TestCase):
|
||||
def test_corrected_eight_branch_runs_its_complete_saved_configuration(self):
|
||||
original = CURRENT_MQL8_PROJECT_PATH.read_bytes()
|
||||
project = json.loads(original)
|
||||
settings = project["simulation"]
|
||||
xml, document = load_input(CURRENT_MQL8_PROJECT_PATH)
|
||||
self.assertEqual(len(document.components), len(project["nodes"]))
|
||||
self.assertEqual(len(document.connections), len(project["edges"]))
|
||||
self.assertEqual(ET.fromstring(xml).get("unitSystem"), "SI")
|
||||
result = run_system_xml_simulation(xml, cancel_check=lambda: False)
|
||||
|
||||
self.assertTrue(result["success"], result["message"])
|
||||
self.assertEqual(result["status"], "completed")
|
||||
self.assertFalse(result["partial"])
|
||||
self.assertEqual(result["simulatedUntil"], settings["t_stop"])
|
||||
integration = result["diagnostics"]["integration"]
|
||||
self.assertEqual(integration["method"], settings["method"])
|
||||
self.assertEqual(integration["rtol"], 1e-8)
|
||||
self.assertEqual(result["diagnostics"]["native"]["backend"], "native-c")
|
||||
# The current case includes a mechanical transition over the complete 10 s.
|
||||
self.assertGreaterEqual(integration["totals"]["stateTransitionCount"], 1)
|
||||
self.assertGreaterEqual(integration["totals"]["solverStartCount"], 2)
|
||||
|
||||
series = result["series"]
|
||||
times = series["time"]
|
||||
self.assertEqual(times[0], settings["t_start"])
|
||||
self.assertEqual(times[-1], settings["t_stop"])
|
||||
self.assertTrue(all(a < b for a, b in zip(times, times[1:])))
|
||||
# Keep every requested output point, in addition to inserted event points.
|
||||
step = settings["step"]
|
||||
actual_grid = {round(t / step) for t in times if abs(t / step - round(t / step)) < 1e-8}
|
||||
expected_grid = set(range(round(settings["t_start"] / step), round(settings["t_stop"] / step) + 1))
|
||||
self.assertTrue(expected_grid.issubset(actual_grid))
|
||||
for key, values in series.items():
|
||||
self.assertEqual(len(values), len(times), key)
|
||||
self.assertTrue(all(math.isfinite(value) for value in values), key)
|
||||
self.assertEqual(CURRENT_MQL8_PROJECT_PATH.read_bytes(), original)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,74 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import math
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
from app.main import run_system_xml_simulation
|
||||
|
||||
|
||||
FIXTURE_PATH = (
|
||||
Path(__file__).resolve().parent
|
||||
/ "fixtures"
|
||||
/ "high_stiffness_explicit_rk45.xml"
|
||||
)
|
||||
ORIGINAL_XML_SHA256 = (
|
||||
"27048a99da0a21922d75785b760c3b5d04be3349b8aef6fbfedfd811d87ef1d5"
|
||||
)
|
||||
|
||||
|
||||
def short_explicit_rk45_xml() -> bytes:
|
||||
original = FIXTURE_PATH.read_bytes()
|
||||
canonical = original.replace(b"\r\n", b"\n").rstrip(b"\n")
|
||||
if hashlib.sha256(canonical).hexdigest() != ORIGINAL_XML_SHA256:
|
||||
raise AssertionError("The high-stiffness RK45 fixture differs from the user XML.")
|
||||
if original.count(b'tStop="10"') != 1:
|
||||
raise AssertionError("Expected one original simulation stop time.")
|
||||
if original.count(b'sampleStep="0.02"') != 1:
|
||||
raise AssertionError("Expected one original simulation sample step.")
|
||||
return original.replace(
|
||||
b'tStop="10"',
|
||||
b'tStop="0.005"',
|
||||
1,
|
||||
).replace(
|
||||
b'sampleStep="0.02"',
|
||||
b'sampleStep="0.001"',
|
||||
1,
|
||||
)
|
||||
|
||||
|
||||
class HighStiffnessExplicitRk45RegressionTests(unittest.TestCase):
|
||||
def test_short_user_model_crosses_the_early_stiff_limit_event(self) -> None:
|
||||
result = run_system_xml_simulation(
|
||||
short_explicit_rk45_xml(),
|
||||
cancel_check=lambda: False,
|
||||
)
|
||||
|
||||
self.assertTrue(result["success"], result["message"])
|
||||
self.assertEqual(result["status"], "completed")
|
||||
self.assertFalse(result["partial"])
|
||||
self.assertEqual(result["simulatedUntil"], 0.005)
|
||||
self.assertNotIn("provided bounds", result["message"])
|
||||
|
||||
integration = result["diagnostics"]["integration"]
|
||||
totals = integration["totals"]
|
||||
self.assertEqual(integration["method"], "RK45")
|
||||
self.assertGreaterEqual(totals["stateTransitionCount"], 1)
|
||||
self.assertGreaterEqual(totals["solverStartCount"], 2)
|
||||
|
||||
series = result["series"]
|
||||
times = series["time"]
|
||||
self.assertEqual(times[0], 0.0)
|
||||
self.assertEqual(times[-1], 0.005)
|
||||
self.assertTrue(
|
||||
all(first < second for first, second in zip(times, times[1:]))
|
||||
)
|
||||
self.assertTrue(any(0.0 < time < 0.001 for time in times))
|
||||
for values in series.values():
|
||||
self.assertEqual(len(values), len(times))
|
||||
self.assertTrue(all(math.isfinite(value) for value in values))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -11,8 +11,8 @@ BASELINE_ROOT = REPOSITORY_ROOT / "tests" / "baselines" / "simulation"
|
||||
GIT_ATTRIBUTES_PATH = REPOSITORY_ROOT / ".gitattributes"
|
||||
|
||||
EXPECTED_ATTRIBUTE_RULES = {
|
||||
("tests/fixtures/legacy/test-mql-8.xml", "text", "eol=lf"),
|
||||
("tests/fixtures/legacy/test-mql-8.json", "text", "eol=lf"),
|
||||
("tests/baselines/simulation/**/sources/*", "text", "eol=lf"),
|
||||
("tests/data/*.json", "text", "eol=lf"),
|
||||
("tests/baselines/simulation/test_mql_full_branches/sources/test_mql-full-branches-01-04.xml", "text", "eol=lf"),
|
||||
("tests/baselines/simulation/**/*.json", "text", "eol=lf"),
|
||||
}
|
||||
|
||||
@@ -14,14 +14,15 @@ import tarfile
|
||||
import unittest
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from app.simulation.paths import HISTORICAL_MQL8_AME_PATH, HISTORICAL_MQL8_PROJECT_PATH, HISTORICAL_MQL8_XML_PATH
|
||||
from app.simulation.registry import get_component_model_spec
|
||||
from app.simulation.reporting.amesim_results import load_test_mql_amesim_results
|
||||
|
||||
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
|
||||
AME_PATH = REPOSITORY_ROOT / "AmesimModels" / "test_mql.ame"
|
||||
JSON_PATH = REPOSITORY_ROOT / "tests/baselines/simulation/test_mql_8/sources/test-mql-8.json"
|
||||
XML_PATH = REPOSITORY_ROOT / "tests/baselines/simulation/test_mql_8/sources/test-mql-8.xml"
|
||||
AME_PATH = HISTORICAL_MQL8_AME_PATH
|
||||
JSON_PATH = HISTORICAL_MQL8_PROJECT_PATH
|
||||
XML_PATH = HISTORICAL_MQL8_XML_PATH
|
||||
MANIFEST_PATH = (
|
||||
REPOSITORY_ROOT
|
||||
/ "tests/baselines/simulation/test_mql_8/manifest.json"
|
||||
@@ -512,7 +513,7 @@ class TestMqlAmeAuthorityContractTests(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
reference,
|
||||
{
|
||||
"path": "AmesimModels/test_mql.ame",
|
||||
"path": "tests/data/AmesimModels/test_mql.ame",
|
||||
"sha256": EXPECTED_AME_SHA256,
|
||||
"bytes": EXPECTED_AME_BYTES,
|
||||
"role": "authoritativePhysicalBaseline",
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
"""Reproduce the eight-branch AME drawing -> editor model audit.
|
||||
|
||||
Run from the repository root with .venv/bin/python. The original inputs are
|
||||
read only. Mapping uses typed graph isomorphism and endpoint edit cost, never
|
||||
component display names; names are emitted only as evidence for review.
|
||||
Run from the repository root with .venv/bin/python and --check to preserve
|
||||
the current project; omit --check to regenerate it. Audit evidence goes to
|
||||
the ignored test/model-audit/mql8 directory. Mapping uses typed graph
|
||||
isomorphism and endpoint edit cost, never component display names; names
|
||||
are emitted only as evidence for review.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from collections import Counter, defaultdict
|
||||
from copy import deepcopy
|
||||
import hashlib
|
||||
@@ -24,11 +27,12 @@ from tests.test_test_mql_ame_contract import (
|
||||
_SOURCE_FIELD_BY_PARAMETER, _numeric_project_value,
|
||||
)
|
||||
from app.simulation.registry import get_component_model_spec
|
||||
from app.simulation.paths import CURRENT_MQL8_AME_PATH, CURRENT_MQL8_PROJECT_PATH
|
||||
|
||||
HERE = ROOT / 'test/solver-newton-20260911/mql8'
|
||||
AME = ROOT / 'tests/data/test_mql.ame'
|
||||
INPUT = ROOT / 'tests/fixtures/legacy/test-mql-8.json'
|
||||
OUTPUT = ROOT / 'tests/data/test-mql-8-corrected.json'
|
||||
HERE = ROOT / 'test/model-audit/mql8'
|
||||
AME = CURRENT_MQL8_AME_PATH
|
||||
INPUT = CURRENT_MQL8_PROJECT_PATH
|
||||
OUTPUT = CURRENT_MQL8_PROJECT_PATH
|
||||
|
||||
|
||||
def read_drawing():
|
||||
@@ -179,8 +183,14 @@ def match_graph(entities, ame_edges, project):
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--check', action='store_true',
|
||||
help='Audit current JSON against AME without changing the project; evidence goes to test/model-audit/mql8/.')
|
||||
arguments = parser.parse_args()
|
||||
HERE.mkdir(parents=True, exist_ok=True)
|
||||
original = json.loads(INPUT.read_text())
|
||||
sources = {str(p.relative_to(ROOT)): {'sha256': hashlib.sha256(p.read_bytes()).hexdigest(),
|
||||
'bytes': p.stat().st_size} for p in (AME, INPUT)}
|
||||
original = json.loads(INPUT.read_text(encoding='utf-8'))
|
||||
entities, edges, globals_, sim, model_info = read_drawing()
|
||||
mapping, matching = match_graph(entities, edges, original)
|
||||
corrected = deepcopy(original)
|
||||
@@ -266,7 +276,8 @@ def main():
|
||||
payload = ReactFlowProjectPayload.model_validate(executable)
|
||||
network = compile_reactflow_network(payload)
|
||||
program = compile_native_program(network)
|
||||
OUTPUT.write_text(json.dumps(corrected, ensure_ascii=False, indent=2) + '\n')
|
||||
if not arguments.check:
|
||||
OUTPUT.write_text(json.dumps(corrected, ensure_ascii=False, indent=2) + '\n', encoding='utf-8', newline='\n')
|
||||
xml = build_reactflow_system_xml(payload)
|
||||
(HERE / 'corrected.xml').write_bytes(xml if isinstance(xml, bytes) else xml.encode())
|
||||
# The archive's parameter table and run input have matching row order.
|
||||
@@ -296,7 +307,8 @@ def main():
|
||||
cache_checks.append({'dataPath': path, 'parameterDataLine': line,
|
||||
'drawingValue': drawing_value, 'runValue': run_value})
|
||||
audit = {
|
||||
'sources': {str(p.relative_to(ROOT)): {'sha256': hashlib.sha256(p.read_bytes()).hexdigest(), 'bytes': p.stat().st_size} for p in (AME, INPUT)},
|
||||
'sources': sources,
|
||||
'checkOnly': arguments.check,
|
||||
'output': str(OUTPUT.relative_to(ROOT)), 'globals': globals_, 'matching': matching,
|
||||
'counts': {'components': len(entities), 'connections': len(edges), 'parameters': len(parameter_audit),
|
||||
'changedParameters': len(parameter_changes), 'changedConnections': len(connection_changes),
|
||||
@@ -315,11 +327,16 @@ def main():
|
||||
'parameters': parameter_audit, 'connections': connection_audit,
|
||||
'evaluationSchedule': program.evaluation_schedule,
|
||||
}
|
||||
(HERE / 'audit.json').write_text(json.dumps(audit, ensure_ascii=False, indent=2) + '\n')
|
||||
(HERE / 'audit.json').write_text(json.dumps(audit, ensure_ascii=False, indent=2) + '\n', encoding='utf-8', newline='\n')
|
||||
print(json.dumps({'counts': audit['counts'], 'matching': matching,
|
||||
'parameters': parameter_changes, 'connections': connection_changes,
|
||||
'simulation': audit['simulation']}, ensure_ascii=False, indent=2))
|
||||
|
||||
if arguments.check:
|
||||
assert not parameter_changes, 'Current JSON parameters differ from AME; see audit.json.'
|
||||
assert not connection_changes, 'Current JSON connection ports differ from AME; see audit.json.'
|
||||
assert original['simulation'] == corrected['simulation'], 'Current JSON time settings differ from AME.'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in new issue
Block a user