跳到主要内容

数据组件

图标

数据组件及其引用在不同情况下在画布中的对象图标

含义 | 种类变量变量引用容器容器引用
全局、实体个体属性、常规对象
实体观察者属性
流程临时对象\\
流程接口
实体个体内置属性\\\
实体观察者内置属性\\\

功能

数据元素用于存储数据,包括变量容器

数据格式

变量可支持各种数据格式(Value / List / Dict),容器是专门用于操作的Dict格式

作用域

数据对象能被直接访问到的区域叫做其作用域,这意味着你可以放置它的引用或在公式中直接使用对象名称来读写

原则

下级能直接读写上级画布的数据对象

全局属性

根画布数据对象作用域为全局,因此能在任意下级位置被访问和修改

实体属性

实体内画布(流程外)上的数据对象是实体属性,作用域为实体内,这意味着:

  • 在实体内,同一主体的实体属性,任意位置都能被直接访问和赋值
  • 在实体外,或实体内不同主体,由于不是其作用域,所以不能直接访问修改,但可以下方式间接交互:
    • 图形化建模访问对象,可以通过请求组件访问单个体属性,访问到的属性可以放置引用到当前画布,可以使用ask_component_name.Entity.property_name访问(不能赋值,因为组件的输出不能修改
    • 公式读写对象,可以使用single_entity_object.property_name进行单个体属性访问和赋值
    • 当然在作用域外,你也可以通过流程接口传递数据实现间接访问当时的取值
模型案例

Agent1以Ask和公式两种方式访问Agent2的两个初值均为0的属性xy并将他们都加10

DataComponents_image0.png

DataComponents_image00.png

  • 个体和观察者属性
    • 实体有个体属性也有观察者属性,归属取决数据对象属性面板的归属设定
    • 观察者属性作用域覆盖整个种群,即个体可以直接读写观察者属性
    • 个体属性作用域仅限于该个体,即观察者不能直接访问个体属性,其它个体也不行
    • 对个体属性来说,每个实体的个体都有一份自己的独立实例,请注意这不是同一个作用域
例子

对于羊个体的年龄属性,Sheep1Age不能被Sheep2直接读写,Sheep2需要使用Sheep1.Age形式在公式中读写,或者请求访问Age请求调用其方法修改Age

流程局部数据对象

  • 放置在流程内画布的数据对象
  • 作用域仅为流程内部(含子流程),无法被外部和上级直接访问
  • 在作用域外,当外部想访问被动流程的与当时触发其运行Trigger相关的中间状态,你可以通过流程接口传递数据实现间接访问当时的取值。即被动流程可将状态赋值保存到接口,由外部的后续计算访问对应端口以得到当时的最终状态,包括三种情况:
    • 上级流程,以sub_process.port_name
    • 调用,以call_component_name.port_name
    • 请求调用,以ask_component_name.port_name
  • 显然,访问到的值与当时触发其运行Trigger相关,这是由寄存机制保证的

建模使用

用于图形化建模

用于表达式

数据对象名称可用于构建表达式或公式

  • 作用域内访问时,直接使用数据对象名称即可
  • 对实体属性,在作用域外访问时,使用点语法 entity_single_object.property_name读写
  • 针对不同格式的数据对象,系统提供了相关方法,可使用 data_object.method 形式调用
提示
  • 由于公式中可以直接使用数据对象和流程步骤对象名称,因此需要注意重名的问题。
  • 对象重名时,公式栏识别的优先顺序详见计算章节中相关内容,系统也会提供模型警告信息

工作机制

初始化

模型初始化时系统遵循以下优先顺序:

  1. 全局对象
  2. 实体属性
  3. 局部对象

因此顺序在后的数据对象在设置初值时,可以使用关于顺序在前的数据对象的表达式,如全局变量X,可以用于设置Agent的属性变量初始值为2X

提示

根据上述规则有:

  • 实体属性可以使用关于全局变量的表达式进行初始化。
  • Agent种群的数量不能使用全局变量初始化,因为层级相同。
  • 实体行为流程的局部变量可以使用关于实体属性和全局变量的表达式初始化。
  • 主动流程开始事件中的参数可以使用其上级变量的表达式。

流程局部对象类型

  • 可以作为接口、常规对象和临时对象(仅变量)
  • 设置为接口后,在流程轮廓,调用请求调用该流程的对象轮廓,会显示对应的端口
  • 流程端口数据传递的方法详见流程的数据传递章节

寿命和寄存机制

  • 数据对象从被创建到销毁叫做其寿命
  • 存储状态与流程Trigger绑定叫做寄存机制,即数据对象为每个Trigger分别存储状态值,以供该Trigger后续触发的计算来访问

常规对象

  • 寿命永久,无寄存机制
  • 包括全局对象、实体属性、流程局部的常规对象、和非流程接口的容器,即除了以下临时对象外所有情况

临时对象

  • 流程临时变量

    • 寿命:从流程内开始事件创建Trigger时被创建,Trigger抵达结束事件销毁时也被销毁
    • 寄存:临时变量为上述每个Trigger存储对应值,由该Trigger触发的流程任意动作的计算都可以temp_variable_name直接访问
  • 容器接口

    由于对应端口只能以状态链传递对象

    • 寿命:与本流程无关
    • 寄存:无寄存
    • 接口所在流程内,表达式能以container_interface_name直接访问被状态链连接的容器对象
    • 接口所在流程内,能连接操作链进行容器操作
    • 可以向下级子流程或调用传递
    • 对应的端口不能用公式访问状态
  • 变量接口

    • 当对应端口以参数形式传递数值时,使用与流程临时变量完全相同,即有寄存,寄存值和寿命均与Trigger相关
    • 当对应端口被状态链连接用于传递外部变量对象时,无寄存,寿命也与本流程无关
    • 接口所在流程内,表达式以variable_interface_name 直接访问,或连接状态链继续向下级子流程端口传递,对应的端口不能用公式访问状态
模型案例:理解寄存

请以步进方式运行模型,并关注第5和第10Tick时Show变量的值。

开始事件在第1个Tick生成1个Trigger,Trigger流经第1个计算时将当前Tick(1)赋值给流程临时变量TempVar,经过滤波网关后走上分支,经过9Tick的时滞后,应在第10个Tick触发计算将TempVar赋值给Show常规变量。所以第10Tick时Show值为1。

开始事件在第3个Tick生成了第2个Trigger,Trigger流经第1个计算时将当前Tick(3)赋值给流程临时变量TempVar,经过滤波网关后走下分支,经过仅2Tick的时滞后,应率先在第5个Tick触发计算将TempVar赋值给Show常规变量。所以第5Tick时Show值为3。

正是由于TempVar寄存机制,即为两个Trigger分别寄存了当时的取值1和3,所以你从Show变量(没有寄存机制)看到了两个值的"后发先至"现象,即第5Tick为3、第10Tick为1,否则你应该看到Show在第5和第10Tick均为3。

建模交互

创建数据对象

  • 拖放数据组件到画布,即创建数据对象
  • 根据对象类型、所在画布、子类型设置等不同,显示的图标也不同,如上节“符号”

样式控制

DataComponents_image17.png

  • 点击画布中的数据对象会浮出样式控制条
  • 更换颜色、添加描述等详见建模基本操作
  • 切换对象形态:控制条的第1个按钮可以切换对象形态到监视器,再次点击可以切回图标样式

监视器

  • 监视器会实时显示当前数据对象存储值
  • 当数据对象为实体个体属性时,会以Dict形式呈现所有个体的值

数据订阅

系统根据用户具体“需求”向后台的模拟引擎订阅相关的模拟运行数据用于用户界面显示,从而尽可能提升计算性能。

这些需求包括:

提示

根据数据订阅机制有以下现象

  • 无论是否对数据对象进行绘图、切换监视器(即是否订阅),都不影响模拟结果
  • 如果你没有查看结果的需求,可以尝试尽量减少数据订阅(关闭监视器、删除相关图表和控制器)提高计算效率和模拟运行速度
  • 如果你在模拟进行到一半的时候查看数据结果(如某个变量的趋势折线图),那么此前Tick的历史无法看到,你可以重新运行得到完整结果