inv(A)*B vs A\B - Why this weird behavior in MatLab? - matlab

Lets create two random matrices,
A = randn(2)
B = randn(2)
both inv(A)*B and A\B give the same result
inv(A)*B
A\B
ans =
0.6175 -2.1988
-0.7522 5.0343
ans =
0.6175 -2.1988
-0.7522 5.0343
unless I multiply with some factor. Why is this?
.5*A\B
.5*inv(A)*B
ans =
1.2349 -4.3977
-1.5045 10.0685
ans =
0.3087 -1.0994
-0.3761 2.5171
This is very annoying since MatLab always nudges me to use A\B instead of inv(A)*B and it took me years to figure out why my code was not working.

When A is non-singular matrix, then inv(A) * B = A \ B.
Your calculation is as follows: .5 * A\B = (0.5 * A) \ B vs .5* inv(A) * B = 0.5 * (A\B) . As such, it will give your unequal result.

Related

How can I prevent MATLAB dde23 from choosing trivial solutions?

I am trying to solve the following system of 2 delay differential equations using dde23 in MATLAB. The solver seems to work for equation 2, but for the first equation it chooses the trivial solution v(1) = 0 (as shown in attached plot). Literature on dde23 does not indicate that it has a feature to force the solution to be nonzero / positive (as in ode solvers); is there a way I can force dde23 to search for nontrivial, >0 solutions? Or some workaround for this issue? Any suggestions would be much appreciated. Thank you!
Equations:
v(1) = (Aval - f) * v(1) - b * v(1) * 2; %S eqn
v(2) = h * b * ylagS(1) * ylagV(2) - b * v(1) * v(2) - m * v(2); %V eqn
Defined constants:
Aval = 1.; %Various constants defined here
f = 10^-5;
b = 10^-7;
h = 1.5;
m = 0.0003;
This example solves a DDE on the interval [0, 5] with lags 1 and 0.2. The function ddex1de computes the delay differential equations, and ddex1hist computes the history for t <= 0.
Note
The file, ddex1.m, contains the complete code for this example. To see the code in an editor, type edit ddex1 at the command line. To run it, type ddex1 at the command line.
sol = dde23(#ddex1de,[1, 0.2],#ddex1hist,[0, 5]);
This code evaluates the solution at 100 equally spaced points in the interval [0,5], then plots the result.
tint = linspace(0,5);
yint = deval(sol,tint);
plot(tint,yint)

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 )

Computing Mahalanobis Distance Between Set of Points and Set of Reference Points

