1

I am looking for a matrix operation of the form: B = M*A*N where A is some general square matrix and M and N are the matrices I want to find. Such that the columns of B are the diagonals of A. The first column the main diagonal, the second the diagonal shifted by 1 from the main and so on.

e.g. In MATLAB syntax:

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

and

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

Edit: It seems a pure linear algebra solution doesn't exist. So I'll be more precise about what I was trying to do:

For some vector v of size 1 x m. Then define C = repmat(v,m,1). My matrix is A = C-C.';. Therefore, A is essentially all differences of values in v but I'm only interested in the difference up to some distance between values. Those are the diagonals of A; but m is so large that the construction of such m x m matrices causes out-of-memory issues. I'm looking for a way to extract those diagonals in a way that is as efficient as possible (in MATLAB).

Thanks!

AsaridBeck91
  • 1,276
  • 9
  • 12
  • What relationship can you assume between `M` and `N`? Is `N` = `M`^-1? That would simplify the problem – titus.andronicus Jan 04 '17 at 13:19
  • 1
    You effectively have one equation (`B=M*A*N`) and two unknowns (`M` and `N`), need more information to solve this! Or do you just want a function which sets up matrix `B` for a given `A`? – Wolfie Jan 04 '17 at 14:23
  • Yes. M and N have freedom but I don't know of a any relation between them. The transformation should just work for general A with M N some constant matrices. – AsaridBeck91 Jan 04 '17 at 15:49
  • M N some constant matrices (non dependent on A values). Setting A the identity matrix shows that MN results in a matrix with first column of ones and all other entries 0 since the identity has ones along the main diagonal and 0 else. But I don't see how this helps. – AsaridBeck91 Jan 04 '17 at 15:57
  • Is this a linear algebra homework? – Alexander Kemp Jan 04 '17 at 17:12
  • No it's a project of mine. I need to deal with very big matrices causing MATLAB out of memory but I only need the values along some diagonals. But why do you ask? Does it make a difference? – AsaridBeck91 Jan 04 '17 at 20:53
  • Yes, Homework is not well liked here..... I dont see how that may solve any memory problem, even if it works, but it has my curiousity – Alexander Kemp Jan 05 '17 at 18:15
  • I think a trivial solution (only 0 or 1 in M and N) does not exist, but you may look at http://mathoverflow.net/questions/4167/what-are-the-components-of-a-transpose-operator-from-rnn-to-rnn/4168#4168 - the question is: Can you represent your superoperator as the product of the two superoperators associated with multiplication? – Alexander Kemp Jan 05 '17 at 18:44
  • It seems that for 2x2 and 3x3 there is no solution to this problem. So I guess there isn't one for general dimension for the same reasons. I'll move on to a different approach. Thanks all. – AsaridBeck91 Jan 05 '17 at 19:47
  • Are you just trying to reorder `A` to `B`? Do you really have to compute `M` and `N`, or was a linear algebra solution just the first thing you thought to try? You could do this just through indexing (i.e. no `M` or `N` needed), as I show in my answer below (assuming that's what you're looking for). – gnovice Jan 05 '17 at 21:48

2 Answers2

1

If you're not actually looking for a linear algebra solution, then I would argue that constructing three additional matrices the same size as A using two matrix multiplications is very inefficient in both time and space complexity. I'm not sure it's even possible to find a matrix solution, given my limited knowledge of linear algebra, but even if it is it's sure to be messy.

Since you say you only need the values along some diagonals, I'd construct only those diagonals using diag:

A = [1 2 3;
     4 5 6;
     7 8 9];
m = size(A, 1);   % assume A is square
k = 1;            % let's get the k'th diagonal
kdiag = [diag(A, k); diag(A, k-m)];

kdiag =

   2
   6
   7

Diagonal 0 is the main diagonal, diagonal m-1 (for an mxm matrix) is the last. So if you wanted all of B you could easily loop:

B = zeros(size(A));
for k = 0:m-1
   B(:,k+1) = [diag(A, k); diag(A, k-m)];
