Как назначить значения по диагонали? - PullRequest
41 голосов
/ 19 октября 2010

Предположим, у меня есть матрица NxN A, индексный вектор V, состоящий из подмножества чисел 1: N и значения K, и я хочу сделать это:

 for i = V
     A(i,i) = K
 end

Есть ли способ сделать это одним оператором с векторизацией?

например. A ( что-то ) = K

Оператор A(V,V) = K не будет работать, он назначает недиагональные элементы, и это не то, что я хочу. e.g.:

>> A = zeros(5);
>> V = [1 3 4];
>> A(V,V) = 1

A =

 1     0     1     1     0
 0     0     0     0     0
 1     0     1     1     0
 1     0     1     1     0
 0     0     0     0     0

Ответы [ 6 ]

59 голосов
/ 19 октября 2010

Я обычно использую ГЛАЗ для этого:

A = magic(4)
A(logical(eye(size(A)))) = 99

A =
    99     2     3    13
     5    99    10     8
     9     7    99    12
     4    14    15    99

В качестве альтернативы, вы можете просто создать список линейных индексов, поскольку от одного диагонального элемента к следующему требуется nRows+1 шагов:

[nRows,nCols] = size(A);
A(1:(nRows+1):nRows*nCols) = 101
A =
   101     2     3    13
     5   101    10     8
     9     7   101    12
     4    14    15   101

Если вы хотите получить доступ только к подмножеству диагональных элементов, вам нужно создать список диагональных индексов:

subsetIdx = [1 3];
diagonalIdx = (subsetIdx-1) * (nRows + 1) + 1;
A(diagonalIdx) = 203
A =
   203     2     3    13
     5   101    10     8
     9     7   203    12
     4    14    15   101

Кроме того, вы можете создать массив логических индексов, используя diag (работает только для квадратных массивов)

diagonalIdx = false(nRows,1);
diagonalIdx(subsetIdx) = true;
A(diag(diagonalIdx)) = -1
A =
    -1     2     3    13
     5   101    10     8
     9     7    -1    12
     4    14    15   101
23 голосов
/ 19 октября 2010
>> tt = zeros(5,5)
tt =
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
>> tt(1:6:end) = 3
tt =
     3     0     0     0     0
     0     3     0     0     0
     0     0     3     0     0
     0     0     0     3     0
     0     0     0     0     3

и более общие:

>> V=[1 2 5]; N=5;
>> tt = zeros(N,N);
>> tt((N+1)*(V-1)+1) = 3
tt =
     3     0     0     0     0
     0     3     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     3

Это основано на том факте, что матрицы могут быть доступны как одномерные массивы (векторы), где 2 индекса (m, n) заменены линейным отображением m * N + n.

2 голосов
/ 25 мая 2018
>> B=[0,4,4;4,0,4;4,4,0]

B =

     0     4     4
     4     0     4
     4     4     0

>> v=[1,2,3]

v =

     1     2     3

>> B(eye(size(B))==1)=v
%insert values from v to eye positions in B

B =

     1     4     4
     4     2     4
     4     4     3
2 голосов
/ 21 февраля 2014

Я бы использовал sub2ind и передал бы диагональные индексы как параметры x и y:

A = zeros(4)
V=[2 4]

idx = sub2ind(size(A), V,V)
% idx = [6, 16]

A(idx) = 1

% A =
% 0     0     0     0
% 0     1     0     0
% 0     0     0     0
% 0     0     0     1
2 голосов
/ 26 марта 2011

Предположим, что K является значением. Команда

A=A-diag(K-diag(A))

может быть немного быстрее

>> A=randn(10000,10000);

>> tic;A(logical(eye(size(A))))=12;toc

Прошедшее время составляет 0,517575 секунд.

>> tic;A=A+diag((99-diag(A)));toc

Прошедшее время составляет 0,353408 секунд.

Но он потребляет больше памяти.

2 голосов
/ 19 октября 2010
A = zeros(7,6);
V = [1 3 5];

[n m] = size(A);
diagIdx = 1:n+1:n*m;
A( diagIdx(V) ) = 1

A =
     1     0     0     0     0     0
     0     0     0     0     0     0
     0     0     1     0     0     0
     0     0     0     0     0     0
     0     0     0     0     1     0
     0     0     0     0     0     0
     0     0     0     0     0     0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...