返回行列式向量 - Matlab

Day*_*mer 5 matlab matrix

我有一个3维Y(i,j,w)的矩阵.我想得到一个行列式向量d(w),其中每个数字都是矩阵Y(:,:,w)的行列式.

是否有优雅的语法,或者我只需要使用循环?

谢谢

小智 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,额外的开销是杀手.(我不会猜到收支平衡点落在哪里,但人们可以很容易地测试它.)

  • @ChrisA - 12.041883/0.002141 = 5624.4令人震惊的差异? (2认同)
  • @Day_Dreamer,你应该总是用"家庭作业"标签标记作业的帖子. (2认同)