Constructing lower triangular matrix - matlab

I'm trying to construct a lower triangular matrix of a particular form, and as of right now, I'm using the following for loop:
M = sparse(eye(DIM));
for k = 1 : DIM - 1
ak = -z*(1-z)^(k-1);
M = M + sparse(diag(ak * ones(1, DIM - k), -k));
end
Basically, each diagonal from the main diagonal down is constant. I didn't include my definitions for DIM and z since they're not relevant to the construction of the matrix.
Does anyone know a faster way to do this? Maybe a vectorized version?

As Andras mentioned in a comment, you can use toeplitz to help you generate this without the need for a loop. You can use the two-input form (supplying the first column and row contents) to create a non-symmetric matrix like so:
M = toeplitz([1 -z.*(1-z).^(0:DIM-2)], [1 zeros(1, DIM-1)]);
This will be a full matrix, so you'll have to convert it to sparse if you need it in that form (although it may not save you anything memory-wise, since your matrix will be half-full).

Related

Computing only necessary rows of a matrix product

Suppose I have a large (but possibly sparse) matrix A, which is K-by-K in dimension. I have another K-by-1 vector, b.
Let Ax=b. If I am only interested in the first n rows, where n < K, of x, then one way of dealing with this in MATLAB is to calculate x=A\b and take the first n elements.
If the dimension K is so large that the entire computation infeasible, is there any other way to get these elements?
I guess one way would be to rearrange the columns of A and rows of x so that the elements you are interested in occur at the end of x. Then you would reduce [A,b] to row echelon form. Finally, to get the components you are after, you take the lower right hand nxn submatrix of the modified A (let's call it An) and you solve the reduced system An * xn = bn, where xn denotes the submarine of x that you are interested in, and bn denotes the last n rows of b after the row echelon reduction.
I mean, the conversion here to echelon form is still expensive, but you don't need to solve for the rest of the components in x, which can save you time.
Just an idea: You could try to use Block Matrix inversion: if you block your matrix into A = [A11, A12;A21, A22], where A11 is n x n, you can compute the blocks of its inverse B = inv(A) = [B11, B12;B21, B22] via Block Matrix Inversion. There are different versions of it, you could use the one where the Schur complement you use is only of size n x n. I'm not quite sure whether it is possible to avoid any inversion that scales with K, but you could look into it.
Your solution is then x(1:n) = [B11, B12]*b. It saves you from ever computing B21, B22. Still, I'm not sure if it is worth it. Depends on the dimensions I guess.
Here is one version, though this still needs the inverse of A22 which is (K-n)x(K-n):
K = 100;
n = 10;
A = randn(K,K);
b = randn(K,1);
% reference version: full inverse
xfull = inv(A)*b;
% blocks of A
A11 = A(1:n,1:n);A12 = A(1:n,n+1:K);A21 = A(n+1:K,1:n);A22 = A(n+1:K,n+1:K);
% blocks of inverse
A22i = inv(A22); % not sure if this can be avoided
B11 = inv(A11 - A12*A22i*A21);
B12 = -B11*A12*A22i;
% solution
x_n = [B11,B12]*b;
disp(x_n - xfull(1:n))
edit: Of course, this computes the inverse "explicitly" and as such is probably much slower than just solving the LSE. It could be worth it, if you had several vectors b you want to fit for a fixed A.

matlab - ith element of vector is the sum of the first i elements of a different vector

I'm trying to compute a vector A for which the ith element is the sum of the first i elements of a different vector B (this vector is given).
I couldn't work out how to do this and the internet wasn't much help either.
I am very new to matlab so an easy solution would be preferred :)
Use MATLAB's cumsum function.
code example:
%generates random vector b
b = rand(5,1);
%calculates accomulative sum
a = cumsum(b);
Result:
b = [0.4319 0.9616 0.5671 0.8731 0.5730]
a = [0.4319 1.3935 1.9606 2.8338 3.4068]

Matlab: Operations along the first dimension of a 3D array

I have a 3D array M(d*d,m,n). For each d*d vector of M (i.e. vectors of the first dimension), I split it into d parts and take the sum of each part to form a new vector (of size d).
For example, if u is a vector along the first dimension of M, then it will be replaced by the vector v, computed by:
v = sum(reshape(u,d,d))';
For the moment I use a loop as following, but I think there should be a much faster way to do it.
N = zeros(d,m,n)
for i=1:m
for j=1:n
N(:,i,j) = sum(reshape(M(:,i,j),d,d))'; %//'
end
end
Thank you so much for any suggestions!
Try this -
N = reshape(sum(reshape(M,d,[])),d,m,n)
I may not be understanding the question correctly but is this what you are looking for?
N=squeeze(sum(reshape(M,[d,d,size(M,2),size(M,3)])))

How do I create a simliarity matrix in MATLAB?

