矩阵平衡算法


9

我一直在从头开始编写控制系统工具箱,而纯粹是在Python3中编写(无耻插件:)harold。从我过去的研究中,我总是care.m出于技术/无关的原因而抱怨Riccati求解器。

因此,我一直在编写自己的例程集。我找不到解决方法的一件事是获得一种高性能的平衡算法,至少与一样好balance.m。在提到它之前,xGEBALfamily在Scipy中公开,并且基本上可以从Scipy进行如下调用,假设您具有一个float类型的2D数组A

import scipy as sp
gebal = sp.linalg.get_lapack_funcs(('gebal'),(A,)) # this picks up DGEBAL
Ab, lo, hi, scaling , info = gebal(A, scale=1 , permute=1 , overwrite_a=0 )

现在,如果我使用以下测试矩阵

array([[ 6.      ,  0.      ,  0.      ,  0.      ,  0.000002],
       [ 0.      ,  8.      ,  0.      ,  0.      ,  0.      ],
       [ 2.      ,  2.      ,  6.      ,  0.      ,  0.      ],
       [ 2.      ,  2.      ,  0.      ,  8.      ,  0.      ],
       [ 0.      ,  0.      ,  0.000002,  0.      ,  2.      ]])

我懂了

array([[ 8.      ,  0.      ,  0.      ,  2.      ,  2.      ],
       [ 0.      ,  2.      ,  0.000002,  0.      ,  0.      ],
       [ 0.      ,  0.      ,  6.      ,  2.      ,  2.      ],
       [ 0.      ,  0.000002,  0.      ,  6.      ,  0.      ],
       [ 0.      ,  0.      ,  0.      ,  0.      ,  8.      ]])

但是,如果我将此传递给balance.m

>> balance(A)

ans =

    8.0000         0         0    0.0625    2.0000
         0    2.0000    0.0001         0         0
         0         0    6.0000    0.0002    0.0078
         0    0.0003         0    6.0000         0
         0         0         0         0    8.0000

如果检查排列模式,则它们是相同的,但是缩放比例已关闭。gebal给定标统一而MATLAB给出了2下列职权:[-5,0,8,0,2]

因此,显然,这些设备使用的不是同一台机器。我尝试了各种选择,例如Lemonnier,Van Dooren双面缩放,原始的Parlett-Reinsch以及其他一些鲜为人知的方法,例如的密集版本SPBALANCE

我可能要强调的一点是,我知道本纳的作品;特别是为此目的的哈密顿矩阵辛平衡。但是,请注意,此类处理是在gcare.m(通用Riccati求解器)内完成的,并且平衡直接通过进行balance.m。因此,如果有人可以指出我的实际实现,我将不胜感激。


披露:我真的不是在尝试逆向工程MathWorks代码:实际上,由于各种原因,包括这个问题的动机,我实际上想摆脱它,也就是说,我不知道它在做什么使我付出了很多代价。时光倒流。我的目的是要获得一个令人满意的平衡算法,该算法允许我传递CAREX示例,以便可以在常规求解器的顶部实现牛顿迭代方法。

Answers:


7

花了我一段时间解决这个问题,并且像往常一样变得显而易见 找到罪魁祸首后,

在检查了David S. Watkins报告的有问题的案例之后 平衡有害的情况。电子。反式 Numer。Anal,23:1-4,2006, 以及此处讨论(均在 arXiv:1401.5766v1中),事实证明matlab通过首先分离对角线元素来使用平衡。

我最初的想法是,根据有关LAPACK函数的经典有限文档,GEBAL自动执行此操作。但是,我想作者的意思是忽略对角线元素的并不是将它们从行/列总和中删除。

实际上,如果我手动从数组中删除对角线,那么两个结果都将重合,即

import scipy as sp
gebal = sp.linalg.get_lapack_funcs(('gebal'),(A,)) # this picks up DGEBAL
Ab, lo, hi, scaling , info = gebal(A - np.diag(np.diag(A)), scale=1 , permute=1 , overwrite_a=0 )  

给出与以下结果相同的结果 balance.m(当然没有对角线输入)相同。

如果有任何精通 Fortran的用户可以通过检查dgebal.f确认这一点,我将不胜感激。

编辑:以上结果并不意味着这是唯一的区别。我还构建了不同的矩阵,即使对角线分开后,GEBAL和balance.m也会产生不同的结果。

我很好奇这可能有什么区别,但是似乎没有办法知道,因为它是内置的matlab,因此是封闭的代码。

EDIT2:事实证明,matlab使用的是旧版本的LAPACK(可能在3.5.0之前),到2016b,它们似乎已升级到了新版本。现在,据我测试,结果一致。所以我认为这解决了问题。我应该已经用较旧的LAPACK版本进行了测试。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.