Anylogic用户手册2.docx
- 文档编号:8929064
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:134
- 大小:1.90MB
Anylogic用户手册2.docx
《Anylogic用户手册2.docx》由会员分享,可在线阅读,更多相关《Anylogic用户手册2.docx(134页珍藏版)》请在冰豆网上搜索。
Anylogic用户手册2
6.矩阵和超矩阵
6.1矩阵
AnyLogicTM支持使用向量和矩阵作为变量类型。
由于向量是矩阵的一个特例,在下面我们将把矩阵和向量统称为矩阵。
在AnyLogicTM中,你可以定义使用矩阵类型变量的方程式。
AnyLogicTM中的Matrix类为你提供了对矩阵进行定义,初始化,和访问的操作,以及其他主要的矩阵操作,包括求逆,转置,求矩阵的秩,LU分解,QR分解,奇异值分解,特征值分解,Cholesky分解,求矩阵的条件数(2阶范数),一阶范数,二阶范数,Frobenius范数,无穷范数,等等。
这个类是从JAMA组(一个JavaTM矩阵运算包,请参考http:
//math.nist.gov/javanumerics/jama/)改编过来的。
请参考AnyLogicTM类参考手册以了解更多的细节信息。
6.1.1定义一个矩阵
►定义一个矩阵变量
1.在结构图中选中此变量。
2.在Properties(属性)窗口中的Variabletype(变量类型)段,选择Matrix(矩阵)选项。
3.在Rows(行)编辑框中,指定矩阵的行数。
4.在Columns(列)编辑框中,指定矩阵的列数。
6.1.2为矩阵设置初始值
默认情况下矩阵中的所有元素值都将设置为0。
你可以为矩阵中的元素设置初始值。
►设置矩阵的初始值
1.在结构图中选中此变量。
2.在Properties(属性)窗口中的Equations(方程式)段,从Form下拉列表中选择Noequations(不包含方程式)。
3.指定InitialValue(初始值)表达式。
请使用这样的格式来定义初始值表达式:
用括号分开各个矩阵,逐行输入矩阵元素的值,将每行分别放置在一对括号中,使用逗号分隔一行中的元素以及不同的行。
请确认所有的行中都含有相同数目的元素。
例如,一个如下的矩阵:
对于二维矩阵,其值按行优先顺序输入:
在Initialvalue(初始值)属性中,输入如下内容:
为增加可读性,你可以将输入的内容分为多行:
你可以将一个矩阵初始化为单位矩阵,即主对角线元素都为1,非主对角线元素都为0的矩阵,方法是输入关键字identity。
6.1.3在模型查看器中访问和修改矩阵
6.1.3.1查看一个矩阵变量
你可以在模型运行时在模型的查看窗口中查看变量的当前值。
►打开查看窗口
1.在模型浏览器或结构图动画中右键点击此变量,然后在弹出菜单中选择Inspect(查看)。
此时即显示SelectItem(选择要查看的项目)对话框,如图53所示。
图53.选择要查看的项目对话框
2.选择你希望查看矩阵中指定的某些元素还是所有的元素。
3.点击OK。
此时即显示查看窗口(图54显示了一个矩阵的查看窗口)。
图54.矩阵的查看窗口
6.1.3.2修改一个矩阵变量
在模型仿真时,你可以对矩阵的元素进行修改。
►修改矩阵的一个元素
1.在模型浏览器或结构图动画中双击此矩阵变量,或者
在模型浏览器或结构图动画中右键点击此矩阵变量,然后在弹出菜单中选择Modify(修改)。
此时即显示Modify(修改)对话框(如图55)。
2.在Applyto(对…实施修改)段,指定你希望修改矩阵的某些元素,还是一次修改所有元素。
3.在Newvalue(新的值)编辑框中输入一个新的值。
4.点击OK。
图55.修改一个矩阵变量
6.1.4在代码中访问和修改矩阵
6.1.4.1在代码中定义和初始化一个矩阵
为在JavaTM代码(通常位于活动对象类代码窗口中的Startupcode(起始代码)段)中定义一个矩阵类型的变量,你可以使用以下几种方式之一:
创建一个具有指定数目的行和列的二维矩阵。
创建一个具有指定行数的向量。
创建一个1×1大小的矩阵,其唯一的元素值设置为你所指定的值。
创建一个矩阵,并且用指定的实数对此矩阵进行初始化。
创建一个矩阵,其元素值在[0,1]区间内均一分布。
创建一个单位矩阵,其主对角线元素值为1,非主对角线元素值为0。
创建一个3×4大小的矩阵,初始化其值为上述表达式中的内容。
矩阵元素值列表的格式与在矩阵的Initialvalue(初始值)属性中定义矩阵变量时的格式相同:
用大括号分开各个矩阵,逐行输入矩阵元素的值,将每行分别放置在一对大括号中,使用逗号分隔一行中的元素以及不同的行。
请确认所有的行中都有相同数目的元素。
为立刻在代码中初始化一个矩阵,请输入如下的代码:
doublea=newdouble[2][3];//创建一个元素为实数类型的矩阵
a[0][0]=5;a[0][1]=7.83;a[0][2]=-1;
a[1]=newdouble[]{0.2,-3.4,0};
A=newMatrix{2,3,a};
如果可以采用一个简单的算法来计算元素值,你可以使用循环来初始化此矩阵。
请参考下面这个例子:
输入如下代码以初始化此矩阵:
intm=3;//行数
intn=4;//列数
A=newMatrix(m,n);//创建新矩阵
for(inti=0;i for(intj=0;j if(j>=i)A.set(i,j,1-i+j); elseA.set(i,j,-5); } } 6.1.4.2在代码中修改和访问矩阵的一个元素 如果你需要在方程式中使用矩阵A的一个子矩阵(例如,其中的一个列),请使用下面这个函数: A.getMatrix(i0,i1,j0,j1) 其中点(i0,j0)和(i1,j1)即指定了所从矩阵A中选取的子矩阵的左上角和右下角元素的位置。 请注意元素的索引是从0开始的。 你可以在代码中通过调用如下函数来访问矩阵的单个元素: A.get(i,j)//如果A是一个矩阵 A.get(i)//如果A是一个向量 为修改矩阵的一个元素,请使用set(i,j,value)方法,例如: A=Matrix.identity(4,4); A.set(3,0,7);//设置左下角元素值为7 A.set(0,3,1);//设置右上角元素值为1 6.1.5在等式中使用矩阵 AnyLogicTM支持在方程式中使用基本类型以及矩阵类型的变量。 你可以定义一个微分方程组,代数方程组,以及一组公式,以描述变量随时间的连续变化。 这样你就可以定义连续时间的对象行为。 请查看第5章“方程式”以了解如何定义方程式。 如果你在方程式中使用了矩阵,则在等号右侧你可以使用表7中所列出的运算。 其中变量A和变量B都是矩阵类型,x是一个real类型的变量。 运算 描述 A+B,A-B,-A 加法,减法,一元反号 x*A,A*x 标量乘法 A*B 矩阵相乘 1/B 矩阵求逆 A/B 与逆矩阵相乘,等同于A*(1/B) A.transpose() 矩阵转置 A[i,j] 访问矩阵的一个元素 A[i] 访问矩阵的一行(如果矩阵为向量,则访问其中的一个元素) f(...,A,…) 调用一个接收矩阵类型参数的方法 表7.矩阵相关的运算 当为等号右侧部分生成代码时,AnyLogicTM遵循以下规则: ●如果所有的变量都是标量,则生成简单的代码,例如x*y+z,且返回的结果也被当作标量。 ●其他情况下AnyLogicTM将返回结果作为矩阵,并且生成下面这样的代码: Matrix.add(Matrix.mult(x,y),z). 为改变运算的顺序,你可以使用圆括号。 例如,对于矩阵微分方程式: 其中A,B,X都是方阵,大小为n*n;C,D,E为向量,大小为n*1。 方程式等号右侧正确的完整表达式为: 你可以显式地告诉AnyLogicTM一个方程式为标量类型,具体做法为在表达式的开头加上#号,例如a=#x*y+z。 这样做可以提高仿真性能。 如果表达式的值为标量类型,则标量表达式的右手侧也可以引用矩阵类型的变量。 在这个例子中,实数变量x的值可以通过以下公式计算出来: 6.1.6使用矩阵 Matrix类支持多种线性代数运算,你可以在方程式,活动对象类代码,和离散时间的处理函数(例如定时器的到时处理动作(Expirationaction),或状态图的状态转换动作)中使用这些运算。 表8是矩阵运算的列表。 运算 描述 A.plus(B) 矩阵加法: A+B。 A.minus(B) 矩阵减法: A-B。 A.uminus() 一元取反: (-A)。 A.times(x) 乘以标量: x*A。 A.times(B) 矩阵相乘: A*B。 A.inverse() 矩阵求逆: A-1。 A.transpose() 矩阵转置: AT。 A.norm1() 列最大值的和。 A.norm2() 最大的奇异值。 A.normInf() 行最大值的和。 A.normF() Frobenius范数: 所有元素的平方和的平方根。 A.solve(B) 求解满足A*X=B的矩阵X。 如果A不是方阵,则X为最小二乘解。 A.solveTranspose(B) 求解满足A*X=B,A’*X’=B’的矩阵X。 如果A不是方阵,则X为最小二乘解。 A.det() 求矩阵的行列式值。 A.rank() 用奇异值分解求得有效的数值秩。 A.cond() 求矩阵的条件数,即最大奇异值与最小奇异值之比。 表8.矩阵运算 下面是一个例子。 如果你要求值等于如下表达式的矩阵: 其中A,B,X都是n*n大小的方阵;C,D,E为向量,大小为n*1。 输入如下代码以创建这样的矩阵: 请注意如果你输入了形如A=B的代码,则你只是让A也引用了B所引用的矩阵。 如果你改变了矩阵B的值,则A的值也会改变,反之亦然。 为避免这样的依赖关系,你应将B的一个拷贝的值赋给A。 为创建一个矩阵的一个拷贝,输入如下代码: 如果你需要在某个时刻检查此矩阵的内容,你可以将它输出到全局的日志中。 你只需要在事件处理函数中适当的位置输入如下代码: 为求解线性方程式,输入如下代码: 为求解矩阵的特征值,输入如下代码: EigenvalueDecompositione=A.eig(); double[]eigRe=e.getRealEigenvalues();//实部的向量 double[]eigIm=e.getImagEigenvalues();//虚部的向量 MatrixV=e.getV();//特征向量矩阵 6.2超矩阵 超矩阵(Hyper-array)是一个维度为N的实数存储结构。 每一维都有有限数目个索引——即下标。 对超矩阵也定义了许多运算和函数。 你可以定义使用超矩阵的方程式,方法与定义使用标量变量的方程式相同。 在如下情况下请使用超矩阵: ●需要存储并访问大量的系数。 ●存在多个模型图层。 在第二种情况下,当你已经为某个子系统定义了模型,而又存在其他与第一个子系统结构相同,但具有不同的参数数值的子系统时,你即可以使用超矩阵。 你可以创建默认图表的拷贝,然后更改其中的参数,以此来建立多维的模型。 这样的方法有一个严重的缺点: 如果你希望对模型进行更改,则你需要进行修改的次数与模型中的图层数成正比;这样图表就会增大,变得难以理解。 超矩阵使你只需为所有的图层创建一个图表。 这样,模型即仍然能保持紧凑,并且你作出的更改将影响整个模型,而不是仅仅影响某个图层。 在学习超矩阵之前,你应首先了解枚举(enumeration)是什么。 6.2.1枚举 通过使用枚举变量(enumeration),你可以创建一个参数,以代表一个其值取自由此枚举类型所定义的有限个元素的集合的属性。 例如,你可以定义一个名为Color的枚举类型,其元素值为Red,Green,和Blue,然后就可以使用这些不言自明的名称作为变量的值。 6.2.1.1定义一个枚举类型 ►定义一个枚举类型 1.点击NewEnumeration(新建枚举类型)工具条按钮 ,或者 在主菜单中选择Insert|NewEnumeration(插入|新的枚举类型)。 此时即显示NewEnumeration(新建枚举类型)对话框。 在此对话框中指定新的枚举类型的名称,选择将包含此枚举类型的包,然后点击OK。 2.你也可以在Project(工程)窗口中,右键点击将包含此枚举类型的包,然后在弹出菜单中选择NewEnumeration…(新建枚举类型)。 此时即显示NewEnumeration(新建枚举类型)对话框。 在此对话框中指定新的枚举类型的名称,然后点击OK。 一个枚举类型可以具有如下的属性: 属性 Name(名称)——此枚举类型的名称。 Elements(元素)——枚举类型的元素集合。 Excludefrombuild(构建时排除)——如果设置了此属性,则此枚举类型将被排除出模型之外。 枚举元素在此枚举类型属性页的Elements(元素)表格中定义。 每个元素都定义于单独的一行中。 ►向枚举类型中加入一个枚举元素 1.在Project(工程)窗口中,点击此枚举类型。 2.在Properties(属性)窗口中,转到Elements(元素)表格的最后一行。 3.输入枚举元素的名称。 枚举元素在此表格中的顺序非常重要。 ►将一个元素在此表格中的位置上移/下移 1.在Properties(属性)窗口中,在Elements(元素)表格中选中此元素。 2.按Ctrl+Up/Ctrl+Down键。 在定义了枚举类型之后,你即可以: ●定义类型为此枚举类型的模型参数。 ●使用此枚举类型作为超矩阵的一维。 6.2.2定义超矩阵类型的变量 AnyLogicTM支持超矩阵类型的变量和参数。 ►定义一个超矩阵类型的参数 1.在Parameter(参数)对话框中,指定HyperArray作为参数类型。 2.在Defaultvalue(默认值)组合框中初始化此超矩阵。 例如,你可以使用一个超矩阵来初始化另一个超矩阵,用于初始化的超矩阵应在活动对象类的Additionalclasscode(附加的类代码)代码段中进行定义和初始化。 ►定义一个超矩阵类型的变量 1.在结构图中选中此变量。 2.在Properties(属性)窗口中,选择变量类型为Array(矩阵)。 在Array选项右方的表格中指定你所需要的维。 此表格的每一行即定义了超矩阵的一维。 为定义新的一维,请转到表格的最后一行,然后点击Dimension(维度)域。 在组合框中,选择一个枚举类型作为此超矩阵的一个下标。 一个超矩阵中不能使用同一个枚举类型作为两个或两个以上的维。 各个维的顺序也很重要。 你可以按Ctrl+Up和Ctrl+Down键来重新对超矩阵的维进行排序。 6.2.3为超矩阵设置初始值 ►设置一个超矩阵的初始值 1.在结构图中选中此变量。 2.在Properties(属性)窗口中的Equations(方程式)段,从Form下拉列表中选择Noequation(不包含方程式)。 3.定义InitialValue(初始值)表达式。 超矩阵类型的常量可以用两种不同的方式表达。 我们将通过使用超矩阵常量来作为一些变量的初始值来演示这两种方式。 下标将列在每个常量前面,并按照这些常量对应的超矩阵的维度声明时的顺序进行排列。 假定你创建一个国家的人均寿命模型,用于描述一些针对不同人群的社会或健康过程。 你可以使用三个属性将人群分开: 性别,年龄群体,和社会群体。 这些属性即符合枚举类型的概念。 你可以定义这样的枚举类型: Gender(male,female),Age(child,teenager,adult,aged),和SocialGroup(wealthy,middleclass,deprived)。 ●矩阵风格。 这一表达方式可以用于1D或2D数组。 ●JavaTM风格——这一表达方式可以用于具有任意维数的超矩阵。 为了使用一个标量常量来初始化超矩阵元素,你只需在Initialvalue(初始值)属性中输入所需的标量值。 如果你需要其元素值按某种规则分布的矩阵,你可以创建一个合适的分布对象(请参考第14章,“随机建模”),然后将它传递给此超矩阵的random()方法。 例如,如果你需要使用均匀分布于[min,max]区间内的元素来初始化矩阵A,那么你只需要在此矩阵的Initialvalue(初始值)属性中输入如下的代码: 你也可以在活动对象类的Startupcode(起始代码)段对矩阵进行初始化,输入如下代码: 6.2.3.1设置超矩阵中的指定元素 有些时候,你需要分别设置超矩阵中的一些元素组。 为此你可以在Startupcode(起始代码)或事件处理函数中调用set()方法: <超矩阵>.set([<下标列表>,]<值>); <下标列表>即指定了<超矩阵>中的哪些元素应赋值为<值>。 例如,超矩阵变量SmokingRate具有如下的维: SocialGroup,Age,Gender。 这一矩阵的可能的下标列表的例子列于表9中。 下标列表 描述 wealthy,teenagers,male 只有一个元素得到<值>的值——富有的男性青少年的吸烟率 wealthy,teenagers 由两个元素组成的向量得到<值>的值——富有的男性和女性青少年的吸烟率 teenagers 一个子矩阵中的元素都得到<值>的值——所有社会群体中的男性和女性青少年的吸烟率 矩阵的所有元素都将得到<值>的值 表9 6.2.4聚合函数 有的时候你需要对超矩阵的元素执行聚合操作。 表10是聚合函数的列表。 函数 描述 sum 求被聚合元素的总和: avg 求平均值: max,min 求被聚合元素的最大值/最小值 prod 所有元素的乘积: Stddev 标准偏差: 表10.超矩阵的聚合函数 使用这些函数的语法为: <超矩阵>.<函数名称>() 有时候你需要对子矩阵执行聚合运算。 你可以通过以下的函数调用来进行: <超矩阵>.get(<下标列表>).<函数名称>() <下标列表>定义了要执行聚合运算的子矩阵,其规则与set()方法相同(请参考第6.2.3.1节,“设置超矩阵中的指定元素” 6.2.5在方程式中使用超矩阵 AnyLogicTM支持在方程式中使用基本类型以及超矩阵类型的变量。 请参考第5章,“方程式”,以了解如何定义方程式。 你可以定义使用超矩阵类型变量的微分方程或公式,方法与定义标量变量的微分方程或公式相似。 然而,在此过程中仍然有一些特殊的地方,我们将在本节中加以描述。 6.2.5.1超矩阵的数学运算 与对矩阵的运算不同,超矩阵的运算并不遵循线性代数规则,而是对矩阵元素一一执行。 操作数可以具有不同的维度。 运算的结果是一个超矩阵,其维度与操作数下标的合集相同。 下面的图中示意了一些运算的例子[符号#代表运算符]。 如果两个操作数都具有相同的维度,则结果的超矩阵也具有相同的维度。 结果超矩阵的每个元素是这两个操作数超矩阵A和B中下标相同的元素进行此运算的结果。 图56.对具有相同维度的超矩阵进行运算 另一种情况: 一个操作数A的维度集合包含另一个操作数B的维度集合。 也就是说,两个维度集合的交集等于B的维度集合,两个维度集合的合集等于A的维度集合。 图57.超矩阵运算,其中一个超矩阵具有较少的维度 与整数或实数标量值(x)的运算即对超矩阵A中的每个元素都实行这样的运算(如图58所示)。 图58.超矩阵与标量之间的运算 在图59所示的例子中,结果的维度集合是所有下标的并集。 你可以将此运算描述为第一个矩阵与第二个矩阵中抽取出的向量之间的一系列运算(如图57所示)。 对于此图中的例子,结果超矩阵中的“wealthy”子矩阵(即“socialgroup”下标为“wealthy”,用红色标记)的计算方法即将超矩阵A与从B中抽取出的socialgroup为wealthy的向量之间进行计算。 图59.具有不同维度的矩阵之间的运算 6.2.5.2矩阵函数 所有预定义的函数和所有的你在工程中定义的查找表都可以接受标量和超矩阵作为参数。 在参数为超矩阵的情况下,一元函数即对此矩阵参数中的每个元素进行运算,与对标量的数学运算相似。 二元函数即对两个超矩阵进行运算,方法与对具有相同下标的超矩阵进行的运算相同。 6.2.5.3获得矩阵元素和子矩阵 有时候你需要访问一些特定的矩阵元素或一个子矩阵。 在方程式中你可以通过使用以下表达式来得到所需的矩阵元素或子矩阵: <超矩阵>[<下标列表>] <下标列表>即定义了要访问哪些矩阵元素或子矩阵,具体方法与set()方法中相同(请参考6.2.3.1节,“设置超矩阵中指定的元素”)。 例如,有一个名为Smoking_Rate的超矩阵,其中根据性别,年龄,和社会群体存储了人们的平均吸烟率。 为在方程中使用此超矩阵的某一个元素的值,你需要在方程表达式中输入如下代码。 你应指定所有维的下标。 为得到一个子矩阵,不要为所有维都指定下标。 例如,你对所有的属于贫穷社会群体的人的吸烟率感兴趣。 则你可以使用如下代码来获得对应的子矩阵,此子矩阵有两维,即(Gender,Age)。 7.消息传递 在许多情况下你都需要从一个活动对象向另一个活动对象发送一些信息。 在AnyLogicTM中,你可以通过传递消息(messages)——即携带了一些有用的信息的数据单元——来建立活动对象之间的相互作用。 消息可以用于建模现实世界中的多种对象。 你可以通过使用消息在你的系统中建立通知或信号机制——在这种情况下,消息可以代表在控制系统中传送的命令或信号。 你也可能需要在你的模型中建模实体流,这时消息即可以用于代表实体——实体将接受服务,被生产出,或接受由你定义的过程中的其他操作,这些实体可以代表商业过程中的文档,服务系统中的顾客,生产模型中的零件和产品,等等。 你可以在同一个模型中建立属于多种不同类型的实体。 消息通过活动对象中的特殊元素——端口(port)——进行发送和接收。 你只能在由连接器(connector)连接起来的两个端口之间进行消息传递,连接器即是消息在模型中流动的路径。 这一章对消息传递机制进行了详细的描述。 本章结构组织如下: ●第7.1节,“端口”,介绍了如何创建端口,以及如何向你的活动对象类中加入端口。 这一节也包括了对消息导向规则的详细描述。 ●第7.2节,“消息”,介绍了如何定义你自己的消息类。 如果你模型中在活动对象之间传递的消息上需要携带一些数据,则你应仔细阅读这一节。 ●第7.3节,“定义自定义的端口类”,这一节给出了对预定义的AnyLogicTM端口类的细节描述。 这一节介绍了如何创建你自己的具有自定义行为的端口类,以改变消息传递的语法。 请参照上述本章的结构以根据你的需求决定学习其中的哪些部分。 如果你使用AnyLogicTM的库对象创建你的模型,请参考第1.5.8节,“活动对象之间的相互作用”以了解如何连接多个对象,以
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Anylogic 用户手册