【问题标题】:ind2sub for nonzero elements of triangular matrixind2sub 用于三角矩阵的非零元素
【发布时间】:2017-03-05 19:14:28
【问题描述】:

我只是想简单地找到 (row, col) 的索引,它是矩阵 A 的最小点。我可以使用

[minval, imin] = min( A(:) )

和MATLAB内置函数

[irow, icol] = ind2sub(imin);

但出于效率原因,矩阵 A 是三角矩阵,我想实现以下函数

function [i1, i2] = myind2ind(ii, N);

k = 1;
for i = 1:N
    for j = i+1:N
        I(k, 1) = i;    I(k, 2) = j;
        k = k + 1;
    end
end
i1 = I(ii, 1);
i2 = I(ii, 2);

此函数为以下输入返回 8 和 31

[irow, icol] = myind2ind(212, 31);  % irow=8, icol = 31

如何在不使用内部“I”的情况下更有效地实现 myind2ind 函数?

【问题讨论】:

  • ind2sub 非常高效且不使用循环。你确定你可以比 MATLAB 更快吗?
  • 我只是想自己用其他语言实现。
  • 尽量不要使用 'i' 和 'j' 作为变量,因为它们是为复数的虚部保留的。
  • 在您的控制台中输入edit sub2ind,您可以看到 Mathworks 是如何实现它的。获取灵感并将其翻译成您的其他语言。您会看到 90% 的代码只是输入检查,二维矩阵的实际计算只需要几行代码。
  • 我的错,我的意思是edit ind2sub ...但同样的推理。另外,如果你实现一种方式,你也可以编写反向操作。

标签: matlab matrix indexing


【解决方案1】:

I矩阵可以由nchoosek生成。

例如,如果N = 5 我们有:

N =5
I= nchoosek(1:N,2)
ans =

   1   2
   1   3
   1   4
   1   5
   2   3
   2   4
   2   5
   3   4
   3   5
   4   5

这样

4 repeated 1 times
3 repeated 2 times
2 repeated 3 times
1 repeated 4 times

我们可以通过Gauss formula for triangular number得到I的行数

(N-1) * (N-1+1) /2 =
N * (N -1) / 2 =
10

给定 jj = size(I,1) + 1 - ii 作为从 I 末尾开始的行索引 I 并使用 N * (N -1) / 2 我们可以制定一个二次方程:

N * (N -1) / 2 = jj
(N^2 -N)/2 =jj

所以

N^2 -N - 2*jj = 0

它的根是:

r = (1+sqrt(8*jj))/2

r 可以舍入并从N 中减去,以获得所需输出的第一个元素(三角矩阵的行数)。

R = N + 1 -floor(r);

对于列号,我们找到当前行R的第一个元素idx_first的索引:

idx_first=(floor(r+1) .* floor(r)) /2;

可以通过从当前行的第一个元素的线性索引中减去当前线性索引并在其上加上R来找到列号。

这是实现的功能:

function [R , C] = myind2ind(ii, N)
    jj = N * (N - 1) / 2 + 1  - ii;
    r = (1 + sqrt(8 * jj)) / 2;
    R = N  -floor(r);
    idx_first = (floor(r + 1) .* floor(r)) / 2;
    C = idx_first-jj + R + 1;
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 2020-02-05
    • 2018-05-18
    相关资源
    最近更新 更多