小智 7
嗯,首先,你几乎从未真正想要计算一个决定因素,你只是认为你这样做.事实上,它几乎从来都不是一件好事,因为决定因素的规模很小.它们常常用于推断矩阵的奇点状态,这在数值分析方面是一件可怕的事情.
一般地说我对决定因素的迷恋...
选项1:
将3-d数组转换为方形矩阵的单元阵列,将数组的每个平面作为一个单元格.mat2cell可以轻松有效地完成这项工作.
接下来,在单元阵列上使用cellfun.cellfun可以将函数(@det)应用于每个单元格,然后返回一个行列式的向量.这难以置信吗?只要在编写循环时预先预先分配向量,它可能不会比在循环中应用det有很大的好处.
方案2:
如果矩阵很小,例如2x2或3x3矩阵,则将明确的向量乘法扩展出行列式的乘法.我认为这不清楚,因为我正在写它,所以对于2x2的情况,其中Y是2x2xn:
d = Y(1,1,:).*Y(2,2,:) - Y(1,2,:).*Y(2,1,:);
Run Code Online (Sandbox Code Playgroud)
当然,你会发现这形成了矩阵Y的每个平面的2x2行列式的向量.3x3的情况也足够简单,也可以作为6个3路乘积的项.我没有仔细检查下面的3x3案例,但它应该是关闭的.
d = Y(1,1,:).*Y(2,2,:).*Y(3,3,:) + ...
Y(2,1,:).*Y(3,2,:).*Y(1,3,:) + ...
Y(3,1,:).*Y(1,2,:).*Y(2,3,:) - ...
Y(3,1,:).*Y(2,2,:).*Y(1,3,:) - ...
Y(2,1,:).*Y(1,2,:).*Y(3,3,:) - ...
Y(1,1,:).*Y(3,2,:).*Y(2,3,:);
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,OPTION 2将非常快,并且它是矢量化的.
编辑:作为对Chris的回应,所需时间存在显着差异.考虑一组1e5矩阵所需的时间.
p = 2;
n = 1e5;
Y = rand(p,p,n);
tic,
d0 = squeeze(Y(1,1,:).*Y(2,2,:) - Y(2,1,:).*Y(1,2,:));
toc
Elapsed time is 0.002141 seconds.
tic,
X = squeeze(mat2cell(Y,p,p,ones(1,n)));
d1= cellfun(@det,X);
toc
Elapsed time is 12.041883 seconds.
Run Code Online (Sandbox Code Playgroud)
这两个调用将相同的值返回到浮点垃圾桶中.
std(d0-d1)
ans =
3.8312e-17
Run Code Online (Sandbox Code Playgroud)
一个循环不会更好,事实上,肯定更糟.那么我是否要编写一段代码,该代码将面临为数组中的许多此类矩阵生成行列式的任务,我将特别考虑2x2和3x3矩阵的代码.我甚至可以写出4x4矩阵.是的,写出来是一团糟,但所需的时间差别很大.
一个原因是MATLAB的det使用对LU的调用,对矩阵进行分解.理论上这比中等大型矩阵的乘法更好,但对于2x2或3x3,额外的开销是杀手.(我不会猜到收支平衡点落在哪里,但人们可以很容易地测试它.)