软件体系结构的“4+1”模型视图

警告

此页面已过时,因为它是为PySD 2.x编写的。然而,这里的内容可能对开发人员有用。有关PySD 3+架构,请参阅 Structure of the PySD module .

4+1 model view 由Philippe Krutchen设计,提供了一种使用多个并发视图来描述软件系统架构的方法。多个视图的使用允许分别解决架构的各个“利益相关者”(例如最终用户、开发人员、系统工程师、项目经理等)的担忧。

软件架构处理抽象、分解和合成、风格和系统的美观。为了描述软件架构,我们使用由多个视图或透视图形成的模型。该模型由五个主要视图组成:逻辑视图、开发视图、过程视图、物理视图以及场景或用户案例。

  • 物理视图:描述软件到硬件的映射并反映其分布式方面

  • 开发视图:描述软件在其开发环境中的静态组织。

  • 逻辑视图:是设计的对象模型

  • 流程视图:捕获设计的并发和同步方面

  • 场景:展示四个视图如何无缝协作

PySD的“4+1”模型视图

PySD的开发视图

包关系图,如图所示 PySD development view ,用于表示组成 PySD .此图表代表了PySD包的分层架构,不包括其模块之间的关系。在 PySD relationships between modules 我们可以找到PySD模块之间的关系。

../../_images/packages.png

PySD开发视图

pysd 是包含所有其他内容和系统的所有逻辑的主包。有必要区分称为 pysd 以及名为pysd的模块。后者允许用户与系统交互,并具有适当的功能来转换Vensim或XMILE模型,此外,还可以执行生成的转换。然而,本文档中没有定义XMILE转换过程。

pysd 模块与的模块交互 py_backend 包.这个包有两个子包: vensimxmile .的 vensim 包包含转换所需的所有逻辑 Vensim 模型

PySD relationships between modules 表示了主要模块之间的关系。为了清楚起见,每个模块都用其名称包表示。

../../_images/relationship-modules.png

模块之间的PySD关系

如上所述,用户与 pysd module.反过来, pysd 负责转换 Vensim 模型进入 Python 通过与 vensim2py ,这创建了正确的 Python 转换.在这个过程中, vensim2py 与模块的功能交互并使用模块的功能: external , utilsbuilder .为了执行执行过程, pysd 使用 functions module.

PySD的逻辑观点

下面详细介绍了每个PySD模块的用途,以及每个模块最重要的功能。

应该注意的是,在图表中,输入参数已详细说明, in 符号,输出参数 out 在函数中修改的符号和参数 inout 符号。此外,由于Python的动态类型,可以通过方便的图表中的注释来描述不同类型的参数。

Main modules of PySD : pysd , vensim2pytable2py 模块进行了详细介绍。的 pysd 模块处于 pysd 包裹,而 vensim2pytable2py 模块处于所述 vensim 包.

pysd 模块具有允许用户创建将Vensim模型转换成Python的必要功能。的 read_vensim() 函数将文本格式的Vensim模型作为参数,并将其转换为Model类的实例,该类位于 functions module.此外, pysd 具有 load() 函数,该函数可以从Python模型生成 Model 类,它可能能够执行和执行模拟。的 load() 函数在内部使用 read_ vensim() 功能

../../_images/main-modules.png

PySD主要模块

table2py 模块只有一个功能, read_tabular() .此函数允许读取表格形式(csv,tab或xlsx)的Vensim模型,并将其转换为Model类的实例。

此外, vensim2py 在该图表中表示。在 vensim2py ,的五个文法 PySD 定义了它们的相关类,这些类允许从Vensim模型解析和获取信息。

The main function of the vensim2py module, which is also used by the read_vensim() function of pysd module, is translate_vensim(). This function starts the translation process. The Vensim model is parsed with the first pysd grammar, file_structure_grammar, found in the get_file_sections() function. The file_structure_grammar divides the model into sections: the main section with the main code of the model and on the other hand, a section for each macro in the model. The obtained sections are passed as parameters to translate_section() function afterwards.

The functions get_model_elements(), get_equation_components(), parse_general_expression() and parse_lookup_expression() have the four remaining grammars of PySD which are: model_structure_grammar, component_structure_grammar, expression_grammar and lookup_grammar, respectively. In addition, after each of these functions, the NodeVisitor classes associated with each grammar are defined. These classes allow the parse tree to be performed and parsed.

