最简单的示例#
现在我们已经准备好使用modelx进行练习,并且理解了modelx对象的基础知识,接下来我们将以斐波那契数列作为第一个建模示例。
斐波那契数列是一个整数序列,从0、1开始,后续的每个数字都是前两个数字相加得到的。
斐波那契数列可以用以下递归公式表示。
以下是n=10以内的斐波那契数列。
n |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
F(n) |
0 |
1 |
1 |
2 |
3 |
5 |
8 |
13 |
21 |
34 |
55 |
在modelx术语中,我们将n
称为参数,0, 1, 2, 3...
称为实参,
而0, 1, 1, 2, 3, ...
则是公式的返回值。
通过这个练习,我们将学习如何在modelx中执行基本操作。
创建单元格并定义其公式#
在您的Spyder IDE中找到MxExplorer小部件。

空白MxExplorer#
在右上角附近有一个标题为Model的下拉框。 这个下拉框用于选择要在下方窗格中显示的模型。 由于我们目前还没有模型,所以显示的是Current Model - None。
左侧的空白窗格用于显示所选模型中对象的树状结构。
在MxExplorer的空白处右键点击,会显示上下文菜单。选择菜单中的创建新单元格项。

MxExplorer中的上下文菜单#
弹出一个用于创建新Cells的对话框。

新建单元格对话框#
对话框包含3个标有Parent、Cells Name、Import As的文本框,在Import As前还有一个复选框,底部则是一个标题为Formula的代码编辑器框。默认情况下,所有文本框均为空白,且复选框处于勾选状态。
父级框用于选择我们将要创建的单元格的父级空间。单元格的父级空间是包含该单元格的空间。由于我们目前还没有任何模型或空间,因此该框中未列出任何项目。在本练习中,您可以保持该框不变,因为当单元格创建时,包含该单元格的模型和空间将自动创建,并使用它们的默认名称Model1
和Space1
。
单元格名称框用于指定单元格名称。
如果该框留空,则单元格名称将从公式框中输入的函数定义中获取。
您可以暂时留空单元格名称框,因为
稍后我们将在公式框中编写一个名为Fibo
的函数定义,
因此该单元格也将被命名为Fibo
。
导入为标签前的复选框用于指示是否要将新单元格导入关联MxConsole中IPython会话的全局命名空间,而导入为标签旁边的文本框用于指定全局变量的名称。如果留空,则变量名称将设置为单元格名称。
如果勾选此复选框,那么要在MxConsole中获取单元格Fibo
,只需输入:
>>> Fibo
如果不勾选此框,要获取单元格 Fibo
,您需要输入:
>>> mx.Model1.Space1.Fibo
因此勾选该复选框的效果等同于执行以下赋值语句:
>>> Fibo = mx.Model1.Space1.Fibo
在本示例中,您无需编辑这些内容,保持原样即可。 您只需要编辑公式框。
有几种方法可以编写返回斐波那契数列的函数。 在这个示例中,我们使用以下定义。 在公式框中编写以下代码,然后点击确定:
def Fibo(n):
if n > 1:
return Fibo(n-1) + Fibo(n-2)
else:
return n

新建单元格对话框#
现在你可以看到模型框中的选中文本已更改为当前模型 - Model1。
在MxExplorer的左侧,你会看到一个名为Space1的项目。
这意味着modelx创建了一个名为Model1
的新模型,并在Model1模型中创建了一个名为Space1
的UserSpace对象。
双击Space1项目,你将在Space1下看到一个名为Fibo的项目。
选择Fibo并右键点击调出上下文菜单。 从上下文菜单中选择显示属性, 然后您将在右下方面板中看到公式。

MxExplorer#
获取计算结果#
单元格 Fibo
在刚创建时还没有值。
我们使用MxConsole来访问Cells对象Fibo
。
记得在创建CellsFibo
时,我们在对话框中勾选了Import AS旁边的复选框,
同时将Import As的文本框留空。
这意味着创建的Cells对象Fibo
会以相同的名称Fibo
导入到MxConsole的命名空间中。
在MxConsole中输入Fibo[10]
(Fibo(10)
同样有效):
>>> Fibo[10]
55
55
,输出了第10个斐波那契数。
其值由关联的Formula自动计算, 当访问单元格值时。 请注意,不仅会为指定参数计算值, 还会为公式递归引用的参数计算值, 以获取指定参数的值。
由于Fibo[10]
引用了Fibo[9]
和Fibo[8]
,
Fibo[9]
又引用了Fibo[8]
和Fibo[7]
,
这种递归引用会一直持续直到在Fibo[1]
和Fibo[0]
处停止,
只需调用fibo[10]
就能计算出从0
到10
参数的Fibo
值。
要查看计算斐波那契数列使用了哪些参数, 您可以将单元格中的参数和值对作为字典获取:
>>> dict(Fibo)
{1: 1, 0: 0, 2: 1, 3: 2, 4: 3, 5: 5, 6: 8, 7: 13, 8: 21, 9: 34, 10: 55}
或者作为Pandas的Series或DataFrame对象:
>>> Fibo.series
n
1 1
0 0
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
Name: Fibo, dtype: int64
>>> Fibo.frame
Fibo
n
1 1
0 0
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
追踪计算#
追踪计算用于检查计算依赖关系。 例如,当您想要调试计算并检查计算是否正确基于预期值时,它非常有用。
要追踪Fibo[10]
的计算过程,
打开MxAnalyzer小部件,选择Precedents标签页,
在Object框中输入Fibo
,
在Args框中输入10
。
你将看到代表Fibo[10]
的条目出现在小部件中。
点击箭头展开该条目,你会看到
Fibo[9]
和Fibo[8]
从Fibo[10]
分支出来。
通过递归展开前置条目,你可以回溯
Fibo[10]
的计算过程,直到
追溯到Fibo[1]
和Fibo[0]
。

