Discover MCPs & agents
Loading MCPs and agents…
Loading MCPs and agents…
Running is not correctness: a MATLAB / Simulink verification workflow for DeepSeek-class coding models.
From the repo.
Running ≠ correct: a practical workflow for driving DeepSeek-class LLMs to produce verifiable MATLAB / Simulink simulations — focused on numerical verification and human root-cause judgment, not just getting code that runs.
有一次我把一套裂缝扩展的 DDM 求解器从 Python 移植到 MATLAB,让模型照着参考实现写。 代码很顺地跑通了,也出了裂缝张开的结果,乍看没什么问题。可我一查全局影响系数矩阵的条件数, RCOND 到了 1.9e-39——矩阵基本是奇异的,那个"看着对"的结果数值上根本是垃圾。 模型不会主动告诉我这件事,因为对它来说代码"能跑"就算交差了。
我没在算法参数上瞎调,而是回到 Python 参考实现逐行对公式,最后发现问题出在影响系数的积分核: MATLAB 版写成了 ∫R dS,参考实现是 ∫(r/R³) dS。积分核的量纲错了,直接决定了矩阵病态。 换回正确的核,矩阵条件数恢复正常,结果也能和参考实现对上。
这件事是这份文档的由来。在工程仿真里,让 AI 写出"能跑"的代码是整个流程里最容易的一段; 难的是判断它写得到底对不对。而几乎所有关于 AI 辅助编程的讨论都停在"能不能跑通、效率高不高", 跳过了这件最要命的事——跑通不等于跑对,一个能跑、还画得出漂亮波形的仿真,数值上可能从头错到尾。 这份文档讲的就是怎么解决它:怎么把任务切成有可验证产出的小块,怎么用 run-verify 回路逼出正确结果, 怎么在模型判不了对错的地方靠人把关。
工具上我绕了一圈才落定:最早用 windsurf 直接操控 MATLAB 的 COM 接口,后来换 opencode 的 plan/code 模式——但这俩模式要人工切换、呆板低效,最后落在 Claude Code 直接接 DeepSeek。 DeepSeek 产出快、迭代快,需求说清楚就能高效出活;但"能产出"和"产出正确"是两回事, 后者才是本文要解决的。
贯穿全篇的一个前提:模型对"对不对"没有可靠的自我判断,它的价值在于快速产出和快速改; 判对错、定根因这两件事必须由人锚住(详见第 4、6 块)。下面六块按这个逻辑展开。
examples/robot_arm_ctc_interp_demo:第 4.7 节的六自由度机械臂 CTC 例子。它用同一组 waypoint 分别跑 linear 和 spline 插值,展示"位置跟踪看起来正常,但 linear 会在力矩里打出周期尖峰"。脚本会输出曲线图和关键统计值,当前 J3 力矩峰值比约为 5.44。适合的共同特征:
实测跑得通的任务类型:
吃力 / 不适合(详见第 6 块):
按"每个子任务都有独立、可验证的产出"来切。典型分层:
拆解时的两条判断:
工具约束补一句:Simulink 这种,逻辑上按上面分层,但"建块 + 连线 + 保存"在实操里要尽量 压进一次调用完成(中途关模型会丢未保存的连线),所以"子任务边界"和"一次调用边界"不完全等同。
话术分两层,这是这套打法最容易被忽略的点。看历史会话里真实发出去的 prompt, 绝大多数是高层委派、很短,例如:
也就是说,具体的工程约束(MATLAB 版本、已知坑、验证标准、看图协议)不靠每条 prompt 重复打, 而是前置固化在持久文件里——全局规则文件、skill 说明、项目的 HANDOFF / STATE / 协议文档。 模型每次会话开头读这些,等于把"长 prompt"摊销成了一次性配置。所以"怎么 prompt"真正的功夫 在于:把下面这些护栏写进持久文件,而不是指望临场把它们说全。
要固化进持久文件的护栏 ——
让它探测,别让它猜:
get_param(block,'DialogParameters') 列出可设参数,确认后再 set_param"。new_system 里测块的参数名,跑通再写进正式 build"。把已知坑写进 prompt 当护栏(这些是反复栽过的):
bc.(['e' num2str(i)]))。/(被当路径分隔符)。arrayfun 匿名函数逐元素处理:@(s) f(s) 而不是 @(s) f(整个数组)。diff()+zero-pad(端点出伪值),用中央差 + 端点前后向差。interp1(...,'spline') 不用 'linear'(linear 的二阶导出尖峰)。要求可独立运行 + 自带自检输出:
ALL_OK、RCOND、Pmax、final 值等),
让"对不对"直接出现在 stdout 里,不用人去翻变量。移植类任务锚定参考实现:
指定交付体系(有兼容要求时):
tiledlayout / exportgraphics /
writematrix / readmatrix / string / arguments / datetime / table"。Simulink 配置:
Block/LConn1 是 Simscape 物理口,Block/1 是 Simulink 信号口。模型自己判不了对错,验证基准必须人来定。按下面几层逐层过。
interp1 用了 linear;
末端单点尖峰,根因是 diff()+zero-pad 造的伪加速度。find_system('Type','Line') 返回空,
连线是否生效要用 get_param(block,'PortConnectivity') 查 SrcBlock。.m 没重载,跑的可能是旧版,先 clear functions; rehash;
.m 和 .slx 同名时 run 跑的是模型不是脚本。csvwrite 会覆盖带表头的 CSV、print 会覆盖 PNG,
用临时副本跑,跑完再确认正式目录没被污染。bdclose('all') 清干净再重载。把上面几层串起来看一个真实例子——六自由度机械臂的轨迹跟踪控制仿真。
这条线里每一步都对应前面的一层:可量化产出(力矩曲线)、看形状找伪信号(规律尖峰)、 用对照实验区分控制器问题和数据问题(换控制器重跑)、归因到上游表示、做最小修复。 模型能跑完整条仿真,但"位置对就算对"这个坑它自己跨不过去——识别尖峰、设计对照、 追到 interp1 这一串判断,是人做的。
DialogParameters,别对着文档猜参数名。bdclose('all') + 全量重建更可靠。.m 报日期格式错时改成逐段执行;
含中文路径写成脚本文件跑,不要用命令行内联(编码会乱)。pinv(J)*dx 不产生实际位移。根因不一定能定位清,务实解是绕开(改数值差分)。
模型不会自己发现这类,得人意识到"工具可能在骗我"。下面第一条是 DeepSeek 类模型实测最硬的短板,有具体案例;其余几条是从任务性质里 总结的、任何模型都要人把关的点。
仿真任务里图无处不在:客户给的系统单线图、技术图纸、衰减曲线截图, 以及"参考图 vs 当前仿真输出对不对"的对照判断。盲模型这几件事全做不了。实测两类典型:
实测可行的解法是给它配一双"外挂眼睛":把图截下来交给一个独立视觉模型(Qwen-VL 一类), 让视觉模型出文字描述 / 差异点,主模型再据此改代码。这个看图协议要写进持久文件 (例如 "你没有视觉能力,所有图片判断先截图交给视觉模型评价,再据反馈改代码"), 否则盲模型会默默忽略图、按文字硬编,产出和客户图对不上。
补充:DeepSeek 近期已上视觉模型,这道墙在变矮;但"主模型 + 外挂视觉模型"的分工对 任何缺视觉 / 视觉弱的中转模型仍是稳妥兜底,值得作为默认流程保留。
Replace {MCP_ENDPOINT_URL} with this MCP’s endpoint URL (from its repo or docs above). No API key — you connect directly.
Tool
OS
Config file: ~/.cursor/mcp.json
{
"mcpServers": {
"mcp-server": {
"url": "{MCP_ENDPOINT_URL}"
}
}
}Paste into mcpServers in the config file. Restart Cursor after saving.
If this MCP is also published on mcpchannel.ai, you can subscribe from Browse and use the gateway config there instead.