值得注意的是, _include_common_grammar() 它具有所有其他语法使用的基本语法规则。

的复杂性 vensim2py ,因为它有五个函数,其中定义了PySD语法及其访问者类, Simplified vensim2py module 它没有细节地表现出来。这些类是:File Parser、Model Parser、EntentParser、ExpressionParser和LookupParser。请注意,这些类继承自NodeVisitor类,该类提供了一个反向控制框架,用于行走一棵树并返回基于该树的新结构。

../../_images/vensim2py-simply.png

简化的vensim 2py模块

Classes of pysd grammars (Part 1)Classes of pysd grammars (Part 2) 用与语法相关的类来表示。

../../_images/grammar1.png

pysd语法的类别(第1部分)

../../_images/grammar2.png

pysd语法的类别(第2部分)

每个类的方法是与不同语法规则相关的访问者方法。每个规则都没有访问者方法,但有一个与规则关联的访问者方法,用于存储有关解析模型的某些信息。在访问者方法中,相关信息存储在每个类的属性中,然后根据语法返回这些属性。

访问者方法总是有三个参数: self , nvc . Self 表示类的当前实例, n 属于节点类型,是正在访问的节点,并且 vcvisit children 是正在分析的运算式的子节点的所有结果的列表。从最后一个参数VC中获取信息并存储在类的属性中。

functions 模块表示为 Simplified functions module .它是PySD中最重要的模块之一,因为它具有将实例化Python转换模型的类,并且还具有运行模拟所需的逻辑。该图代表了它所拥有的类以及它们之间的关系。

../../_images/functions-simply.png

简化功能模块

functions 模块的详细信息可以在 Functions module (Part 1) 图表以及 Time 在此模块中定义类。在 functions ,我们可以找到许多在Vensim中使用但在Python中具有相关逻辑的函数,例如:PulSE、IF THEN ELSE、RAN多姆CLARORM等。

Time类别代表整个模拟过程中的时间。的 t 属性表示当前时间,该时间随着模拟的进行而变化,并且 step 属性表示每次迭代中发生的时间增量。

../../_images/functions1.png

功能模块(第1部分)

In the diagram Functions module (Part 2) the classes of the functions module Stateful, Integ, Macro and Model are represented in detail. The Stateful class is one of the most relevant classes of that module, since, except Time, all the classes inherit from it. This class makes it possible to represents the evolution of the state of a certain element models, recreating the simulation process in Vensim. To do so, it has an attributed called state that simulates the state of the elements and changes its value in each iteration of the simulation.

../../_images/functions2.png

功能模块(第2部分)

Integ级模拟Vensim股票。它接收并存储初始值,并具有获得执行积分所需的求导的函数。

Model类存储有关(转换的)模型主代码的所有信息。此类的一个实例称为pysd模型,它是Vensim文件的Python语言表示。 也就是说,Model类实现了模型的有状态元素的表示,并且具有访问和修改模型组件的大部分方法。此外,Model类负责将时间实例化为模型变量的函数,并且还负责通过欧拉积分执行模拟。

initialize() 该类的函数初始化模型模拟。的 run() 该功能允许通过增加步骤来模拟模型的行为。和 _euler_step() 函数允许一步完成欧拉积分,使用状态元素的状态并更新它。

Model类继承自Macro类。渲染Vensim宏的逻辑在Macro类中实现。此类获取在转换过程中创建的有状态对象,并初始化它们以稍后获取它们的派生对象和执行结果。Model执行与Macro相同的功能,但Model是根模型对象,因此它有更多方法来促进执行。

接着在 Builder module 附图 builder module.这个模块中没有定义类,但它负责使用转换中获得的结果在Python中创建文本模型。它有必要的代码来在pysd模型中组装Vensim或XMILE的所有元素,并从这些元素中创建Python兼容的版本。

../../_images/builder-module.png

构建器模块

的主要功能 builder 模块 build() .该函数构建并编写模型的Python表示。它被称为来自 vensim2py 完成Vensim模型转换的整个过程后,模块。作为参数,它传递已解析的模型的不同元素、脚注、命名空间和应写入Python表示结果的文件名称。该函数有某些永久代码行,这些代码行始终写入创建的模型中,但有些代码行是用之前在 vensim2py module.