end

B =

   1   2   3
   5   6   4
   9   7   8

From the comments:

For v some vector of size 1xm. Then B=repmat(v,m,1). My matrix is A=B-B.'; A is essentially all differences of values in v but I'm only interested in the difference up to some distance between values.

Let's say

m = 4;
v = [1 3 7 11];

If you construct the entire matrix,

B = repmat(v, m, 1);
A = B - B.';

A =
    0    2    6   10
   -2    0    4    8
   -6   -4    0    4
  -10   -8   -4    0

The main diagonal is zeros, so that's not very interesting. The next diagonal, which I'll call k = 1 is

[2 4 4 -10].'

You can construct this diagonal without constructing A or even B by shifting the elements of v:

k = 1;
diag1 = circshift(v, m-k, 2) - v;

diag1 =

    2    4    4  -10

The main diagonal is given by k = 0, the last diagonal by k = m-1.

beaker
  • 16,331
  • 3
  • 32
  • 49
  • Yes, that would work but my idea was to use the linear algebra solution so that I will not have to resort to such large matrices in the first place. I should have made that clear. – AsaridBeck91 Jan 05 '17 at 19:11
  • I'm not sure I understand what you're proposing. If you use `B = M*A*N` you have 4 `mxm` matrices. Using this approach you have only the original matrix and however many `mx1` diagonals you actually need. – beaker Jan 05 '17 at 19:14
  • You are correct but the specific matrix I want to run this operation over is constructed from a vector of length m. With m about 1e6. My MATLAB can't create even a zeros matrix with such m. I needed to get to the diagonals without matrices at all. But it seems this approach isn't good since I believe a general algebraic solution doesn't exists. – AsaridBeck91 Jan 05 '17 at 19:50
  • Okay, then I think we need to get a better idea of how your matrix is constructed. If there are a lot of zero values you can look into sparse matrices, but I don't know if that applies in your case. – beaker Jan 05 '17 at 19:53
  • For v some vector of size 1xm. Then B=repmat(v,m,1). My matrix is A=B-B.'; A is essentially all differences of values in v but I'm only interested in the difference up to some distance between values. Hence the diagonals. I can solve this issue with a for loop but it's quite slow... That's why I was looking for linear algebra's help. – AsaridBeck91 Jan 05 '17 at 20:00
  • In that case each diagonal of `A` is `v - circshift(v, k, 2)` for `k = 0..m-1`, I think. – beaker Jan 05 '17 at 20:17
  • Actually, with the ordering you have it's `circshift(v, m-k, 2) - v` for `k = 0:m-1`. – beaker Jan 05 '17 at 20:33
  • Yeah true. That might help. still a loop over diagonals but a shorter one. I'll try it out. Thanks! – AsaridBeck91 Jan 05 '17 at 20:56
  • I'm not understanding the problem then. If your goal is to create some `x << m` diagonals then avoiding construction of `A` altogether seems the way to go. If you want all `m` diagonals at one, then you're going to run into memory problems again. – beaker Jan 05 '17 at 21:01
  • By the way, you should really add the construction of `A` to your original question. It makes it a lot easier to come up with possible solutions. – beaker Jan 05 '17 at 21:02
  • Ok I edited the question. My original thought was that if I was able to make A look like a complete v dependent algebraic expression e.g A=D.F.v.H.J and I'm only interested in some x< – AsaridBeck91 Jan 06 '17 at 11:02
1

You can do this using the function toeplitz to create column indices for the reshuffling, then convert those to a linear index to use for reordering A, like so:

>> A = [1 2 3; 4 5 6; 7 8 9]
A =
     1     2     3
     4     5     6
     7     8     9
>> n = size(A, 1);
>> index = repmat((1:n).', 1, n)+n*(toeplitz([1 n:-1:2], 1:n)-1);
>> B = zeros(n);
>> B(index) = A
B =
     1     2     3
     5     6     4
     9     7     8

This will generalize to any size square matrix A.

gnovice
  • 125,304
  • 15
  • 256
  • 359