I have a problem where I need to solve linear equations. The matrix is the same, but the rhs changes (during an iterative procedure). The only way I could see to do this without repeating the matrix factorization is like:
[L,U] = lu(A);
x = U\(L\b);
This seems clunky. Is there a better way? Can I use LU factors that are stored in a single array? TIA
Given a system
LU*x = b
where L is a lower triangular matrix and U is an upper triangular matrix.
From your question I understand that the vector b is changing constantly and you would like to keep the LU factorization constant for all possible vectors b.
In other words, if you have n different b's you would like n different solutions with the same LU decomposition of A.
I would use forward substitution where you solve a system
L*m = b
and then backwards substitution with
U*x = m
More here.
This way you keep the factorization constant for every vector b.
And concerning the other question, yes, it is possible to store the L and U matrices in a single matrix. Just recognize that the diagonal of the L matrix is not relevant because it is always 1.
Related
In Matlab, I'm trying to solve for the energies and eigenstates of a Hamiltonian matrix which has a highly degenerate set of eigenvectors. The matrix is a 55x55 hermitian matrix, and when I call either eig or schur to do the diagonalization I find that some (but not all) of the eigenvectors are the "wrong" linear combinations within each degenerate subspace. What I mean by "wrong" is that there are additional constraints in the problem. In this case, there is a good quantum number, M, which I want to preserve by not allowing states with different M values to be mixed--- but that mixing is exactly what I see when I run the code. Is there a way to tell Matlab to diagonalize the matrix while simultaneously maintaining the eigenvectors of another operator?
you can use diag to diagonalize a matrix and [eig_vect,eig_val] = eig(A) to give you eigenvectors.
I don't know matlab well enough to know whether there is a routine for this this, but here's how to do it algorithmically:
First diagonalise H, as you do now. Then for each degenerate eigen-space V, diagonalise the restriction of C to V, and use this diagonalisation to compute simulaneous diagonalisations of C and H
In more detail:
I assume you have an operator C that commutes with your Hamiltonian H. If V is the eigen-space of H for a particular (degenerate) eigen value, and you have a basis x[1] .. x[n] of V , then for each i, Cx[i] must be in V, and so we can expand Cx[i] in terms of the x[], and get a matrix representation C^ of the restriction of C to V, that is we compute
C^[k,j] = <x[k]|C*x[j]> k,j =1 .. n
Diagonalise the matrix C^, getting
C^ = U*D*U*
Then for each row (r1,..rn) of U* we can form
chi = Sum{ j | r[j]*x[j]}
A little algebra shows that this is an eigenvector of C, and also of H
Let assume an equation A x = b, where A is a real n x n matrix, b is a real valued vector of length n and x is the solution vector of this linear system.
We can find the solution of x by finding the inverse of A.
B= inv(A)
And therefore
x =A^{-1}b.
x= B*b
Can I apply the same solver if A and b are complex?
EDIT: I'm looking for explanation why it should work. Thanks :)
You can do that. Better in Matlab would be x = A\b. That will usually get the answer faster and more accurately.
In short yes, it works for any matrices irrespective of the field. (Well, at least real or complex field works.)
I think your question is whether B exists or not. It does as long as the determinant of B is non-zero. Vice versa.
I have a question about solving linear equation Ax=b, in which x is unknown, A is square matrix NxN and non-singular matrix.
The vector x can be solved by
x=inv(A)*b
or
x=A\b
In Matlab, the ‘\’ command invokes an algorithm which depends upon the structure of the matrix A and includes checks (small overhead) on properties of A. Hence, It highly depends on A structure. However, A structure is unknown (i.e random matrix). I want to measure complexity of above equation. Hence, to fairly comparison, I need to fixed the method which I used. In this case, I choose Gaussian Elimination (GE) with complexity O(N^3) My question is how can I choose/fix the method (i.e. GE) to solve above equation?
One way would be to compute the LU factorisation (assuming A is not symmetric)
[L,U] = lu(A)
where L is a permutation of a lower-triangular matrix with unit diagonal and U is upper triangular. This is equivalent to the Gaussian elimination.
Then, when you solve Ax = b, you actually perform first Ly = b and then Ux = y.
The important thing is that solving these linear system is essentially O(n^2), while computing the factorisation is O(n^3). So if n is big, you can just measure the time taken to compute the LU factorisation.
For random matrices, you can see the complexity of the LU factorization like that
nn = round(logspace(2, 4, 20)) ;
time = zeros(size(nn)) ;
for i = 1:numel(nn)
A = rand(nn(i),nn(i)) ;
tic() ; [L,U] = lu(A) ;
time(i) = toc() ;
end
loglog(nn,time) ;
(change the "4" to something bigger or smaller, depending on you pc).
On my laptop, I have this result
where the slop of 3 (hence, the O(n^3) complexity) is fairly clear.
I want to solve, in MatLab, a linear system (corresponding to a PDE system of two equations written in finite difference scheme). The action of the system matrix (corresponding to one of the diffusive terms of the PDE system) reads, symbolically (u is one of the unknown fields, n is the time step, j is the grid point):
and fully:
The above matrix has to be intended as A, where A*U^n+1 = B is the system. U contains the 'u' and the 'v' (second unknown field of the PDE system) alternatively: U = [u_1,v_1,u_2,v_2,...,u_J,v_J].
So far I have been filling this matrix using spdiags and diag in the following expensive way:
E=zeros(2*J,1);
E(1:2:2*J) = 1;
E(2:2:2*J) = 0;
Dvec=zeros(2*J,1);
for i=3:2:2*J-3
Dvec(i)=D_11((i+1)/2);
end
for i=4:2:2*J-2
Dvec(i)=D_21(i/2);
end
A = diag(Dvec)*spdiags([-E,-E,2*E,2*E,-E,-E],[-3,-2,-1,0,1,2],2*J,2*J)/(dx^2);`
and for the solution
[L,U]=lu(A);
y = L\B;
U(:) =U\y;
where B is the right hand side vector.
This is obviously unreasonably expensive because it needs to build a JxJ matrix, do a JxJ matrix multiplication, etc.
Then comes my question: is there a way to solve the system without passing MatLab a matrix, e.g., by passing the vector Dvec or alternatively directly D_11 and D_22?
This would spare me a lot of memory and processing time!
Matlab doesn't store sparse matrices as JxJ arrays but as lists of size O(J). See
http://au.mathworks.com/help/matlab/math/constructing-sparse-matrices.html
Since you are using the spdiags function to construct A, Matlab should already recognize A as sparse and you should indeed see such a list if you display A in console view.
For a tridiagonal matrix like yours, the L and U matrices should already be sparse.
So you just need to ensure that the \ operator uses the appropriate sparse algorithm according to the rules in http://au.mathworks.com/help/matlab/ref/mldivide.html. It's not clear whether the vector B will already be considered sparse, but you could recast it as a diagonal matrix which should certainly be considered sparse.
I have to solve in MATLAB a linear system of equations A*x=B where A is symmetric and its elements depend on the difference of the indices: Aij=f(i-j).
I use iterative solvers because the size of A is say 40000x40000. The iterative solvers require to determine the product A*x where x is the test solution. The evaluation of this product turns out to be a convolution and therefore can be done dy means of fast fourier transforms (cputime ~ Nlog(N) instead of N^2). I have the following questions to this problem:
is this convolution circular? Because if it is circular I think that I have to use a specific indexing for the new matrices to take the fft. Is that right?
I find difficult to program the routine for the fft because I cannot understand the indexing I should use. Is there any ready routine which I can use to evaluate by fft directly the product A*x and not the convolution? Actually, the matrix A is constructed of 3x3 blocks and is symmetric. A ready routine for the product A*x would be the best solution for me.
In case that there is no ready routine, could you give me an idea by example how I could construct this routine to evaluate a matrix-vector product by fft?
Thank you in advance,
Panos
Very good and interesting question! :)
For certain special matrix structures, the Ax = b problem can be solved very quickly.
Circulant matrices.
Matrices corresponding to cyclic convolution Ax = h*x (* - is convolution symbol) are diagonalized in
the Fourier domain, and can be solved by:
x = ifft(fft(b)./fft(h));
Triangular and banded.
Triangular matrices and diagonally-dominant banded matrices are solved
efficiently by sparse LU factorization:
[L,U] = lu(sparse(A)); x = U\(L\b);
Poisson problem.
If A is a finite difference approximation of the Laplacian, the problem is efficiently solved by multigrid methods (e.g., web search for "matlab multigrid").
Interesting question!
The convolution is not circular in your case, unless you impose additional conditions. For example, A(1,3) should equal A(2,1), etc.
You could do it with conv (retaining only the non-zero-padded part with option valid), which probably is also N*log(N). For example, let
A = [a b c d
e a b c
f e a b
g f e a];
Then A*x is the same as
conv(fliplr([g f e a b c d]),x,'valid').'
Or more generally, A*x is the same as
conv(fliplr([A(end,1:end-1) A(1,:)]),x,'valid').'
I'd like to add some comments on Pio_Koon's answer.
First of all, I wouldn't advise to follow the suggestion for triangular and banded matrices. The time taken by a call to Matlab's lu() procedure on a large sparse matrix massively overshadows any benefits gained by solving the linear system as x=U\(L\b).
Second, in the Poisson problem you end up with a circulant matrix, therefore you can solve it using the FFT as described. In this specific case, your convolution mask h is a Laplacian, i.e., h=[0 -0.25 0; -0.25 1 -0.25; 0 -0.25 0].