在图像 Utils module 蕴含在 utils module.实用程序的主要目的是将对项目有用的所有功能汇集在一个模块中。其中许多功能在转换过程中会被多次使用。因此,正如已经在 PySD relationships between modules ,该模块由 builder , functions , externalvensim2py 模块。反过来, decorators , externalfunctions 模块导入到 utils 模块来定义已使用且在正在转换的模型中具有特定含义的名称列表。

../../_images/utils-module.png

Utils模块

Simplified external module 代表 external 模块及其包含的类,但没有详细信息。该模块中定义的类的主要目的是读取外部数据。外部模块的主要目标是将读取外部数据文件所需的所有功能或工具收集在一个文件中。

../../_images/external-simply.png

简化的外部模块

The figure External module (Part 1) shows the detailed diagrams of the External and Excels class.

External是该模块的主类,所有其他类都从它继承,Excels类除外。

../../_images/external1.png

外部模块(第1部分)

External类允许存储某些信息,例如正在读取的文件的名称及其包含的数据。

Excels类负责读取Excel文件并存储有关它们的信息,以避免多次读取这些文件,从而实现单例模式。

External module (Part 2) 将呈现从External类继承的所有类。

../../_images/external2.png

外部模块(第2部分)

在Vensim中,有不同的声明允许从用作Vensim模型中变量的外部文件获取数据。以下是PySD中支持的这些函数集。

要从诸如GET XLS GROUP和GET DIRECT GROUP这样的陈述中获取数据,需要ExtData类。反过来,对于GET XLS LOOKUPS和GET DIRECT LOOKUPS陈述,ExtSYS类。对于GET XLS CONSTANT和GET DIRECT CONSTANT函数,使用ExtConstant类,最后,为了实现GET XLS SUBTENT和GET DIRECT SUBTENT函数,使用ExtSubScript类。

这些运算式创建External类的新实例,其中存储了表示必要数据结构的信息。External类的这些实例在有状态对象之前被初始化。

要更好地理解下一个模块的功能和原因,请称为 decorators ,建议了解 Decorator pattern .

在PySD中,实现了一种两级缓存,以尽可能加快模型执行速度。缓存是使用装饰器实现的。在转换过程中,每个转换的陈述或函数都标记有两种类型的缓存之一。@ cache.run装饰器用于其值在模型执行期间为常数的函数。这样,它们的价值在模型的整个执行过程中仅计算一次。另一方面,其值必须随着每个执行步骤而更改的函数会使用@ ache.Step装饰器进行标记。

Decorators module 的人物 decorators 详细介绍了转换步骤中开发和装饰模型功能的功能所在的模块。

../../_images/decorators-module.png

装饰者模块

缓存类允许定义这些装饰器的功能。的 run()step() 函数定义PySD中使用的两级缓存的功能。的 reset() 函数重置作为参数输入的时间并清除标记为步骤的值的缓存。的 clean() 函数清除名称作为参数传递的缓存。

PySD的进程视图

活动图用于表示PySD流程视图。的 Main process view 是PySD的主要活动图,下图中呈现的其他图是其分解。

../../_images/main1.png

主要流程视图

当用户使用 read_vensim() 功能 pysd module.在此函数中, translate_vensim() 在内部调用函数,该函数作为参数传递给Vensim模型,并在 vensim2py module.这是修改文件路径扩展名时,将扩展名从mdl更改为py,因此Python中的转换模型将保存在与Vensim模型相同的路径中。然后,分割构成模型的部分,随后,从这些获得的部分中,创建包含模型中所有宏的列表。此外,每个部分都会被组织和转换,从而完成Python文件的转换。组成系统的子系统 Main process view 图在下面更详细地解释。

The figure Divide into sections shows the first subsystem. Inside the translate_vensim() function, the Vensim model is read in text mode and the grammar file_structure_grammar is responsible for separating the macros and the main code. This grammar is defined in the get_file_sections() function, in vensim2py module. In turn, in this function defines the class that has the visitor methods associated with the grammar rules, called FileParser. As result of this function and grammar, the text of the model is divided into a list with the different sections that compose it, and a section is obtained for each macro of the model and other section with the main code.

../../_images/divide-sentences2.png

分成部分