I am working towards comparing multiple images. I have these image data as column vectors of a matrix called "images." I want to assess the similarity of images by first computing their Eucledian distance. I then want to create a matrix over which I can execute multiple random walks. Right now, my code is as follows:
% clear
% clc
% close all
%
% load tea.mat;
images = Input.X;
M = zeros(size(images, 2), size (images, 2));
for i = 1:size(images, 2)
for j = 1:size(images, 2)
normImageTemp = sqrt((sum((images(:, i) - images(:, j))./256).^2));
%Need to accurately select the value of gamma_i
gamma_i = 1/10;
M(i, j) = exp(-gamma_i.*normImageTemp);
end
end
My matrix M however, ends up having a value of 1 along its main diagonal and zeros elsewhere. I'm expecting "large" values for the first few elements of each row and "small" values for elements with column index > 4. Could someone please explain what is wrong? Any advice is appreciated.
Since you're trying to compute a Euclidean distance, it looks like you have an error in where your parentheses are placed when you compute normImageTemp. You have this:
normImageTemp = sqrt((sum((...)./256).^2));
%# ^--- Note that this parenthesis...
But you actually want to do this:
normImageTemp = sqrt(sum(((...)./256).^2));
%# ^--- ...should be here
In other words, you need to perform the element-wise squaring, then the summation, then the square root. What you are doing now is summing elements first, then squaring and taking the square root of the summation, which essentially cancel each other out (or are actually the equivalent of just taking the absolute value).
Incidentally, you can actually use the function NORM to perform this operation for you, like so:
normImageTemp = norm((images(:, i) - images(:, j))./256);
The results you're getting seem reasonable. Recall the behavior of the exp(-x). When x is zero, exp(-x) is 1. When x is large exp(-x) is zero.
Perhaps if you make M(i,j) = normImageTemp; you'd see what you expect to see.
Consider this solution:
I = Input.X;
D = squareform( pdist(I') ); %'# euclidean distance between columns of I
M = exp(-(1/10) * D); %# similarity matrix between columns of I
PDIST and SQUAREFORM are functions from the Statistics Toolbox.
Otherwise consider this equivalent vectorized code (using only built-in functions):
%# we know that: ||u-v||^2 = ||u||^2 + ||v||^2 - 2*u.v
X = sum(I.^2,1);
D = real( sqrt(bsxfun(#plus,X,X')-2*(I'*I)) );
M = exp(-(1/10) * D);
As was explained in the other answers, D is the distance matrix, while exp(-D) is the similarity matrix (which is why you get ones on the diagonal)
there is an already implemented function pdist, if you have a matrix A, you can directly do
Sim= squareform(pdist(A))

Vector to Matrix syntax in MATLAB

Is there a way to combine 2 vectors in MATLAB such that:
mat = zeros(length(C),length(S));
for j=1:length(C)
mat(j,:)=C(j)*S;
end
Using normal MATLAB syntax similar to:
mat = C * S(1:length(S))
This gives a "Inner matrix dimensions must agree error" because it's trying to do normal matrix operations. This is not a standard Linear Algebra operation so I'm not sure how to correctly express it in MATLAB, but it seems like it should be possible without requiring a loop, which is excessively slow in MATLAB.
From your description, it sounds like a simple matrix operation. You just have to make sure you have the right dimensions for C and S. C should be a column vector (length(C)-by-1) and S should be a row vector (1-by-length(S)). Assuming they are the right dimensions, just do the following:
mat = C*S;
If you're not sure of their dimensions, this should work:
mat = (C(:))*(S(:)');
EDIT: Actually, I went a little crazy with the parentheses. Some of them are unnecessary, since there are no order-of-operation concerns. Here's a cleaner version:
mat = C(:)*S(:)';
EXPLANATION:
The matrix multiplication operator in MATLAB will produce either an inner product (resulting in a scalar value) or an outer product (resulting in a matrix) depending on the dimensions of the vectors it is applied to.
The last equation above produces an outer product because of the use of the colon operator to reshape the dimensions of the vector arguments. The syntax C(:) reshapes the contents of C into a single column vector. The syntax S(:)' reshapes the contents of S into a column vector, then transposes it into a row vector. When multiplied, this results in a matrix of size (length(C)-by-length(S)).
Note: This use of the colon operator is applicable to vectors and matrices of any dimension, allowing you to reshape their contents into a single column vector (which makes some operations easier, as shown by this other SO question).
Try executing this in MATLAB:
mat = C*S'
As In:
C = [1; 2; 3];
S = [2; 2; 9; 1];
mat = zeros(length(C),length(S));
for j=1:length(C)
mat(j,:)=C(j)*S;
end
% Equivalent code:
mat2 = C*S';
myDiff = mat - mat2
Do you mean the following?
mat = zeros(length(C),length(S));
for j=1:length(C)
mat(j,:)=C(j)*S;
end
If so, it's simply matrix multiplication:
C' * S % if C and S are row vectors
C * S' % if C and S are column vectors
If you don't know whether C and S are row vectors or column vectors, you can use a trick to turn them into column vectors, then transpose S before multiplying them:
C(:) * S(:)'
I'm not entirely clear on what you're doing - it looks like your resulting matrix will consist of length(C) rows, where the ith row is the vector S scaled by the ith entry of C (since subscripting a vector gives a scalar). In this case, you can do something like
mat = repmat(C,[1 length(S)]) .* repmat(S, [length(C) 1])
where you tile C across columns, and S down rows.
Try this:
C = 1:3
S = 1:5
mat1 = C'*S
mat2 = bsxfun(#times, C',S)
(esp. good when the function you need isn't simpler MATLAB notation)
--Loren
Try using meshgrid:
[Cm, Sm] = meshgrid(C, S);
mat = Cm .* Sm;
edit: nevermind, matrix multiplication will do too. You just need one column vector C and one row vector S. Then do C * S.