文西姆转换
PySD允许解析Vensim .mdl 文件并将结果转换为 AbstractModel
对象,稍后(构建过程)可以用于以另一种编程语言构建模型。
转换工作流
以下转换工作流程允许在解析其内容的同时拆分Vensim文件,以构建 AbstractModel
object.工作流程可总结如下:
Vensim file :将模型方程从草图中拆分,并允许将模型拆分为部分(主要部分和宏部分)。
Vensim section :是一套完整的变量和定义,可集成。然后,Vensim部分可以拆分为模型表达。
Vensim element :mdl文件中的定义,可以是后缀(子)范围定义或变量定义。它包括单位和评论。同一变量的定义分组在同一个
AbstractElement
object.允许解析其左侧(LHS)以获取脚注(子)范围或变量的名称,并根据使用的分配操作符(=,==,:=,(),:)将其作为特定类型的组件返回Vensim component :变量定义的分类对象,它取决于用于定义变量的操作符。可以解析其右侧(RHS)以获取该表达的抽象语法树(AST)。
一旦按照前面的步骤解析并分解了模型, AbstractModel
已经回来了
文西姆文件
VensimFile类允许读取原始的Vensim模型文件,使用File SectionsVisitor将其解析为Section元素,使用SketchVisitor解析其草图,以便对每个视图的变量进行分类。最终结果可以被输出到AbstractModel类,以便用另一种编程语言构建模型。
- class pysd.translators.vensim.vensim_file.VensimFile(mdl_path: str | Path, encoding: None | str = None)[源代码]
VensimFile类允许解析mdl文件。创建对象时,模型文件将自动打开;不必要的制表符、空白和断点将被删除;草图将从模型方程中拆分。
- 参数:
mdl_path (str or pathlib.Path) -- Vensim模型的路径。
encoding (str or None (optional)) -- 源模型文件的编码。如果无,则将从模型中读取编码,如果模型文件中未定义编码,则将设置为“UTF-8”。默认为无。
- property verbose
将模型信息打印到标准输出。
- parse(parse_all: bool = True) None [源代码]
使用“parsing_grammars/file_sections. pe”中给出的语法和FilesSectionsVisitor类来精简地解析模型文件,以访问解析的表达。
这会破坏VenssimSections中的模型文件,该文件对应于主模型部分和宏。
- 参数:
parse_all (bool (optional)) -- 如果为True,将自动解析创建的VensimSection对象。否则,这些对象将仅添加到self.sections中,而不会解析。默认为True。
- parse_sketch(subview_sep: List[str]) None [源代码]
使用“sparning_grammars/sketch. pe”中给出的语法和SketchVisitor类来精简地解析模型的草图,以访问解析的表达。
它将修改第一部分的views_dict,包括按视图对变量进行分类的字典。这个,应该在调用self.parse方法后调用。
- 参数:
subview_sep (list) -- 用于对文件夹和子目录中的模型视图进行分类的分隔符列表。分离器的顺序必须与视图名称中出现的顺序相同。例如,如果视图被命名为“economy:demand.exports”,如果subview_sep= [":", "."] 此视图的变量将包含在文件“exports.py”和economy/demand文件夹中。
- get_abstract_model() AbstractModel [源代码]
实例化构建期间使用的AbstractModel对象。该方法应该在解析模型(self.parse)之后调用,如果您想要按视图拆分变量,也应该在解析草图(self.parse_sketch)之后调用。这会自动从模型部分调用get_abstract_section方法。
- 返回:
AbstractModel --抽象模型对象,可用于以另一种语言构建模型。
- 返回类型:
文西姆部分
Section类允许使用SectionElementsVisitor将模型部分解析为元素。最终结果可以导出到AbstractSection类,以便用另一种编程语言构建模型。节可以是主模型(没有宏),也可以是宏定义。
- class pysd.translators.vensim.vensim_section.Section(name: str, path: Path, section_type: str, params: List[str], returns: List[str], content: str, split: bool, views_dict: dict | None)[源代码]
Section类允许解析模型部分的元素。
- 参数:
name (str) -- 部分名称。即,“__main__”代表主要部分,宏名称代表宏。
path (pathlib.Path) -- 部分路径。主要部分的模型名称和宏的干净宏名称。
section_type (str ('main' or 'macro')) -- 节类型。
params (list) -- 该部分采用的参数列表。如果是主要部分,那么它将是一个空列表。
returns (list) -- 返回该部分的变量列表。如果是主要部分,那么它将是一个空列表。
content (str) -- 部分内容为字符串。
split (bool) -- 如果为True,则创建的部分将根据views_dict拆分变量。
views_dict (dict) -- 观点词典。给出任何级别分类的变量,以便按文件将它们拆分。
- property verbose
将部分信息打印到标准输出。
- parse(parse_all: bool = True) None [源代码]
使用parsing_grammars/section_elements.peg中给出的语法和SectionElementsVisitor类来访问解析的表达式,使用parsimonious来解析section对象。
这将打破部分 (__main__ 或宏)在VenssimElements中,它们是每个模型表达LHS和RHS,具有已经解析的单元和描述。
- 参数:
parse_all (bool (optional)) -- 如果为True,将自动解析创建的VensimElement对象。否则,这些对象将仅添加到self.elements中,而不会解析。默认为True。
- get_abstract_section() AbstractSection [源代码]
实例化将在构建过程中使用的AbstractSection类的对象。应在解析部分(self.parse)后调用此方法。该方法由Model的get_abstract_mode方法自动调用,并自动生成AbstractSubScript范围并将组件合并到元素中。它还从每个模型组件调用get_abstract_components方法。
- 返回:
AbstractSection -- AbstractSection对象,可用于用另一种编程语言构建模型。
- 返回类型:
文西姆元素
Element类允许解析模型方程的LHS。根据LHS值,将返回一个SubscriptRange对象或一个Component对象。有四种组件类型:
组件:常规组件,用“=”定义。
UnchangeableConstant:不可更改的常数,用“==”定义。
数据:数据组件,用“:=”定义
:
语法组件有自己的解析器来处理表达的RHS,而其他3个组件共享同一个解析器。解析组件的最终结果可以被输出到AbstractElement对象,以便用其他编程语言构建模型。可以定义另外两个类似元素的对象,它们仅用于测试:
约束:现实检查的约束,用“:THE CONDITION:”定义
测试输入:用于测试的输入,用“:测试输入:”定义
- class pysd.translators.vensim.vensim_element.Element(equation: str, units: str, documentation: str)[源代码]
元素对象允许解析Vensim表达式的LHS。
- 参数:
- property verbose
将元素信息打印到标准输出。
- class pysd.translators.vensim.vensim_element.SubscriptRange(name: str, definition: List[str] | str | dict, mapping: List[str] = [])[源代码]
后缀范围定义,由Vensim中的“:”或“<->”定义。
- property verbose
将订阅范围信息打印到标准输出。
- get_abstract_subscript_range() AbstractSubscriptRange [源代码]
实例化用于构建的AbstractSubwrittRange对象。此方法由Sections的get_abstract_section方法自动调用。
- 返回:
AbstractSubscriptRange --AbstractSubwrittRange对象,可用于用另一种编程语言构建模型。
- 返回类型:
- class pysd.translators.vensim.vensim_element.Component(name: str, subscripts: Tuple[list, list], expression: str)[源代码]
由Vensim中的“名称= expr”定义的模型组件。
- 参数:
- get_abstract_component() AbstractComponent | AbstractLookup [源代码]
获取用于构建的抽象组件。此方法由Sections的get_abstract_section方法自动调用。
- 返回:
AbstractComponent --抽象组件对象,可用于以另一种语言构建模型。如果分量方程包括外部查找(GET XLS/DIRECT LOOKUPS),则将使用AbstractSYS类。
- 返回类型:
- class pysd.translators.vensim.vensim_element.UnchangeableConstant(name: str, subscripts: Tuple[list, list], expression: str)[源代码]
由Vensim中的“Name == expr”定义的不可更改的常数。此类继承自Components类。
- 参数:
- get_abstract_component() AbstractUnchangeableConstant [源代码]
获取用于构建的抽象组件。此方法由Sections的get_abstract_section方法自动调用。
- 返回:
AbstractComponent --抽象组件对象,可用于以另一种语言构建模型。
- 返回类型:
- class pysd.translators.vensim.vensim_element.Lookup(name: str, subscripts: Tuple[list, list], expression: str)[源代码]
收件箱组件,由Vensim中的“名称(expr)”定义。此类继承自Components类。
- 参数:
- parse() None [源代码]
使用parsing_grammars/lookups.peg中给出的语法和LookupsVisitor类来访问表达式的RHS,使用parsimonious解析组件对象。
- get_abstract_component() AbstractLookup [源代码]
获取用于构建的抽象组件。此方法由Sections的get_abstract_section方法自动调用。
- 返回:
AbstractComponent --抽象组件对象,可用于以另一种语言构建模型。
- 返回类型:
- class pysd.translators.vensim.vensim_element.Data(name: str, subscripts: Tuple[list, list], keyword: str, expression: str)[源代码]
数据组件,由Vensim中的“名称:= expr”定义。此类继承自Components类。
- 参数:
- parse() None [源代码]
使用“sparning_grammars/components. pe”中给出的语法和EquationVisitor类来节俭地解析组件对象,以访问表达的RHS。
如果表达为无,则将从Vensim中的VDF文件中读取数据。
- get_abstract_component() AbstractData [源代码]
获取用于构建的抽象组件。此方法由Sections的get_abstract_section方法自动调用。
- 返回:
AbstractComponent --抽象组件对象,可用于以另一种语言构建模型。
- 返回类型:
支持的功能和特征
转换器的持续开发将支持Vensim功能的完整子集。当前版本支持以下操作员、功能和功能。
运营商
支持所有基本操作符,包括下表中显示的操作符。
Vensim |
文西姆例子 |
抽象语法 |
---|---|---|
- |
-A |
逻辑结构( ['negative'] ,(A,)) |
+ |
+A |
A |
:不: |
:不:A |
逻辑结构( [':NOT:'] ,(A,)) |
Vensim |
文西姆例子 |
抽象语法 |
---|---|---|
^ |
A ^ B |
算术结构( ['^'] ,(A,B)) |
* |
A * B |
算术结构( ['*'] ,(A,B)) |
/ |
A / B |
算术结构( ['/'] ,(A,B)) |
+ |
A + B |
算术结构( ['+'] ,(A,B)) |
- |
A - B |
算术结构( ['-'] ,(A,B)) |
= |
A = B |
逻辑结构( ['='] ,(A,B)) |
<> |
A <> B |
逻辑结构( ['<>'] ,(A,B)) |
< |
A < B |
逻辑结构( ['<'] ,(A,B)) |
> |
A > B |
逻辑结构( ['>'] ,(A,B)) |
>= |
A >= B |
逻辑结构( ['>='] ,(A,B)) |
<= |
A <= B |
逻辑结构( ['<='] ,(A,B)) |
:和: |
A:和:B |
逻辑结构( [':AND:'] ,(A,B)) |
或: |
A:或:B |
逻辑结构( [':OR:'] ,(A,B)) |
此外,Vensim :EXCEPT: operator is also supported to manage exceptions in the subscripts. See the 下标 科.
功能
当前支持的Vensim功能列表详细信息如下:
Vensim |
文西姆例子 |
抽象语法 |
Vensim评论 |
---|---|---|---|
ABS |
ABS(A) |
CallStructure('abs', (A,)) |
|
MIN |
Min(A,B) |
呼叫结构(' min ',(A,B)) |
|
MAX |
MAX(A,B) |
呼叫结构(' max ',(A,B)) |
|
SQRT |
SQRT(A) |
呼叫结构(' SQRT ',(A,)) |
|
EXP |
EXP(A) |
CallStructure('exp',(A,)) |
|
LN |
LN(A) |
呼叫结构(' In ',(A,)) |
|
SIN |
SIN(A) |
呼叫结构(' sin ',(A,)) |
|
COS |
COS(A) |
呼叫结构(' cos ',(A,)) |
|
TAN |
TAN(A) |
CallStructure('tan',(A,)) |
|
ARCSIN |
阿尔克辛(A) |
呼叫结构(' arcsin ',(A,)) |
|
ARCCOS |
Arcos(A) |
CallStructure('arccos',(A,)) |
|
ARCTAN |
阿克坦(A) |
呼叫结构(“arctan”,(A,)) |
|
倒置矩阵 |
倒置矩阵(A) |
呼叫结构(' invert_matrix ',(A,)) |
|
ELMCOUNT |
埃尔默斯顿(A) |
CallStructure('elmcount',(A,)) |
|
INTEGER |
整体(A) |
CallArchitecture(' int ',(A,)) |
|
QUANTUM |
量子(A,B) |
呼叫结构(“量子”,(A,B)) |
|
MODULO |
莫杜洛(A,B) |
呼叫结构(“模”,(A,B)) |
|
IF THEN ELSE |
如果有其他情况(A、B、C) |
呼叫结构(' if_then_else ',(A,B)) |
|
XIDZ |
XIDZ(A,B,X) |
呼叫结构(' xidz ',(A,B,X)) |
|
ZIDZ |
ZIDZ(A,B) |
呼叫结构(' zidz ',(A,B)) |
|
VMIN |
VMIN(A[dim!]) |
呼叫结构(' vmin ',(A,)) |
|
VMAX |
MAX(A [dim!] ) |
CallStructure('vmax',(A,)) |
|
SUM |
总和(A [dim!] ) |
呼叫结构(' sum ',(A,)) |
|
PROD |
PROD(A [dim!] ) |
呼叫结构(' prod ',(A,)) |
|
PULSE |
脉冲(开始、宽度) |
呼叫结构('脉冲',(开始,宽度)) |
|
脉冲串 |
PULSE TRAIN(start, width, tbetween, end) |
CallStructure('pulse_train',(start,tbetween,width,end)) |
|
RAMP |
RAMP(slope、start_time、end_time) |
呼叫结构(' ramp ',(slope,start_time,end_time)) |
|
STEP |
Step(高度,Step_time) |
CallStructure('step',(height,step_time)) |
|
获得时间价值 |
获取时间值(相对于、抵消、测量) |
CallStructure('get_time_value',(relativeto,offset,measure)) |
并非所有案件都得到实施! |
矢量选择 |
VECTOR SELECT(sel_数组 [dim!] ,BEP_数组 [dim!] 、miss_val、n_action、e_action) |
CallArchitecture(' vector_select ',(sel_数组,BEP_数组,miss_val,n_action,e_action)) |
|
载体等级 |
VECTOR RANK(vec, direction) |
呼叫结构(' vector_rank ',(vec,Direction)) |
|
向量重排序 |
VECTOR REOrder(vec,svec) |
呼叫结构(' vector_reorder ',(vec,svec)) |
|
载体排序 |
VECTOR SORT ORDER(vec, direction) |
呼叫结构(' vector_sort_order ',(vec,Direction)) |
|
GAME |
游戏(A) |
游戏结构(A) |
|
分配可用 |
分配可用(请求,pp,可用) |
AllocateDeliverable Architecture(请求、pp、avenue) |
|
按优先级分配 |
按优先级分配(请求、优先级、尺寸、宽度、供应) |
AllocateByPriorityArchitecture(请求、优先级、大小、宽度、供应) |
|
INITIAL |
初始值 |
初始结构(值) |
|
如果正确,请抽样 |
SAMPLE IF TRUE(条件,输入,初始值) |
SampleIfTrueArchitecture(条件、输入、初始值) |
|
随机0 1 |
随机0 1() |
呼叫结构(' random_0_1 ',()) |
|
随机均匀 |
随机分布(m,x,s) |
CallArchitecture(' random_uniform ',(m,x,s)) |
|
随机正态 |
随机正态(m,x,h,r,s) |
呼叫结构(' random_normal ',(m,x,h,r,s)) |
|
随机指数 |
随机指数(m,x,h,r,s) |
呼叫结构(' random_exponential ',(m,x,h,r,s)) |
Vensim |
文西姆例子 |
抽象语法 |
---|---|---|
延迟1 I |
DELAY 1 I(输入、延迟时间、初始值) |
延迟结构(输入,延迟_时间,初始值,1) |
DELAY1 |
延迟1(输入,延迟时间) |
延迟结构(输入,delay_time,输入,1) |
延迟3 I |
DELAY 3I(输入、延迟时间、初始值) |
延迟结构(输入,延迟_时间,初始值,3) |
延迟3 |
DELAY3(input,delay_time) |
延迟结构(输入,delay_time,输入,3) |
延迟N |
延迟N(输入,延迟时间,初始值,n) |
DelayNStructure(输入,delay_time,initial_Value,n) |
延迟固定 |
DELAY FIXED(input,delay_time,initial_value) |
DelayFixed(输入、delay_time、initial_Value) |
SMOOTHI |
SMOOTH 1I(输入、延迟时间、初始值) |
SmoothFrame(输入,smth_time,initial_value,1) |
SMOOTH |
SMOOTH 1(输入,延迟时间) |
SmothArchitecture(输入,smth_time,输入,1) |
SMOOTH 3I |
SMOOTH3I(input, delay_time, initial_value) |
SmoothFrame(输入,smth_time,initial_value,3) |
SMOOTH 3 |
SMOOTH 3(输入,延迟时间) |
SmoothStructure(input,smth_time,input,3) |
光滑N |
SMOOTH N(输入,延迟时间,初始值,n) |
SmothNStructure(输入,smth_time,initional_Value,n) |
FORECAST |
预测(输入、平均时间、地平线) |
预测结构(输入,平均_时间,地平线,0) |
TREND |
趋势(输入、平均时间、初始趋势) |
TrendStructure(input, average_time, initial_trend) |
Vensim |
文西姆例子 |
抽象语法 |
---|---|---|
获取XLS数据 |
获取XLS数据('文件',',' time_row_or_col ',',' cell ') |
GetDataStructure('file','tab','time_row_or_col','cell') |
获取直接数据 |
GET DIRECT DATA('file','tab','time_row_or_col','cell') |
GetDataStructure('file','tab','time_row_or_col','cell') |
获取XLS查找 |
获取XLS LOOKUPS('文件',' tab ',' x_row_or_col ',' cell ')' |
GetLookupsArchitecture('文件',' x_row_or_col ',',cell ') |
直接查看 |
获取直接查找('文件',' tab ',' x_row_or_col ','获取直接查找(')', |
GetLookupsArchitecture('文件',' x_row_or_col ',',cell ') |
获取XLS常数 |
获取XLS Constants(' file ',' tab ',' cell ') |
GetConstantsStructure('file','tab','cell') |
获得直接稳定性 |
获取直接常数(“文件”、“tab”、“cell”) |
GetConstantsStructure('file','tab','cell') |
获得XLS提交 |
GET XLS SUBSCRIPT('file','tab','first_cell','last_cell','prefix') |
|
获得直接主题 |
获取直接主题('文件',' tab ',',',') |
股票
股票在Vensim中定义为 INTEG(flow, initial_value) 受支持并转换为AST为 IntegStructure(flow, initial_value) .
下标
还支持几个与下标相关的特性。其中包括:
不同范围的基本脚注操作。
下标范围和子范围定义。
基本脚注映射,其中脚注范围映射到完整范围(例如new_dim:A,B,C -> dim,dim_other)。目前尚不支持映射到部分范围(例如new_dim:A,B,C -> dim:E,F,G)。
下标复制(例如new_dim <->dim)。
:EXCEPT:具有任意数量参数的运算符。
用作变量的脚本(例如my_var [dim] =另一个var * dim)。
subscribe vector操作(例如SUM(my var [dim, dim!] )).
查找
支持Vensim Lookup表情。它们可以使用硬编码值、使用 GET LOOKUPS 功能或使用 WITH LOOKUPS 功能
数据
支持具有GET函数的数据定义和空数据定义(没有公式,Vensim使用VDF文件)。这些定义可能包括也可能不包括任何可能的插值关键字: :INTERPOLATE:, :LOOK FORWARD:, :HOLD BACKWARD:, :RAW:. These keywords will be stored in the 'keyword' argument of AbstractData
分别为“interpolate”、“look_forward”、“hold_backward”和“raw”。GET XLS/GROUP的抽象结构在支持的GET函数表中给出。空数据声明的抽象结构是 DataStructure
.
目前,支持应用于数据的任何特定功能(例如,SEARCH IF True、TIME SEARCH.),但未来可能会包括新的。
宏观
支持Vensim宏。关键字:MACRO:和:END OF MACRO:之间的宏内容被分类为模型的一部分,随后用于从模型的其余部分构建独立的部分。
计划的新功能和功能
废弃的功能和特性
如果正确,请注意
的复杂性 SHIFT IF TRUE 函数并且需要变异另一个变量中已经计算的值,因此该函数的实现暂时已被放弃。
然而,可以使用IF THEN ELSE在库存流中重现相同的行为。中给出了一个模型,该模型具有避免“如果真”并使模型与PySD一起工作的解决方法 issue #265 .