从Vensim案例PDF到可运行系统动力学模型:提取、生成与仿真校验 📅 发布时间:2026/9/17 13:58:57 👁 浏览次数: 简介这是一份面向系统动力学建模初学者与城市交通研究者的Vensim软件案例资料以PDF形式完整呈现上海地区私家车变化的系统动力学建模全过程帮助读者掌握从系统边界划定、因果关系分析到模型仿真与趋势预测的实操思路。压缩包内共1个PDF文件约372KB内容围绕城市居民私家车消费系统展开涵盖私车价格、使用费用、上牌费用、报废量、保有量等关键变量并梳理出15条正负反馈回路说明增长趋势与自我调节机制的作用方式还配有系统组成结构图与因果关系简图便于对照理解建模逻辑。目前已有1181人学习下载。通过这份案例读者可以完整看到需求导向建模的分析框架理解道路建设、居民收入、公共交通、政策因素等对私车需求的正负影响并借助模型结论认识上牌费用、使用费用调控与公交发展对私家车增长的抑制作用为开展类似城市交通系统仿真研究提供可参考的建模范例与变量筛选思路。1. 从一份 Vensim 软件案例.pdf 反推出可运行的系统动力学模型手里只有一份名为vensim软件案例.pdf的文件时直接翻页看结论很危险PDF 里的因果回路图、存量流量图、方程列表和仿真曲线往往缺了可执行模型文件.mdl。Vensim 的价值恰恰在于把文字案例变成可跑、可改参数、可做敏感性分析的模型。对 IT 从业者来说这件事可以拆成三步先把 PDF 当非结构化数据源提取变量与方程再按 Vensim 语法生成.mdl最后用命令脚本和 CSV 输出做验证。适合系统动力学入门者、做供应链或政策仿真的人以及需要把旧案例迁移到 Vensim PLE/DSS 的工程师。接下来不讨论 PDF 里某一页写了什么而是给出一套从 PDF 到模型的通用复现路径。2. Vensim 软件案例.pdf 的文本与表格提取用 pdfplumber 拆出变量和方程2.1 案例 PDF 里通常藏了哪几类可复原信息一份 Vensim 软件案例 PDF 常见结构是“图 表 方程列表 曲线”。图给人看表给参数方程列表才是能直接变成.mdl的硬信息。提取时先别急着写正则先把页面里的对象分桶变量名、方程、单位、初始值、表函数、时间边界。不同 PDF 质量差别很大有的方程是文本层有的已经转成图片后者只能走 OCR 或手工补录。PDF 中的信息Vensim 对应对象常见位置可提取性变量名变量名方程列表、存量流量图标签高方程方程表达式附录、脚注、正文段落中单位Units方程后括号、参数表中初始值INTEG第二参数存量说明、表下方注释中表函数WITH LOOKUP参数表、曲线图旁数据点低时间设置Time Bounds案例说明、仿真设置段高2.2 用 pdfplumber 提取文本和表格的最小脚本先做文本层提取再决定哪些页需要走表格提取。下面脚本把全角符号先归一化再用正则抓“变量 表达式”的行。它不保证抓到所有方程但能快速给出候选清单减少手工翻页。import pdfplumber import re import pandas as pd pdf_path vensim软件案例.pdf equations [] with pdfplumber.open(pdf_path) as pdf: for page_no, page in enumerate(pdf.pages, start1): text page.extract_text() or # 全角符号归一化PDF 里经常混用 text text.replace(, ).replace(, ().replace(, )) # 匹配中文或英文变量名后接等号 pattern r([A-Za-z\u4e00-\u9fa5][\w\u4e00-\u9fa5]*)\s*\s*([^\n]) for var, expr in re.findall(pattern, text): equations.append({ page: page_no, var: var.strip(), expr: expr.strip() }) df pd.DataFrame(equations).drop_duplicates(subset[var]) df.to_csv(extracted_equations.csv, indexFalse, encodingutf-8-sig) print(df.head(10))这段代码的核心参数是extract_text()的默认布局模式和正则分组。page_no用来回溯原页var和expr后面会变成.mdl的左右两边。drop_duplicates只按变量名去重适合方程列表重复出现的 PDF如果同一变量有多个版本应该保留全部并加page列人工裁决。若输出为空先打开 PDF 看文字能否选中选不中就是扫描件需要改用 OCR。2.3 变量分类与正则识别方程提取出的方程要按 Vensim 对象分类否则生成.mdl时会漏掉存量初值或把常量写成辅助变量。存量一定有INTEG或DELAY类结构流量通常出现在存量括号里辅助变量是普通表达式常量是纯数字或单参数。表函数在 PDF 里常以“输入值 / 输出值”表格出现需要单独转成WITH LOOKUP。变量类型Vensim 写法识别特征清洗动作存量INTEG(流量, 初值)含INTEG补第二参数流量普通方程出现在存量括号内检查单位/时间辅助变量普通方程无INTEG消循环依赖常量数值纯数字或单参数建参数表表函数WITH LOOKUP成对数据转 Lookup识别存量时正则不要只抓INTEG还要抓DELAY1、DELAY3、SMOOTH这些函数内部也隐含状态。识别流量时先找存量方程括号里的加减项再回表里匹配同名变量。若 PDF 里写的是“库存 生产 - 运输”但没写初值常见做法是先从案例曲线读初始点再在.mdl里补INTEG(生产 - 运输, 100)。初值来源必须标记不能默认为 0否则仿真曲线会整体偏移。2.4 提取阶段最容易翻车的 3 个细节第一是公式跨行。PDF 的文本层会把一个长方程拆成多行正则会只抓到半截。处理方式是按页合并文本遇到行尾是运算符或左括号时把下一行拼上来。第二是中文变量名和空格。Vensim 支持中文变量名但.mdl里空格和标点容易出问题建议先转成英文下划线命名再在注释里保留中文。第三是表格跨页。表函数数据常出现在两页之间extract_tables()会分开返回需要按表头合并。注意提取结果只是候选清单不要直接当成最终模型。PDF 里的方程可能有排版错误尤其是负号、乘号和上下标生成.mdl前必须逐条和原页对照。另外单位缺失是常见问题。Vensim 的单位检查能救命但前提是单位列被提取出来。若 PDF 只写了“件/月”没有统一到Units行可以先用注释保存等模型跑通后再补。不要为了跑通而删掉单位检查那会把量纲错误推迟到结果解释阶段。3. 把 Vensim 案例方程写成 .mdl存量流量图的语法与生成脚本3.1 Vensim .mdl 文件的最小骨架Vensim 模型文件是文本格式核心是“变量 表达式 ~ 单位 ~ 注释 |”。~分隔表达式、单位和注释|结束一条方程。存量用INTEG流量和辅助变量用普通表达式。下面是一个最小骨架包含一个存量、一个流量和一个阶跃输入。实际案例里的变量名可以替换但结构不变。(01) Inventory INTEG(Production - Shipment, 100) ~ Units: Widgets ~ 库存存量初值来自案例曲线起点 | (02) Production 20 STEP(5, 10) ~ Units: Widgets/Month ~ 第 10 个月开始增加 5 单位/月 | (03) Shipment Inventory / 4 ~ Units: Widgets/Month ~ 发货量按库存的四分之一计算 |每条方程后面的~ Units不是装饰Vensim 会用它做量纲一致性检查。STEP(5, 10)表示在第 10 个时间单位从 0 跳到 5常用于案例里的政策冲击。INTEG的第二参数必须是数值或常量表达式不能是随仿真变化的变量。若 PDF 案例里写的是“初始库存约 100”这里就填 100并在注释里保留“约”字来源。3.2 用 Python 按 CSV 变量表批量生成方程当提取出的方程有几十条时手工拼.mdl容易漏掉|和单位行。用 Python 读 CSV按行生成方程文本再补一个默认单位占位。生成后先不要急着在 Vensim 里运行先用文本编辑器检查括号是否成对。import pandas as pd rows pd.read_csv(extracted_equations.csv) lines [] for _, r in rows.iterrows(): var str(r[var]).strip() expr str(r[expr]).strip() # 去掉 PDF 里带出的编号例如 (01) expr expr.lstrip(0123456789(). ) # 单位先留占位后续在 Vensim 里逐条校准 lines.append(f{var} {expr}) lines.append(f ~ Units: TODO) lines.append(f ~ 从 vensim软件案例.pdf 第 {r[page]} 页提取) lines.append( |) mdl_text \n.join(lines) with open(case_model.mdl, w, encodingutf-8) as f: f.write(mdl_text) print(mdl_text[:800])这段脚本的关键在expr.lstrip和单位占位。lstrip去掉 PDF 方程前的编号和点号避免把(01)带进表达式。Units: TODO是故意留的Vensim 载入后会提示单位缺失比直接填错单位更安全。page列写进注释方便回溯原 PDF。若某条表达式中包含换行生成前要先把换行替换成空格否则.mdl会被截断。3.3 时间边界、积分方法和单位检查.mdl只描述方程仿真控制参数通常写在模型设置或命令脚本里。时间边界包括INITIAL TIME、FINAL TIME、TIME STEP和SAVEPER。积分方法在 Vensim 里可选 Euler、RK4 等系统动力学模型多数先用 Euler步长取 0.25 或 1。时间步长太大存量会震荡太小仿真变慢但精度提升有限。参数含义典型值填错后果INITIAL TIME仿真开始时间0初值对应不上FINAL TIME仿真结束时间100曲线被截断TIME STEP积分步长0.25 或 1震荡或过慢SAVEPER保存间隔1输出点太少Integration积分方法Euler/RK4刚性系统误差大单位检查要逐条对照存量单位是“件”流量单位必须是“件/月”辅助变量若参与加法单位必须一致。案例 PDF 里常把“月”和“年”混用生成.mdl时统一成同一时间单位。若暂时不知道单位先留TODO但不要让模型带TODO做敏感性分析否则量纲错误会伪装成参数敏感。3.4 生成 .mdl 后先做哪三步静态检查第一步查括号和|。每条方程必须以|结束INTEG、WITH LOOKUP的括号要成对。第二步查存量初值。所有INTEG必须有第二参数且初值不能是未定义变量。第三步查循环依赖。辅助变量之间不能出现A B 1、B A - 1这种代数环Vensim 会报 simultaneous equations需要把其中一个改成存量或延迟。提示静态检查可以用文本搜索完成。搜INTEG(看初值搜~ Units: TODO看单位缺口搜看变量名是否含空格或运算符。完成这三步后再载入 Vensim。若 Vensim 报“单位不一致”不要直接关掉单位检查先看是流量除时间漏了还是存量初值单位写成了流量单位。很多案例 PDF 的方程本身是对的错在提取时把单位行漏掉了。4. 在 Vensim 中跑通案例仿真参数、命令脚本与敏感性分析4.1 加载 .mdl 后必须设置的 4 个仿真参数载入case_model.mdl后先设置时间边界再设步长和保存间隔。Vensim PLE 里在Model Time Bounds设置DSS 里可以用命令脚本覆盖。下面四个参数决定仿真能不能复现 PDF 里的曲线形状。TIME STEP和SAVEPER不要设成相同值就完事步长是积分精度保存间隔是输出密度两者职责不同。参数建议起点调整依据INITIAL TIME0案例起点FINAL TIME100案例时间跨度TIME STEP0.25曲线是否震荡SAVEPER1输出 CSV 行数若 PDF 案例里的曲线是月度数据TIME STEP取 0.25 能让 Euler 积分更稳SAVEPER取 1 让输出和月度对齐。若曲线出现锯齿先减半步长再检查方程里是否有PULSE或STEP突变。突变本身不是错误但步长太大时突变点会被平滑掉。4.2 用 .cmd 命令脚本做批量仿真Vensim DSS 支持命令脚本适合把同一模型跑多组参数。常见写法如下先关闭交互再设置运行名、保存间隔和附加时间最后运行并另存 CSV。不同版本命令关键字可能略有差异但思路一致把仿真设置写成文本重复执行。SPECIALNOINTERACTION SIMULATERUNNAME|case_run_01| SIMULATESAVEPER|1| SIMULATEADDTIME|0| MENURUN MENUSAVEAS|case_run_01.csv|NOINTERACTION让 Vensim 不弹窗适合批处理。RUNNAME是本次运行的标识后续 CSV 用它命名。SAVEPER覆盖模型里的保存间隔。ADDTIME通常为 0表示从初始时间开始保存。SAVEAS把结果导出成 CSV列名就是变量名。若脚本执行后没有 CSV先检查 Vensim 版本是否支持.cmdPLE 版通常需要手动导出。4.3 敏感性分析和 SyntheSim 的使用边界SyntheSim 适合手动拖动常量看曲线怎么变。它不生成正式敏感性报告但能快速判断哪个参数最敏感。正式敏感性分析需要给参数指定分布例如均匀分布、正态分布再跑多次仿真。案例 PDF 里若只给了一条基准曲线可以先对三个关键常量做 ±20% 扰动看输出曲线的包络。注意敏感性分析前必须确保单位检查通过。单位不一致时参数扰动会同时改变量纲解释结果没有意义。常见做法是把关键常量做成参数表用 Python 生成多组.cmd每组改一个常量值再批量导出 CSV。这样比在界面里反复拖动更容易复现。若模型里有表函数敏感性分析要同时扰动表函数的输出点不能只改常量。4.4 仿真不收敛或曲线异常时的排查表Vensim 模型跑不起来多数不是软件问题而是方程结构或参数问题。下面表格按现象列排查顺序从最容易检查的开始。现象可能原因检查动作报 simultaneous equations辅助变量成环把一条改成存量或延迟曲线爆炸正反馈过强检查增益和初值曲线全为 0初值漏填搜INTEG(单位报错流量未除时间统一时间单位输出 CSV 为空SAVEPER太大改小保存间隔排查时先看 Vensim 的错误日志再回.mdl搜变量名。若错误指向某个辅助变量先把它的表达式拆成两步确认中间量是否合理。曲线爆炸不一定是方程错可能是案例本身就在模拟增长但增长率超过时间步长承载范围。把TIME STEP减半再跑若曲线稳定说明是数值积分问题不是结构问题。5. 从 Vensim 软件案例.pdf 到可复现报告输出 CSV 的校验技巧把 Vensim 导出的 CSV 和 PDF 里的观测曲线放在同一张图上是验证模型是否复现的关键一步。Vensim 的 CSV 前几行常带标题和单位读入时要跳过。下面代码把仿真列和观测列对齐计算 RMSE并画对比图。skiprows2是常见跳行数实际以 CSV 前几行内容为准。import pandas as pd import matplotlib.pyplot as plt sim pd.read_csv(case_run_01.csv, skiprows2) sim.columns sim.columns.str.strip() sim sim.rename(columns{sim.columns[0]: Time}) obs pd.read_csv(observed.csv) obs.columns obs.columns.str.strip() plt.plot(sim[Time], sim[Inventory], labelsim) plt.plot(obs[Time], obs[Inventory], o, labelobs) plt.xlabel(Time) plt.ylabel(Inventory) plt.legend() plt.tight_layout() plt.savefig(compare.png, dpi150) n min(len(sim), len(obs)) rmse ((sim[Inventory].values[:n] - obs[Inventory].values[:n]) ** 2).mean() ** 0.5 print(round(rmse, 3))rename把第一列统一成Time避免不同导出设置下列名不一致。n取两者较短长度防止观测数据比仿真短时报错。RMSE 只是入门指标曲线相位差大时还要看峰值时间和峰值的偏差。若 RMSE 高但曲线形状接近先检查初值和单位再调参数。把 RMSE 和参数偏移量写进同一张 CSV下一次仿真前先看这两列再决定改方程还是改参数。本文还有配套的精品资源点击获取