I have an n x p matrix - mX which is composed of n points in R^p.
I have another m x p matrix - mY which is composed of m reference points in R^p.
I would like to create an n x m matrix - mD which is the Mahalanobis Distance matrix.
D(i, j) means the Mahalanobis Distance between point i in mX, mX(i, :) and point j in mY, mY(j, :).
Namely, is computes the following:
mD(i, j) = (mX(i, :) - mY(j, :)) * inv(mC) * (mX(i, :) - mY(j, :)).';
Where mC is the given Mahalanobis Distance PSD Matrix.
It is easy to be done in a loop, is there a way to vectorize it?
Namely, is the a function which its inputs are mX, mY and mC and its output is mD and fully vectorized without using any MATLAB toolbox?
Thank You.
Approach #1
Assuming infinite resources, here's one vectorized solution using bsxfun and matrix-multiplication -
A = reshape(bsxfun(#minus,permute(mX,[1 3 2]),permute(mY,[3 1 2])),[],p);
out = reshape(diag(A*inv(mC)*A.'),n,m);
Approach #2
Here's a comprise solution trying to reduce the loop complexity -
A = reshape(bsxfun(#minus,permute(mX,[1 3 2]),permute(mY,[3 1 2])),[],p);
imC = inv(mC);
out = zeros(n*m,1);
for ii = 1:n*m
out(ii) = A(ii,:)*imC*A(ii,:).';
end
out = reshape(out,n,m);
Sample run -
>> n = 3; m = 4; p = 5;
mX = rand(n,p);
mY = rand(m,p);
mC = rand(p,p);
imC = inv(mC);
>> %// Original solution
for i = 1:n
for j = 1:m
mD(i, j) = (mX(i, :) - mY(j, :)) * inv(mC) * (mX(i, :) - mY(j, :)).'; %//'
end
end
>> mD
mD =
-8.4256 10.032 2.8929 7.1762
-44.748 -4.3851 -13.645 -9.6702
-4.5297 3.2928 0.11132 2.5998
>> %// Approach #1
A = reshape(bsxfun(#minus,permute(mX,[1 3 2]),permute(mY,[3 1 2])),[],p);
out = reshape(diag(A*inv(mC)*A.'),n,m); %//'
>> out
out =
-8.4256 10.032 2.8929 7.1762
-44.748 -4.3851 -13.645 -9.6702
-4.5297 3.2928 0.11132 2.5998
>> %// Approach #2
A = reshape(bsxfun(#minus,permute(mX,[1 3 2]),permute(mY,[3 1 2])),[],p);
imC = inv(mC);
out1 = zeros(n*m,1);
for ii = 1:n*m
out1(ii) = A(ii,:)*imC*A(ii,:).'; %//'
end
out1 = reshape(out1,n,m);
>> out1
out1 =
-8.4256 10.032 2.8929 7.1762
-44.748 -4.3851 -13.645 -9.6702
-4.5297 3.2928 0.11132 2.5998
Instead if you had :
mD(j, i) = (mX(i, :) - mY(j, :)) * inv(mC) * (mX(i, :) - mY(j, :)).';
The solutions would translate to the versions listed next.
Approach #1
A = reshape(bsxfun(#minus,permute(mY,[1 3 2]),permute(mX,[3 1 2])),[],p);
out = reshape(diag(A*inv(mC)*A.'),m,n);
Approach #2
A = reshape(bsxfun(#minus,permute(mY,[1 3 2]),permute(mX,[3 1 2])),[],p);
imC = inv(mC);
out1 = zeros(m*n,1);
for i = 1:n*m
out(i) = A(i,:)*imC*A(i,:).'; %//'
end
out = reshape(out,m,n);
Sample run -
>> n = 3; m = 4; p = 5;
mX = rand(n,p); mY = rand(m,p); mC = rand(p,p); imC = inv(mC);
>> %// Original solution
for i = 1:n
for j = 1:m
mD(j, i) = (mX(i, :) - mY(j, :)) * inv(mC) * (mX(i, :) - mY(j, :)).'; %//'
end
end
>> mD
mD =
0.81755 0.33205 0.82254
1.7086 1.3363 2.4209
0.36495 0.78394 -0.33097
0.17359 0.3889 -1.0624
>> %// Approach #1
A = reshape(bsxfun(#minus,permute(mY,[1 3 2]),permute(mX,[3 1 2])),[],p);
out = reshape(diag(A*inv(mC)*A.'),m,n); %//'
>> out
out =
0.81755 0.33205 0.82254
1.7086 1.3363 2.4209
0.36495 0.78394 -0.33097
0.17359 0.3889 -1.0624
>> %// Approach #2
A = reshape(bsxfun(#minus,permute(mY,[1 3 2]),permute(mX,[3 1 2])),[],p);
imC = inv(mC);
out1 = zeros(m*n,1);
for i = 1:n*m
out1(i) = A(i,:)*imC*A(i,:).'; %//'
end
out1 = reshape(out1,m,n);
>> out1
out1 =
0.81755 0.33205 0.82254
1.7086 1.3363 2.4209
0.36495 0.78394 -0.33097
0.17359 0.3889 -1.0624
Here is one solution that eliminates one loop
function d = mahalanobis(mX, mY)
n = size(mX, 2);
m = size(mY, 2);
data = [mX, mY];
mc = cov(transpose(data));
dist = zeros(n,m);
for i = 1 : n
diff = repmat(mX(:,i), 1, m) - mY;
dist(i,:) = sum((mc\diff).*diff , 1);
end
d = sqrt(dist);
end
You would invoke it as:
d = mahalanobis(transpose(X),transpose(Y))
Reduce to L2
It seems that Mahalanobis Distance can be reduced to ordinary L2 distance if you are allowed to preprocess matrix mC and you are not afraid of numerical differences.
First of all, compute Cholesky decomposition of mC:
mR = chol(mC) % C = R^t * R, where R is upper-triangular
Now we can use these factors to reformulate Mahalanobis Distance:
(Xi-Yj) * inv(C) * (Xi-Yj)^t = || (Xi-Yj) inv(R) ||^2 = ||TXi - TYj||^2
where: TXi = Xi * inv(R)
TYj = Yj * inv(R)
So the idea is to transform points Xi, Yj to TXi, TYj first, and then compute euclidean distances between them. Here is the algorithm outline:
Compute mR - Cholesky factor of covariance matrix mC (takes O(p^3) time).
Invert triangular matrix mR (takes O(p^3) time).
Multiply both mX and mY by inv(mR) on the right (takes O(p^2 (m+n)) time).
Compute squared L2 distances between pairs of points (takes O(m n p) time).
Total time is O(m n p + (m + n) p^2 + p^3) versus original O(m n p^2). It should work faster when 1 << p << n,m. In such case step 4 would takes most of the time and should be vectorized.
Vectorization
I have little experience of MATLAB, but quite a lot of SIMD vectorization on x86 CPUs. In raw computations, it would be enough to vectorize along one sufficiently large array dimension, and make trivial loops for the other dimensions.
If you expect p to be large enough, it may probably be OK to vectorize along coordinates of points, and make two nested loops for i <= n and j <= m. That's similar to what #Daniel posted.
If p is not sufficiently large, you can vectorize along one of the point sequences instead. This would be similar to solution posted by #dpmcmlxxvi: you have to subtract single row of one matrix from all the rows of the second matrix, then compute squared norms of the resulting rows. Repeat n times (
or m times).
As for me, full vectorization (which means rewriting with matrix operations instead of loops in MATLAB) does not sound like a clever performance goal. Most likely partially vectorized solutions would be optimally fast.
I came to the conclusion that vectorizing this problem is not efficient. My best idea for vectorizing this problem would require m x n x p x p working memory, at least if everything is processed at once. This means with n=m=p=152 the code would already require 4GB Ram. At these dimensions, my system can run the loop in less than a second:
mD=zeros(size(mX,1),size(mY,1));
ImC=inv(mC);
for i=1:size(mX,1)
for j=1:size(mY,1)
d=mX(i, :) - mY(j, :);
mD(i, j) = (d) * ImC * (d).';
end
end

How to vectorize the evaluation of a quadratic form (x' * A * x)?

If I have a matrix A and I want to evaluate x' * A * x for multiple values of x, how can I vectorize this?
(I could do X' * A * X and take the diagonal, but this is clearly inefficient.)
One way to think about it is that you are trying to take a bunch of dot products between the vectors in X and the vectors in AX. Matlab has a function for that:
N = 10; % number of x's
M = 100; % length of x's
X = rand(M,N);
A = rand(M, M);
% way 1
way1 = diag(X' * A * X);
% way 2
way2 = dot(X, A*X)';
% compare
[way1 way2]
How about this?
sum((A*X).*X,1)
Or, if you are dealing with complex values,
sum((A*X).*conj(X),1)
Check:
>> A = rand(4,4);
>> X = rand(4,3);
>> sum((A*X).*X,1)
ans =
5.4755 2.6205 3.4803
>> diag(X'*A*X)
ans =
5.4755
2.6205
3.4803
This could be one approach, though not sure if this would be more efficient than the direct matrix multiplication + diag based approach -
%// Perform X'*A equivalent multiplication
mult1 = bsxfun(#times,permute(X,[1 3 2]),A)
%// Perform rest of the equivalent multiplication
mult2 = bsxfun(#times,mult1,permute(X,[3 1 2]))
%// Perform the summations required to reduce to desired output's size
out = sum(reshape(mult2,[],size(X,2)),1)
You can re-arrange the multiplications a bit -
mult1 = bsxfun(#times,permute(X,[1 3 2]),permute(X,[3 1 2]))
mult2 = bsxfun(#times,mult1,A)
out = sum(reshape(mult2,[],size(X,2)),1)
Or merge the ending bsxfun(#times and sum with a bit more simplified and maybe more efficient version -
mult1 = bsxfun(#times,permute(X,[1 3 2]),permute(X,[3 1 2]))
out = reshape(permute(mult1,[3 1 2]),size(X,2),[])*A(:)
Or simplify it further to make it a one-liner that uses minimal of tools and could be the most efficient of the lot! -
out = reshape(bsxfun(#times,X.',permute(X,[2 3 1])),[],numel(A))*A(:)
In numpy, you can do np.einsum('ij,jk,ki->i',np.transpose(X),A,X).

Matlab transition matrix

I tried to find a function of matlab, I found 'tf' but I didn't know how to use it :/
So I am trying to write a code of transition matrix, from:
mat1=[1,1,1;
1,1,0;
1,0,0];
to this one:
mat2=[1,2,3;
0,1,1;
0,0,1]
I think I have to do something like:
a{1} * mat2(1,:) + a{2} * mat2(1,:) + a{3} * mat2(1,:) = mat1(1,:);
a{4} * mat2(2,:) + a{5} * mat2(2,:) + a{6} * mat2(2,:) = mat1(2,:);
a{7} * mat2(3,:) + a{8} * mat2(3,:) + a{9} * mat2(3,:) = mat1(3,:);
find the a{1}, a{2}, .... a{9} that solve these equations, and put it in the columns:
result = [a{1} a{4} a{7};
a{2} a{5} a{8};
a{3} a{6} a{9}];
Is my way good? can someone tell me please how to use the matlab function for creating a transition matrix for my matrices?
This is an example:
1(1,2,3)-1(0,1,1)-1(0,0,1) = (1,1,1)
1(1,2,3)-1(0,1,1)-2(0,0,1) = (1,1,0)
1(1,2,3)-2(0,1,1)-1(0,0,1) = (1,0,0)
then, the result should be:
result = [1 1 1
-1 -1 -2
-1 -2 -1]
now if I take the vector (3, -1, -1) in the basis of B, I got (1,0,0) in the basis of c.
The tf function computes the transfer function model. That does not seem to be in any way related to your problem.
EDITED:
Now I got it, so the result matrix R that you want is actually
R = (M1 * M2^-1)^T
hence
result = (mat1 * inv(mat2))';
where the transposition is simply due to your choice of picking the indices column-first.
However, I must underline that this solution yields
mat1 = result' * mat2;
so R^T is not the transition matrix from M1 to M2, but the transition matrix from M2 to M1.
TF() is transfer function. As in controls. For example, if the function is F(s) = (1/5s^2+2s+1) Numerator = [1] Denominator = [5 2 1] and therefore your transfer function F = tf([1], [5 2 2]). From here you can do a lot of fun engineering stuff like bode(F) and so on.
What I think you are trying to do is: http://www.mathworks.com/matlabcentral/newsreader/view_thread/132415