2015-07-27 1 views
1

В Matlab есть способ скопировать нижнюю треугольную половину матрицы в верхнюю треугольную половину?В Matlab есть способ скопировать нижнюю треугольную половину матрицы в верхнюю треугольную половину?

Для квадратной матрицы А, я хочу быть в состоянии сделать

triu(A)=tril(A)'; 

для того, чтобы установить все A(i,j) в A(j,i) для I> J.

Есть ли удобный/эффективный способ сделать это?

Примечание: ответ может быть применен к разреженным матрицам.


На тему эффективности,

Я сделал некоторые испытания в отношении относительной стоимости времени для доступа к части матрицы. Я использовал версию R2014a

Некоторые результаты: логическое индексирование болезненно медленное и его следует избегать; хуже логическое индексирование с разреженными матрицами; добавление, включающее плотные матрицы в среде с разреженной матрицей, является tortu r ous, и его следует избегать любой ценой.

До сих пор данные свидетельствуют о том, что tril(A,-1)+tril(A)', пожалуй, лучший способ. (Цикличность не пробовали. Но это, скорее всего, по крайней мере, столь же медленно, как логическую индексацию.)

% Note: In each case, the posted results are those after a few "warm up" trials. 

% providing the arrays 
>> e=ones(1000,1); 
>> temp=[e,zeros(1000,999)]; 
>> A=magic(1000); 
>> temp2=[true(1000,1),false(1000,999)]; 

% matrix addition (without sparse matrix support) 
>> tic;for i=1:1000; A=A+temp; A=A-temp; end; toc 
Elapsed time is 1.903718 seconds. 
>> tic;for i=1:1000; A=A+temp; A=A-temp; end; toc 
Elapsed time is 1.898125 seconds. 
>> tic;for i=1:1000; A=A+temp; A=A-temp; end; toc 
Elapsed time is 1.896766 seconds. 

% logical indexing to modify part of a matrix by a smaller matrix (a column vector) 
>> tic;for i=1:1000; A(temp2)=A(temp2)+e; A(temp2)=A(temp2)-e; end; toc 
Elapsed time is 4.916888 seconds. 
>> tic;for i=1:1000; A(temp2)=A(temp2)+e; A(temp2)=A(temp2)-e; end; toc 
Elapsed time is 4.926484 seconds. 
>> tic;for i=1:1000; A(temp2)=A(temp2)+e; A(temp2)=A(temp2)-e; end; toc 
Elapsed time is 4.929350 seconds. 

% logical indexing to modify part of a matrix by a scalar 
>> tic;for i=1:1000; A(temp2)=A(temp2)+1; A(temp2)=A(temp2)-1; end; toc 
Elapsed time is 4.914185 seconds. 
>> tic;for i=1:1000; A(temp2)=A(temp2)+1; A(temp2)=A(temp2)-1; end; toc 
Elapsed time is 4.909323 seconds. 
>> tic;for i=1:1000; A(temp2)=A(temp2)+1; A(temp2)=A(temp2)-1; end; toc 
Elapsed time is 4.905367 seconds. 
>> tic;for i=1:1000; A(temp2)=1; A(temp2)=-1; end; toc 
Elapsed time is 2.472018 seconds. 
>> tic;for i=1:1000; A(temp2)=1; A(temp2)=-1; end; toc 
Elapsed time is 2.463884 seconds. 
>> tic;for i=1:1000; A(temp2)=1; A(temp2)=-1; end; toc 
Elapsed time is 2.462588 seconds. 

% matrix addition with sparse matrix support (astounding?) 
>> A=sparse(A); temp3=sparse(temp2); 
>> tic;for i=1:1000; A=A+temp3; A=A-temp3; end; toc 
Elapsed time is 13.648472 seconds. 
>> tic;for i=1:1000; A=A+temp3; A=A-temp3; end; toc 
Elapsed time is 13.485242 seconds. 
>> tic;for i=1:1000; A=A+temp3; A=A-temp3; end; toc 
Elapsed time is 13.551307 seconds. 

% matrix addition with sparse matrix support between matrices with identical sparsity structure 
>> tic;for i=1:1000; temp3=temp3+temp3; temp3=temp3-temp3; end; toc 
Elapsed time is 0.013174 seconds. 
>> tic;for i=1:1000; temp3=temp3+temp3; temp3=temp3-temp3; end; toc 
Elapsed time is 0.018456 seconds. 
>> tic;for i=1:1000; temp3=temp3+temp3; temp3=temp3-temp3; end; toc 
Elapsed time is 0.009555 seconds. 

