【问题标题】:How to replace kth diagonal in a matrix in octave?如何以八度音阶替换矩阵中的第 k 个对角线?
【发布时间】:2021-09-16 08:46:58
【问题描述】:

我正在尝试在 Octave 中替换矩阵的子对角线和超对角线。

这是我正在使用的代码:

A=[-3 -2 -1 0 1 2 3;0.1 0.2 0.2 0.5 0.6 -0.1 0]'
P=zeros(4,4)

for (k=1:7)
  j=A(k,1)
  diag(P,j)=A(k,2)
end

这是我得到的错误:diag(0,_): subscripts must be either integers 1 to (2^63)-1 or logicals

但是所有的小部分都还好。 diag(P,-3) 工作正常,但是当我要求在循环中替换时它拒绝!

我能做些什么呢?这是:diag(P,j)=e,不是替换超对角线和子对角线的正确代码吗?

【问题讨论】:

    标签: matrix octave


    【解决方案1】:

    您收到错误的原因是diag(P,j) 不是对P 对角线的引用,它是一个返回该对角线上值的函数。因此,您所做的是将值 A(k,2) 分配给函数的返回值,并且由于它从未分配给变量名,因此该值丢失并且没有任何变化。

    要修复您的循环,您需要在P 中提供索引并分配给这些索引。一种方法是使用逻辑索引告诉 MATLAB P 中的哪些值要更改。例如,

    P = zeros(4)
    M = logical(diag([1,1,1], -1))
    P(M) = 3
    

    给我们

    P =
    
       0   0   0   0
       0   0   0   0
       0   0   0   0
       0   0   0   0
    
    M =
    
      0  0  0  0
      1  0  0  0
      0  1  0  0
      0  0  1  0
    
    P =
    
       0   0   0   0
       3   0   0   0
       0   3   0   0
       0   0   3   0
    

    不幸的是,我们无法同时指定要创建的对角线结果矩阵的大小,因此我们必须在创建之前计算对角线上的元素数量.

    A=[-3 -2 -1 0 1 2 3;0.1 0.2 0.2 0.5 0.6 -0.1 0].'   
    
    n=4;   % Number of rows/columns in P... 
           % If we want a non-square matrix, we'll have to do more math
    P=zeros(n);
    
    for k=1:2*n-1   % Remove hardcoded values to make the code more general.
      j=A(k,1);
      diag_length = n-abs(j);
      M=diag(true(1,diag_length),j);   % Create logical array with true on jth diagonal
      P(M)=A(k,2);
    end
    

    结果是:

    P =
    
       0.5000   0.6000  -0.1000        0
       0.2000   0.5000   0.6000  -0.1000
       0.2000   0.2000   0.5000   0.6000
       0.1000   0.2000   0.2000   0.5000
    

    另一种方法是使用spdiagsspdiags 的用途之一是获取一个矩阵的列,并使用它们来构建输出矩阵的对角线。您传递要设置的对角线的索引、每个对角线的值矩阵以及矩阵大小。

    如果我们只为每个对角线传递一个值,spdiags 将只设置一个值,因此我们将不得不复制输入向量 n 次。 (spdiags 会很乐意丢弃值,但不会填充它们。)

    A=[-3 -2 -1 0 1 2 3;0.1 0.2 0.2 0.5 0.6 -0.1 0].'
    n = 4;
    
    diag_idx = A(:,1).';   % indices of diagonals
    diag_val = A(:,2).';   % corresponding values
    diag_val = repmat(diag_val, n, 1);   % duplicate values n times
    
    P = spdiags(diag_val, diag_idx, n, n);
    P = full(P);
    

    最后一行是因为spdiags 创建了一个稀疏矩阵。 full 将其转换为常规矩阵。 P 的最终值是您所期望的:

    P =
    
       0.5000   0.6000  -0.1000        0
       0.2000   0.5000   0.6000  -0.1000
       0.2000   0.2000   0.5000   0.6000
       0.1000   0.2000   0.2000   0.5000
    

    当然,如果您喜欢单行,您可以将所有这些命令组合在一起。

    P = full(spdiags(repmat(A(:,2).', n, 1), A(:,1).', n, n));
    

    【讨论】:

    • 感谢您的指导。这真的是另一种思维方式。如果您向我展示使用 spdiags 的更紧凑的方式,我将不胜感激
    • @Clarisha 完成。如果您有任何问题,请告诉我。
    • 非常感谢,spdiags通俗易懂!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 2014-08-03
    • 1970-01-01
    • 2014-12-25
    • 2021-06-10
    • 2022-08-15
    相关资源
    最近更新 更多