“划分为部分”序列完成后,它将继续创建宏列表,如所示 Create macro list 图表。在转换的这一部分中,所有标记为宏的部分都被过滤以将它们全部存储在列表中。因此,Vensim模型的所有宏都集中在一个列表中。

../../_images/macro-list3.png

创建宏列表

接下来,使用 translate_section() 功能 vensim2py module.

Organize each section 详细展示了这个序列,及其在中开发的子活动 Create Python namespaceParse each component 图.

../../_images/translate-section4.png

组织每个部分

In the figure Organize each section, from the get_model_elements() function (vensim2py module), each section is parsed with the grammar model_structure_grammar, which is responsible for organizing and updating the sections to elements of the model depending on whether they are equations or comments. In the get_model_elements() function, in addition to this grammar, the NodeVisitor class associated with it is defined which is called ModelParser. The model_structure_grammar grammar results the model divided into elements that, in turn, are organized by: equation, units, limits, doc and the kind of the statement. Later, as the model progresses through the different grammars of PySD, the new labels into which these elements are divided are update or added to the stored.

The elements that have been classified as comments do not influence the translation of the Vensim file, they are only useful for model developers. For this reason, a filter of all the model elements has been placed and the equation elements will be updated through the component_structure_grammar grammar, which is shown in Organize each section. This grammar adds more information about the name and the kind of equation. In summary, this grammar allows updating and detailing the information of the elements of the model that are equations. The component_structure_grammar grammar is in the get_equation_components() function of the vensim2py module as well as the NodeVisitor class, which contains the necessary logic and is called ComponentParser.

../../_images/namespace5.png

创建Python命名空间

“创建Python命名空间”子系统如图所示 Create Python namespace ,这是转换过程的下一步。命名空间是一个字典,由Vensim文件中包含的变量名称、后缀、函数和宏组成。为这些名称分配了Python中的安全名称。在Python中创建安全名称需要替换Vensim变量中允许的一些字符,但在Python中,这些字符在变量名称中无效,例如空白、关键字、未经授权的符号等。在本字典中,Vensim名称被存储为字典“key”,Python中相应的安全名称被存储在字典“values”中。

为此,在translate_section中,您可以访问以前获得的宏列表和已更新的不同部分。对于每个宏名称、每个宏参数和模型的其他元素,将向名称空间字典添加一条记录,该记录的名称在Vensim中表示该记录,而在Python中则表示相应的名称,该名称由 utils module.随后,创建另一个字典来添加组成模型的脚注的名称,如图所示 Create Python namespace .脚注的名称存储在另一个字典中,因为它们不用于创建Python函数,它们仅代表DataArrays的维度,并且在Python中不需要有安全名称。因此,这个脚注字典由模型中的所有脚注组成,并且它以脚注名称作为字典键,并以与其关联的脚注值作为字典值。

创建命名空间后,将继续解析不同的组件,如图所示 Parse each component (子系统 Organize each section ).在转换序列的此时,模型的元素按类型进行划分,例如正规表达或查找定义。

../../_images/parse-components6.png

解析每个组件

If it is an equation, it will be parsed with the expression_grammar grammar and if it is a lookup, the the lookup_grammar grammar will be used. The first grammar commented, expression_grammar, is found in the parse_general_expression() function of the vensim2py module, where the ExpressionParser class is also defined, which contains all the logic associated with this grammar.

查找_语法语法及其关联类LookupParser在 parse_lookup_expression() 功能 vensim2py module.两个语法都会再次更新存储的元素,并添加相应的Python转换作为每个元素的新标签。

完成此序列并返回图形后 Organize each section ,PySD转换过程以构建器结束。的 builder 模块负责使用 build() 该模块的功能。为此,它使用了流程中创建的命名空间以及之前转换并标记了相关信息的模型的不同元素,这些信息将成为最终Python文件的一部分。

PySD的物理视图

PySD 系统部署在单个工作站上,所需的一切都在同一个组件中。因此,在部署关系图中捕获PySD的物理视图不会添加有关系统的更多信息。

PySD的场景

整个过程中可以区分两种主要场景 PySD 图书馆项目。的过程 translating 从Vensim到Python的模型是第一个场景。发现的第二种情况是 execution 这允许执行模拟并允许用户获得Vensim模型的结果。