I would like to implement the Power Method for determining the dominant eigenvalue and eigenvector of a matrix in MATLAB.
Here's what I wrote so far:
%function to implement power method to compute dominant
%eigenvalue/eigenevctor
function [m,y_final]=power_method(A,x);
m=0;
n=length(x);
y_final=zeros(n,1);
y_final=x;
tol=1e-3;
while(1)
mold=m;
y_final=A*y_final;
m=max(y_final);
y_final=y_final/m;
if (m-mold)<tol
break;
end
end
end
With the above code, here is a numerical example:
A=[1 1 -2;-1 2 1; 0 1 -1]
A =
1 1 -2
-1 2 1
0 1 -1
>> x=[1 1 1];
>> x=x';
>> [m,y_final]=power_method(A,x);
>> A*x
ans =
0
2
0
When comparing with the eigenvalues and eigenvectors of the above matrix in MATLAB, I did:
[V,D]=eig(A)
V =
0.3015 -0.8018 0.7071
0.9045 -0.5345 0.0000
0.3015 -0.2673 0.7071
D =
2.0000 0 0
0 1.0000 0
0 0 -1.0000
The eigenvalue coincides, but the eigenvector should be approaching [1/3 1 1/3]. Here, I get:
y_final
y_final =
0.5000
1.0000
0.5000
Is this acceptable to see this inaccuracy, or am I making some mistake?
You have the correct implementation, but you're not checking both the eigenvector and eigenvalue for convergence. You're only checking the eigenvalue for convergence. The power method estimates both the prominent eigenvector and eigenvalue, so it's probably a good idea to check to see if both converged. When I did that, I managed to get [1/3 1 1/3]. Here is how I modified your code to facilitate this:
function [m,y_final]=power_method(A,x)
m=0;
n=length(x);
y_final=x;
tol=1e-10; %// Change - make tolerance more small to ensure convergence
while(1)
mold = m;
y_old=y_final; %// Change - Save old eigenvector
y_final=A*y_final;
m=max(y_final);
y_final=y_final/m;
if abs(m-mold) < tol && norm(y_final-y_old,2) < tol %// Change - Check for both
break;
end
end
end
When I run the above code with your example input, I get:
>> [m,y_final]=power_method(A,x)
m =
2
y_final =
0.3333
1.0000
0.3333
On a side note with regards to eig, MATLAB most likely scaled that eigenvector using another norm. Remember that eigenvectors are not unique and are accurate up to scale. If you want to be sure, simply take the first column of V, which coincides with the dominant eigenvector, and divide by the largest value so that we can get one component to be normalized with the value of 1, just like the Power Method:
>> [V,D] = eig(A);
>> V(:,1) / max(abs(V(:,1)))
ans =
0.3333
1.0000
0.3333
This agrees with what you have observed.
Related
In my earlier question asked here : Matlab: How to compute the inverse of a matrix
I wanted to know how to perform inverse operation
A = [1/2, (1j/2), 0;
1/2, (-1j/2), 0;
0,0,1]
T = A.*1
Tinv = inv(T)
The output is Tinv =
1.0000 1.0000 0
0 - 1.0000i 0 + 1.0000i 0
0 0 1.0000
which is the same as in the second picture. The first picture is the matrix A
However for a larger matrix say 5 by 5, if I don't use the identity, I to perform element wise multiplication, I am getting infinity value. Here is an example
A = [1/2, (1j/2), 1/2, (1j/2), 0;
1/2, (-1j/2), 1/2, (-1j/2), 0;
1/2, (1j/2), 1/2, (1j/2), 0;
1/2, (-1j/2), 1/2, (-1j/2), 0;
0, 0 , 0 , 0, 1.00
];
T = A.*1
Tinv = inv(T)
Tinv =
Inf Inf Inf Inf Inf
Inf Inf Inf Inf Inf
Inf Inf Inf Inf Inf
Inf Inf Inf Inf Inf
Inf Inf Inf Inf Inf
So, I tried to multiply T = A.*I where I = eye(5) then took the inverse Eventhough, I don't get infinity value, I am getting element 2 which is not there in the picture for 3 by 3 matrix case. Here is the result
Tinv =
2.0000 0 0 0 0
0 0 + 2.0000i 0 0 0
0 0 2.0000 0 0
0 0 0 0 + 2.0000i 0
0 0 0 0 1.0000
If for 3 by 3 matrix case, I use I = eye(3), then again I get element 2.
Tinv =
2.0000 0 0
0 0 + 2.0000i 0
0 0 1.0000
What is the proper method?
Question : For general case, for any sized matrix m by m, should I multiply using I = eye(m) ? Using I prevents infinity values, but results in new numbers 2. I am really confused. Please help
UPDATE: Here is the full image where Theta is a vector of 3 unknowns which are Theta1, Theta1* and Theta2 are 3 scalar valued parameters. Theta1 is a complex valued number, so we are representing it into two parts, Theta1 and Theta1* and Theta2 is a real valued number. g is a complex valued function. The expression of the derivative of a complex valued function with respect to Theta evaluates to T^H. Since, there are 3 unknowns, the matrix T should be of size 3 by 3.
your problem is slightly different than you think. The symbols (I, 0) in the matrices in the images are not necessarily scalars (only for n = 1), but they are actually square matrices.
I is an identity matrix and 0 is a matrix of zeros. if you treat these matrix like that you will get the expected answers:
n = 2; % size of the sub-matrices
I = eye(n); % identity matrix
Z = zeros(n); % matrix of zeros
% your T matrix
T = [1/2*I, (1j/2)*I, Z;
1/2*I, (-1j/2)*I, Z;
Z,Z,I];
% inverse of T
Tinv1 = inv(T);
% expected result
Tinv2 = [I,I,Z;
-1j*I,1j*I,Z;
Z,Z,I];
% max difference between computed and expected
maxDist = max(abs(Tinv1(:) - Tinv2(:)))
First you should know, whether you should do
T = A.*eye(...)
or
I = A.*1 %// which actually does nothing
These are completely different things. Be sure what you need, then think about the code.
The reason why you get all inf is because the determinant det of your matrix is zero.
det(T) == 0
So from the mathematical point of view your result is correct, as building the inverse requires every element of T to be divided by det(T). Your matrix cannot be inversed. If it should be possible, the error is in your input matrix, or again in your understanding of the actual underlying problem to solve.
Edit
After your question update, it feels like you're actually looking for ctranpose instead of inv.
I use matlab to calculate the distance transform of a binary image, and I found that bwdist() can calculate distances of all the points of the image, but I just want to know the distance of a special point.
for example,I have a binary image like this
image =
1 0 0
0 0 1
0 0 0
The bwdist() compute the distance transform of all points
>> bwdist(a)
ans =
0 1.0000 1.0000
1.0000 1.0000 0
2.0000 1.4142 1.0000
But I just want to compute distance of the point image(3,2), so the function give me 1.4142
any function can do?
You can use find to find row and column indices for all 1's, then use pdist2 from Statistics and Machine Learning Toolbox to calculate distances for all 1's from the search point (3,2) and finally choose the minimum of those distances to get the final output. Here's the implementation shown as a sample run -
>> image
image =
1 0 0
0 0 1
0 0 0
>> point
point =
3 2
>> [R,C] = find(image);
>> min(pdist2([R C],point))
ans =
1.4142
If you don't have access to pdist2, you can use bsxfun to replace it like so -
min(sqrt(sum(bsxfun(#minus,[R C],point).^2,2)))
I've been trying to wrap my head around this for awhile and was hoping to get some insight.
Suppose you have matrix A, then you switched rows until you ended up with matrix B;
A = [1 3 1;
3 2 1;
2 3 1;];
B = [3 2 1;
1 3 1;
2 3 1;];
invA =
0.0000 -1.0000 1.0000
-1.0000 -1.0000 2.0000
3.0000 5.0000 -7.0000
invB =
-1.0000 0.0000 1.0000
-1.0000 -1.0000 2.0000
5.0000 3.0000 -7.0000
How would I document these row switches?. I'm ultimately trying to alter the inverse of B to match with the inverse of A. My conclusion was that given 2 rows switched (aka between rows 1 and 2), the end result of the inverse would be identical except for switching the columns of (1 and 2) of the inverse B.
This is quite a basic algebra question.
You can write your matrix B as a product of a permutation matrix P and A:
B = PA;
(in your example: P = [0 1 0;1 0 0;0 0 1];).
Now you can invert B:
inv( B ) = inv( PA )
The inverse of a product is
= inv(A) * inv(P)
Since matrix P is a permutation matrix: inv(P) = P.'. Thus
= inv(A) * P.'
That is, inv(B) = inv(A) * P.' which means that you apply the permutation P to the columns of inv(A).
Note that a permutation P can represent more than a single switch between rows, moreover, permutations can be multiplies to account for repeated switching of rows.
An important comment: I use inv in this answer to denote the inverse of a matrix. However, when running Matlab and numerically inverting matrices it is un-recommended to use inv function explicitly.
Given a matrix A that represents polynomials in each column. How can the roots of each polynomial be calculated efficiently without loops?
Here's a comparison between 3 methods:
A simple loop through all the rows, using roots on each row.
A completely loopless approach, based on YBE's idea of using a block-diagonal matrix,
using sparse as an intermediate
A simple loop through all the rows, but this time using "inlined" code from roots.
The code:
%// The polynomials
m = 15;
n = 8;
N = 1e3;
X = rand(m,n);
%// Simplest approach
tic
for mm = 1:N
R = zeros(n-1,m);
for ii = 1:m
R(:,ii) = roots(X(ii,:));
end
end
toc
%// Completely loopless approach
tic
for mm = 1:N
%// Indices for the scaled coefficients
ii = repmat(1:n-1:m*(n-1), n-1,1);
jj = 1:m*(n-1);
%// Indices for the ones
kk = bsxfun(#plus, repmat(2:n-1, m,1), (n-1)*(0:m-1).'); %'
ll = kk-1;
%// The block diagonal matrix
coefs = -bsxfun(#rdivide, X(:,2:end), X(:,1)).'; %'
one = ones(n-2,m);
C = full(sparse([ii(:); kk(:)], [jj(:); ll(:)],...
[coefs(:); one(:)]));
%// The roots
R = reshape(eig(C), n-1,m);
end
toc
%// Simple loop, roots() "inlined"
tic
R = zeros(n-1,m);
for mm = 1:N
for ii = 1:m
A = zeros(n-1);
A(1,:) = -X(ii,2:end)/X(ii,1);
A(2:n:end) = 1;
R(:,ii) = eig(A);
end
end
toc
The results:
%// m=15, n=8, N=1e3:
Elapsed time is 0.780930 seconds. %// loop using roots()
Elapsed time is 1.959419 seconds. %// Loopless
Elapsed time is 0.326140 seconds. %// loop over inlined roots()
%// m=150, n=18, N=1e2:
Elapsed time is 1.785438 seconds. %// loop using roots()
Elapsed time is 110.1645 seconds. %// Loopless
Elapsed time is 1.326355 seconds. %// loop over inlined roots()
Of course, your mileage may vary, but the general message should be clear: The old advice of avoiding loops in MATLAB is just that: OLD. It just no longer applies to MATLAB versions R2009 and up.
Vectorization can still be a good thing though, but certainly not always. As in this case: profiling will tell you that most time is spent on computing the eigenvalues for the block-diagonal matrix. The algorithm underlying eig scales as N³ (yes, that is a three), plus it cannot take advantage of sparse matrices in any way (like this block-diagonal one), making the approach a poor choice in this particular context.
Loops are your friend here ^_^
Now, this is of course based on eig() of the companion matrix, which is a nice and simple method to compute all roots in one go. There are of course many more methods to compute roots of polynomials, each with their own advantages/disadvantages. Some are a lot faster, but aren't so good when a few of the roots are complex. Others are a lot faster, but need a fairly good initial estimate for every root, etc. Most other rootfinding methods are usually a lot more complicated, which is why I left these out here.
Here is a nice overview, and here is a more in-depth overview, along with some MATLAB code examples.
If you're smart, you should only dive into this material if you need to do this computation millions of times on a daily basis for at least the next few weeks, otherwise, it's just not worth the investment.
If you're smarter, you'll recognize that this will undoubtedly come back to you at some point, so it's worthwhile to do anyway.
And if you're an academic, you master all the root-finding methods so you'll have a giant toolbox, so you can pick the best tool for the job whenever a new job comes along. Or even dream up your own method :)
You can use arrayfun in combination with roots, which will give you the results in terms of cell arrays.
n = size(A,2);
t = arrayfun(#(x)roots(A(:,x)), 1:n, 'UniformOutput', 0);
You can then use cell2mat to convert it to a matrix. Either: r = cell2mat(t), or
r = cell2mat(arrayfun(#(x)roots(A(:,x)), 1:n, 'UniformOutput', 0));
Practically what roots does is to find the eigenvalues of the companion matrix.
roots(p) = eig(compan(p))
So here is my example that constructs a block-diagonal matrix out of the companion matrices of each polynomial, than finds the eigenvalues of the block-diagonal matrix.
>> p1=[2 3 5 7];
>> roots(p1)
ans =
-0.0272 + 1.5558i
-0.0272 - 1.5558i
-1.4455
>> eig(compan(p1))
ans =
-0.0272 + 1.5558i
-0.0272 - 1.5558i
-1.4455
>> p2=[1 2 9 5];
>> roots(p2)
ans =
-0.6932 + 2.7693i
-0.6932 - 2.7693i
-0.6135
>> p3=[5 1 4 7];
>> roots(p3)
ans =
0.3690 + 1.1646i
0.3690 - 1.1646i
-0.9381
>> A=blkdiag(compan(p1),compan(p2),compan(p3))
A =
-1.5000 -2.5000 -3.5000 0 0 0 0 0 0
1.0000 0 0 0 0 0 0 0 0
0 1.0000 0 0 0 0 0 0 0
0 0 0 -2.0000 -9.0000 -5.0000 0 0 0
0 0 0 1.0000 0 0 0 0 0
0 0 0 0 1.0000 0 0 0 0
0 0 0 0 0 0 -0.2000 -0.8000 -1.4000
0 0 0 0 0 0 1.0000 0 0
0 0 0 0 0 0 0 1.0000 0
>> eig(A)
ans =
-0.0272 + 1.5558i
-0.0272 - 1.5558i
-1.4455
-0.6932 + 2.7693i
-0.6932 - 2.7693i
-0.6135
0.3690 + 1.1646i
0.3690 - 1.1646i
-0.9381
I have a symmetric matrix with the elements A=[8.8191,0,1.0261; 0,3,0; 1.0261,0,3.1809];
I used the eig(A) function in MATLAB , the eigenvalues and eigenvectors are given :
eigvect =
0.1736 0 0.9848
0 -1.0000 0
-0.9848 0 0.1736
eigval =
3.0000 0 0
0 3.0000 0
0 0 9.0000
Eigenvalues are correct but the eigenvectors are not which I expect, because I think 2 of them should be equal. Does MATLAB calculate correctly the eigenvectors?
The definition of an eigenvalue can be found anywhere on the web
A*v = lam*v
v being the eigenvector with lam, its corresponding eigenvalue.
So test your results:
i =1;
A*eigvect (:,i)-eigval(i,i)*eigvect(:,i) %which should be approx [0;0;0]
It is not necessary that each of the repeating eigenvalue should have its (independent) associated eigenvector. This means, an nxn matrix with an eigenvalue repeating more than once has less or equal to n linearly independent eigenvectors.
Example 1: Matrix
2 0;
0 2
has eigenvalue 2 (repeating twice), but it has two linearly independent eigenvectors associated with eigenvalue 2
Example 2:Matrix
A= 1 1 1 -2;
0 1 0 -1;
0 0 1 1;
0 0 0 1
has eigenvalue 1 (repeating four times), but it has only two independent eigenvectors associated with eigenvalue 1.