MxAnalyzer 前置条件选项卡#
同样地,你也可以在依赖项标签页中追踪Fibo
某个元素的依赖项,
例如Fibo[5]
。
依赖项是指那些直接或间接使用Fibo[5]
值进行计算的其他元素。

MxAnalyzer 依赖项标签页#
通过输入覆盖计算#
单元格的值可以由用户指定。当用户为某些参数赋值时,这些指定的值将优先于公式计算结果。让我们看看这是如何运作的。
现在单元格 Fibo
中已有 n=0, ... ,10
的值。
我们将通过给 Fibo[0]
赋值为 1
,来把 n=0
的值从 0
替换为 1
。
>>> Fibo[0] = 1
然后检查Fibo
中保存的所有值:
>>> dict(Fibo)
{1: 1, 0: 1}
可以看到,对于n=2, ..., 10
的值被清除了。
这是因为n=2, ..., 10
的值是通过递归计算得出的,
最终引用了Fibo[1]
和Fibo[0]
。
由于Fibo[0]
被你的输入更新了,
所有依赖的值都被清除了。
再次获取Fibo
直到n=10
的值:
>>> Fibo[10]
89
>> dict(Fibo)
{1: 1, 0: 1, 2: 2, 3: 3, 4: 5, 5: 8, 6: 13, 7: 21, 8: 34, 9: 55, 10: 89}
现在你可以看到,当n=10
时的值是89
,这个值在修改Fibo[0]
之前是n=11
对应的值。
保存工作#
最后一步是保存我们创建的Model。在MxExplorer中右键点击部件调出上下文菜单,然后选择Write Model项。

编写模型对话框#
顶部的线条框用于选择放置模型文件夹的位置。 点击文件夹按钮并选择您想要放置模型的文件夹。模型将被保存为多个文件, 存放在所选位置下的一个文件夹中。 在文件夹名称框中输入文件夹名称。 这里我们将文件夹命名为FiboModel,但您可以根据喜好自由命名。

写入模型对话框#
如果勾选了标有备份旧文件夹的复选框,并且存在同名文件夹时,系统会在创建新文件夹前,将原文件夹重命名为带有_BAK后缀加数字的形式,例如FiboModel_BAK1。 由于该路径下不存在名为FiboModel的文件夹,因此该复选框不会产生任何效果。 点击确定保存模型。
现在让我们检查保存的模型是否可以重新加载。 在MxExplorer的上下文菜单中,选择Read Model, 然后会出现Read Model对话框。
从文件夹按钮中选择模型文件夹。 模型名称框用于指定模型名称,如果您希望 将新模型命名为与保存名称不同的名称。 导入为复选框用于指示是否要为 模型定义一个全局名称,并指定变量名。 如果留空,变量名将设置为与模型名称相同。
在这个练习中,我们将模型名称留空并保持导入为勾选且空白,看看会发生什么。

读取模型对话框#
新模型将作为Model1
可用,而旧模型
会被重命名为Model1_BAK1
,您可以在
MxExplorer中的Model框中查看。

模型列表#
请注意,MxConsole中的全局变量Fibo
仍然指向旧模型Model1_BAK1
中的Cells:
>>> Fibo
<Cells Fibo(n) in Model1_BAK1.Space1>
新Model中的Fibo
单元格可以通过Model1.Space1.Fibo
访问,
因此重新定义Fibo
指向新的单元格:
>>> Model1.Space1.Fibo
<Cells Fibo(n) in Model1.Space1>
>>> Fibo = Model1.Space1.Fibo
现在,让我们检查一下 Fiob
在计算前的值。
>>> dict(Fibo)
{0: 1}
您可以看到只有您输入的值被记住,而计算出的值并未保存。您可以检查是否获得了与旧模型相同的值:
>>> Fibo[10]
89
>>> dict(Fibo)
{0: 1, 1: 1, 2: 2, 3: 3, 4: 5, 5: 8, 6: 13, 7: 21, 8: 34, 9: 55, 10: 89}