What is a quick way to compute the euclidean norm of two sets of vectors? - matlab

I know that MATLAB works better when most or everything is vectorized. I have two set of vectors X and T. For every vector x in X I want to compute:
this is because I want to compute:
which can be easily expressed as MATLAB linear algebra operations as I wrote above with a dot product. I am hoping that I can speed this up by having those vectors, instead of computing each f(x) with a for loop. Ideally I could have it all vectorized and compute:
I've been think about this for some time now, but it doesn't seem to be a a nice way were a function takes two vectors and computes the norm between each one of them, with out me having to explicitly write the for loop.
i.e. I've implemented the trivial code:
function [ f ] = f_start( x, c, t )
% Computes f^*(x) = sum_i c_i exp( - || x_i - t_i ||^2)
% Inputs:
% x = data point (D x 1)
% c = weights (K x 1)
% t = centers (D x K)
% Outputs:
% f = f^*(x) = sum_k c_k exp( - || x - t_k ||^2)
[~, K] = size(t);
f = 0;
for k=1:K
c_k = c(k);
t_k = t(:, k);
norm_squared = norm(x - t_k, 2)^2;
f = f + c_k * exp( -1 * norm_squared );
end
end
but I was hoping there was a less naive way to do this!

I think you want pdist2 (Statistics Toolbox):
X = [1 2 3;
4 5 6];
T = [1 2 3;
1 2 4;
7 8 9];
result = pdist2(X,T);
gives
result =
0 1.0000 10.3923
5.1962 4.6904 5.1962
Equivalently, if you don't have that toolbox, use bsxfun as follows:
result = squeeze(sqrt(sum(bsxfun(#minus, X, permute(T, [3 2 1])).^2, 2)));

Another method just for kicks
X = [1 2 3;
4 5 6].';
T = [1 2 3;
1 2 4;
7 8 9].';
tT = repmat(T,[1,size(X,2)]);
tX = reshape(repmat(X,[size(T,2),1]),size(tT));
res=reshape(sqrt(sum((tT-tX).^2)).',[size(T,2),size(X,2)]).'

Related

Left matrix divide with vectors

How explicitly does Matlab solve the rightmost equation in c1, specifically ((x-1)\y)?
I am well aware what happens when you use a matrix, e.g. A\b (where A is a matrix and b is a column vector), but what happens when you use backslash on two vectors with equal rows?
The problem:
x = (1:3)';
y = ones(3,1);
c1 = ((x-1)\y) % why does this =0.6?
You're doing [0;1;2]\[1;1;1]. Essentially x=0.6 is the least-squares solution to
[0;1;2]*x=[1;1;1]
The case you have from the documentation is the following:
If A is a rectangular m-by-n matrix with m ~= n, and B is a matrix with m rows, then A\B returns a least-squares solution to the system of equations A*x= B.
(Specifically, you have m=3, n=1).
A = (1:3).' - 1; % = [0;1;2]
B = ones(3,1); % = [1;1;1]
x = A\B; % = 0.6
Algebraically, it's easy to see this is the solution to the least-squares minimisation
% Calculate least squares
leastSquares = sum( ((A*x) - B).^2 )
= sum( ([0;1;2]*x - [1;1;1]).^2 )
= sum( [-1; x-1; 2x-1].^2 )
= 1 + (x-1)^2 + (2x-1)^2
= 1 + x^2 - 2*x + 1 + 4*x^2 - 4*x + 1
= 5*x^2 - 6*x + 3
% Minimum least squares -> derivative = 0
d(leastSquares)/dx = 10*x - 6 = 0
10*x = 6
x = 0.6
I have no doubt that MATLAB uses a more sophisticated algorithm to come to the same conclusion, but this lays out the mathematics in a fairly plain way.
You can see experimentally that there is no better solution by testing the following for various values of x... 0.6 gives the smallest error:
sum( ([0;1;2]*x - [1;1;1]).^2 )

Solving a difference equation with initial condition

Consider a difference equation with its initial conditions.
5y(n) + y(n-1) - 3y(n-2) = (1/5^n) u(n), n>=0
y(n-1) = 2, y(n-2) = 0
How can I determine y(n) in Matlab?
Use an approach similar to this (using filter), but specifying initial conditions as done here (using filtic).
I'm assuming your initial conditions are: y(-1)=2, y(-2)=0.
num = 1; %// numerator of transfer function (from difference equation)
den = [5 1 -3]; %// denominator of transfer function (from difference equation)
n = 0:100; %// choose as desired
x = (1/5).^n; %// n is >= 0, so u(n) is 1
y = filter(num, den, x, filtic(num, den, [2 0], [0 0]));
%// [2 0] reflects initial conditions on y, and [0 0] those on x.
Here's a plot of the result, obtained with stem(n,y).
The second line of your code does not give initial conditions, because it refers to the index variable n. Since Matlab only allows positive integer indices, I'll assume that you mean y(1) = 0 and y(2) = 2.
You can get an iteration rule out of your first equation by simple algebra:
y(n) = ( (1/5^n) u(n) - y(n-1) + 3y(n-2) ) / 5
Code to apply this rule in Matlab:
n_max = 100;
y = nan(n_max, 1);
y(1) = 0;
y(2) = 2;
for n = 3 : n_max
y(n) = ( (1/5^n) * u(n) - y(n-1) + 3 * y(n-2) ) / 5;
end
This code assumes that the array u is already defined. n_max specifies how many elements of y to compute.

Create Matrix using Matrix Indices

In matlab, how could you create a matrix M using its indices to populate the values? For example, say I want to create a 3x3 matrix M such that
M(i,j) = i+j --> [ 2 3 4; 3 4 5; 4 5 6]
I tried making vectors: x = 1:3', y = 1:3 and then
M = x(:) + y(:)
but it didn't work as expected.
Any thoughts on how this can be done?
Thanks!
UPDATE
The M I actually desire is:
M(i,j) = -2^(-i - j).
One way would be
x = 1:3;
z = ones(1,3);
N = z'*x + x'*z
M = -2 .^ -(z'*x + x'*z)
% Or simply
% M = -2 .^ -N
Output:
N =
2 3 4
3 4 5
4 5 6
M =
-0.250000 -0.125000 -0.062500
-0.125000 -0.062500 -0.031250
-0.062500 -0.031250 -0.015625
You should use bsxfun to find the sum:
M=bsxfun(#plus, (1:3).', 1:3)
and for the second formula:
M=-2.^(-bsxfun(#plus, (1:3).', 1:3))
bsxfun(#(x,y)(-2.^(-x-y)), (1:3).', 1:3)
This uses the Answer of Mohsen Nosratinia with the function you wished.

How to vectorize a sum of dot products between a normal and array of points

I need to evaluate following expression (in pseudo-math notation):
∑ipi⋅n
where p is a matrix of three-element vectors and n is a three-element vector. I can do this with for loops as follows but I can't figure out
how to vectorize this:
p = [1 1 1; 2 2 2];
n = [3 3 3];
s = 0;
for i = 1:size(p, 1)
s = s + dot(p(i, :), n)
end
Why complicate things? How about simple matrix multiplication:
s = sum(p * n(:))
where p is assumed to be an M-by-3 matrix.
I think you can do it with bsxfun:
sum(sum(bsxfun(#times,p,n)))
----------
% Is it the same for this case?
----------
n = 200; % depending on the computer it might be
m = 1000*n; % that n needs to be chosen differently
A = randn(n,m);
x = randn(n,1);
p = zeros(m,1);
q = zeros(1,m);
tic;
for i = 1:m
p(i) = sum(x.*A(:,i));
q(i) = sum(x.*A(:,i));
end
time = toc; disp(['time = ',num2str(time)]);

Obtain matrix of indices in octave / matlab

Given some multidimensional matrix A in Octave / Matlab,
What's the easiest way to get a matrix of the same size as A where all elements are replaced by their index along the k'th dimension
ie for the matrix
A =
ans(:,:,1) =
0.095287 0.191905
0.226278 0.749100
ans(:,:,2) =
0.076826 0.131639
0.862747 0.699016
I want a function f such that
f(A,1) =
ans(:,:,1) =
1 1
2 2
ans(:,:,2) =
1 1
2 2
f(A,2) =
ans(:,:,1) =
1 2
1 2
ans(:,:,2) =
1 2
1 2
and
f(A, 3) =
ans(:,:,1) =
1 1
1 1
ans(:,:,2) =
2 2
2 2
Also, given a sparse matrix B
What's the easiest way to get another sparse matrix of the same size where the nonzero elements are replaced by their index along the k'th dimension? (so same problem as above, but for only the nonzero elements)
Ideally I'm looking for a way which is well-vectorized for octave (meaning it doesn't explicitly loop over anything)
CLARIFICATION: For the sparse matrix one, I'm looking for a solution which does not involve creating a full size(B) matrix at any point
ndgrid() does what you want, although not in the format you are looking for. If you know the dims of the input A beforehand, you can use the following line to create the N-dimentional mesh grid:
% for matrix a where ndims(a) == 3
[x, y, z] = ndgrid (1:size(a,1), 1:size(a,2), 1:size(a,3));
% x is like f(a, 1)
% y is like f(a, 2)
% z is like f(a, 3)
You may be able to write a custom wrapper around ndgrid() to convert it to the function format you are looking for.
In case anyone's curious, since I didn't know about ndgrid, here's the answer I came up with:
function [y] = indices(a,k)
s = size(a);
n = s(k);
D = length(s);
x = permute(a,[k,1:(k-1),(k+1):D]);
y = reshape(x,n,[]);
y = diag(1:n) * ones(size(y));
y = reshape(y,size(x));
y = permute(y,[(2:k),1,(k+1):D]);
endfunction
function [y] = spindices(a,k)
s = size(a);
n = s(k);
D = length(s);
x = permute(a,[k,1:(k-1),(k+1):D]);
y = reshape(x,n,[]);
y = spdiag(1:n) * spones(y);
y = reshape(y,size(x));
y = permute(y,[(2:k),1,(k+1):D]);
endfunction