【问题标题】:Matlab: make a matrix by looping through an index without using a For loop?Matlab:通过在不使用 For 循环的情况下循环索引来制作矩阵?
【发布时间】:2015-08-25 21:33:18
【问题描述】:

我有一个函数A(k),当我输入例如A(1) 时,它会返回一个依赖于k 的矩阵。我想自动创建矩阵:

[A(3)*A(2)*A(1) A(3)*A(2) A(3)]

Mathematica 中我可以这样做:

Table[Apply[Dot,Table[A(k),{k,3,i,-1}]],{i,1,3}]

假设 A(k) 是一个返回 3x3 矩阵的函数。例如输入A(1) 可能会返回:

[1,2,3;4,5,6;7,8,9]

Mathematica 代码说明Table[A(k),{k,3,i,-1}] 是从 k=3 到 k=i 的“循环”,每次迭代将 k 递减 -1。因此输出将是 list {A(3),A(2),...,A(i)}... 显然 k 从 3 开始,然后对于 i=2,输出列表将是 {A(3),A(2)}。函数Apply[Dot,Table[A(k),{k,3,i,-1}]] 将列表的元素相乘。对于 i=2,这将产生 A(3)*A(2)。最后,Table[Apply[Dot,Table[A(k),{k,3,i,-1}]],{i,1,3}] 应用与第一条语句相同的逻辑,将i 从 1 循环到 3。因为内表依赖于 i,这将创建元素列表 {A(3)*A(2)*A(1),A(3)*A(2),A(3)}。列表是 Mathematica 的矩阵版本。

如何在 MATLAB 中实现相同的效果,即不使用 for 循环来实现结果?谢谢!

【问题讨论】:

  • 我可以假设你的数组的大小是 3 吗?在你的例子中不是很清楚。我也看不到参数 1 对预期输出的影响。你能再举几个例子说明你追求的是什么吗?
  • A(k) 的大小为 10x10。但我想这对于不同大小的数组的适用性并不重要。
  • 您为什么想要使用循环?...特别是因为您可以缓存早期的乘法并在以后的迭代中使用它?
  • 这不是代码高尔夫。我个人认为for 循环更适合您的目的。单行(对我来说)将需要几个arrayfun/cellfun 调用和cell2mat 调用来将所有内容转换回来。 for 循环具有更高的可读性,并且肯定会更快....不过,这是我的两分钱。
  • 现在有了解释,我同意 rayryeng。 for 循环可能是解决这个问题的最有效方法。

标签: matlab loops for-loop functional-programming


【解决方案1】:

为了记录,这是一个循环版本,主要用于后续的时间检查。这不是你想要的答案,而是你需要的答案;)

N = 10; %size of A
old = eye(N);
M2 = [];
for i=3:-1:1
   new = old*A(i);
   M2 = [new M2];
   old = new;
end

或者如果你想真正高效(可能不是这样):

N = 10; %size of A
M2 = A(3);
old = M2;
for i=2:-1:1
   new = old*A(i);
   M2 = [new M2];
   old = new;
end

【讨论】:

  • 谢谢。令人惊奇的是,在 mathematica.stackexchange 上,人们对将所有内容都纳入函数式编程而垂涎三尺……而这里恰恰相反,都是以效率的名义。我想知道什么是神话,什么是事实?我自己是一个 MATLAB 人,但最近我开始欣赏 Mma 的函数式语法。
  • @space_voyager 这不是相反的。在许多情况下,内置函数更加简洁和高效。你只需要知道什么时候放弃。至于Mma vs matlab:俗话说,如果你有一把锤子,很难不看到到处都是钉子。所以诀窍是使用那些最适合工作的工具,并适当地使用它们。
【解决方案2】:

This answer 基本上是解决问题的方法,但是当我们讨论高效使用 matlab 时,我想在这里留下我的想法,如何高效使用 Matlab。与大型 2D 矩阵不同,创建一个 3D 矩阵要简单得多,其中每个乘法的结果都堆叠在一起。如果可以接受 3D 矩阵,请按原样使用代码,否则在最后一行注释以获得 2D 矩阵。

M3=[];
n=3;
M3(:,:,n) = A(n);
for ix=n-1:-1:1
   M3(:,:,ix) = M3(:,:,ix+1)*A(i);
end
%M3=reshape(M3,size(M3,1),[]);

【讨论】:

  • 你的意思是M3=reshape(M3,10,[]);
  • 我认为 3 或 10 都是错误的。修复它以使用任意尺寸。一个很好的例子,为什么不在代码中使用幻数,还删除了所有其他幻数。
【解决方案3】:

您可以使用arrayfun() 和索引作为参数,例如:

%// Compute the product A(3)*A(2)*...*A(idx)
F = @(idx) prod(reshape(cell2mat(arrayfun(A,3:-1:idx, 'UniformOutput', false)),10,10,4-idx),3);
%// Use the last function with idx=1:3
M = cell2mat(arrayfun(F,1:3, 'UniformOutput', false));

【讨论】:

  • 你确定输出尺寸没问题?
  • arrayfun(A,3:-1:idx, 'UniformOutput', false) 工作正常,但 prod(cell2mat(...)) 没有返回 A(3)*A(2)*...*A(idx)
  • 你说得对,我无法尝试使用真正的函数 A 返回一个矩阵。可能cell2mat的输出有问题,但是没有合适的A()就很难调试
  • 试试B=rand(10); A=@(x)x*B;
  • 它有所不同,因为prod 会做一个元素乘积,但你需要一个矩阵乘积(去过那里,做过:)
猜你喜欢
  • 2013-02-16
  • 1970-01-01
  • 2020-05-12
  • 2014-05-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多