% matrix addition with sparsity support between two very sparse matrix of completely different sparsity structure 
>> temp4=sparse([zeros(1000,999),ones(1000,1)]); 
>> tic;for i=1:1000; temp4=temp4+temp3; temp4=temp4-temp3; end; toc 
Elapsed time is 0.019596 seconds. 
>> tic;for i=1:1000; temp4=temp4+temp3; temp4=temp4-temp3; end; toc 
Elapsed time is 0.014397 seconds. 
>> tic;for i=1:1000; temp4=temp4+temp3; temp4=temp4-temp3; end; toc 
Elapsed time is 0.010127 seconds. 
>> tic;for i=1:1000; temp4=temp4+temp3; temp4=temp4-temp3; end; toc 

% logical indexing with very sparse matrix 
>> tic;for i=1:1000; temp4(temp2)=1; temp4(temp2)=-1; end; toc 
Elapsed time is 6.333907 seconds. 
>> tic;for i=1:1000; temp4(temp2)=1; temp4(temp2)=-1; end; toc 
Elapsed time is 6.378107 seconds. 
>> tic;for i=1:1000; temp4(temp2)=1; temp4(temp2)=-1; end; toc 
Elapsed time is 6.486917 seconds. 

% cost for creating logical arrays 
>> tic;temp2=[true(10000,1),false(10000,9999)];toc 
Elapsed time is 0.060349 seconds. 
>> tic;temp2=[true(10000,1),false(10000,9999)];toc 
Elapsed time is 0.063874 seconds. 
>> tic;temp2=[true(10000,1),false(10000,9999)];toc 
Elapsed time is 0.060837 seconds. 

ответ

4

Вы можете попробовать tril(A,-1)+tril(A)'.

>> A = rand(3); 

A = 

    0.2277 0.9234 0.9049 
    0.4357 0.4302 0.9797 
    0.3111 0.1848 0.4389 

>> tril(A,-1)+tril(A)' 

ans = 

    0.2277 0.4357 0.3111 
    0.4357 0.4302 0.1848 
    0.3111 0.1848 0.4389 

также:

A(triu(true(3),1)) = A(tril(true(3),-1)) 

Там, наверное, еще один вариант тоже ...

+0

Хороший ответ. Для 'A = tril (A, -1) + tril (A) '' это создало бы другую копию A (которая наполовину завершена)? Создание дополнительных копий может быть проблематичным для больших матриц, даже если оно разреженное. Для 'A (triu (true (3), 1)) = A (tril (true (3), - 1))', это, по-видимому, модифицирует сам А. Но будет ли создание «tril (true (n), 1)« дорогостоящим? И если A (3,1) = 0, например, будет ли A (triu (true (3), 1)) = A (tril (true (3), - 1)) 'изменяет разреженность на A (3 , 1) '? Большое спасибо! – Argyll

+0

@Argyll Оба момента кажутся действительными. Я пытаюсь придумать лучший способ сделать это с разреженными матрицами в Matlab. – Justin

+0

@Argyll Существует ли какая-либо специальная структура матрицы? Это очень редко? Возможно, вам будет лучше с петлей. Я бы попробовал варианты и время их. – Justin

3

Это может быть один подход с bsxfun использовать logical indexing установить верхние треугольные элементы такие же, как и нижние -

%// Get size of square-sized input array 
N = size(A,1); 

%// Create lower triangular mask 
mask = bsxfun(@gt,[1:N]',[1:N]) %//' 

%// Replace transposed masked (upper triangular) elements with lower ones 
A(mask.') = A(mask) 

С точки зрения переменных crea существует дополнительный логический массив mask, который создается и с вызовом функции добавляется дополнительный bsxfun.

Пример запуска -

A = 
     0.39223  0.70605  0.046171 
     0.65548  0.031833  0.097132 
     0.17119  0.27692  0.82346 
mask = 
    0  0  0 
    1  0  0 
    1  1  0 
A = 
     0.39223  0.65548  0.17119 
     0.65548  0.031833  0.27692 
     0.17119  0.27692  0.82346 

Для чисел производительности, связанных с созданием сравнения эквивалент маски на основе tril/triu и bsxfun, Benchmarks comparing BSXFUN and TRIU можно было бы назвать также.

+0

Любые комментарии для разреженных матриц? –