------------------------------------------------------------------------------ -- Haskell module: Eigensystem -- Date: initialized 2001-03-25, last modified 2001-03-25 -- Author: Jan Skibinski, Numeric Quest Inc. -- Location: http://www.numeric-quest.com/haskell/Eigensystem.hs -- See also: http://www.numeric-quest.com/haskell/QuantumVector.html -- See also: http://www.numeric-quest.com/haskell/Orthogonals.html -- -- Description: -- -- This module extends the QuantumVector module by providing functions -- to calculate eigenvalues and eigenvectors of Hermitian operators. -- Such toolkit is of primary importance due to pervasiveness of -- eigenproblems in Quantum Mechanics. -- -- This module is organized in three layers: -- -- 1. Interface to module QuantumVector, where all function signatures -- are expressed in terms of linear operators, Dirac vectors and scalars. -- -- Here the operators are defined directly via maps from input to -- output vectors. In many cases it is much easier to define the operators -- directly rather than to rely on their matrix representation. -- -- 2. Conversion layer between operators and their matrix representation. -- -- Sometimes it is more convenient to start with an underlying matrix -- representation of an operator. There are also cases where a direct -- manipulation on operators is too difficult, while it is trivial -- to obtain the corresponding results via matrices. One example is a -- computation of a Hermitian conjugate of A: -- < ei | A' | ej > = conjugate < ej | A | ej > -- (Here ' stands for a dagger) -- If however the operator A is made from a product or a sum of simpler -- operators, whose Hermitian conjugates are known to us, then the -- direct approach from the upper layer could be easier and perhaps more -- efficient in some cases. -- -- 3. Implementation layer is stored in a separate module LinearAlgorithms, -- where matrices are represented as lists of columns of scalars, and -- vectors -- as lists of scalars. -- -- This layer is completely independendent of the other two and can be -- reused separately for applications other than those caring for the -- QuantumVector module and its notation. It can also be reimplemented -- via Haskell arrays, or perhaps by some other means, such as trees -- of nodes relating square blocks of data to support paralleism. -- -- See also bottom of the page for references and license. ----------------------------------------------------------------------------- module Eigensystem (eigenvalues, adjoint) where import Data.Complex import QuantumVector import LinearAlgorithms (triangular, tridiagonal, triangular2) import Data.List (findIndex) ---------------------------------------------------------------------------- -- Category: Eigensystem for QuantumVector ---------------------------------------------------------------------------- eigenvalues :: Ord a => Bool -> Int -> [Ket a] -> (Ket a -> Ket a) -> [Scalar] eigenvalues doTri n es a -- A list of eigenvalues of operator 'a' -- obtained after 'n' triangularizations -- of a matrix corresponding to operator 'a' -- where -- 'es' is a list of base vectors -- 'doTri' declares whether or not we -- want the initial tridiagonalization -- (applies to Hermitian operators only) | doTri == True = f b1 | otherwise = f b where f c = diagonals $ operator es $ triangular n c diagonals us = [toBra e <> us e | e <- es] b = matrix es a b1 = tridiagonal b eigenpairs :: Ord a => Int -> [Ket a] -> (Ket a -> Ket a) -> ([Scalar], [Ket a]) eigenpairs n es a -- A pair of lists (eigenvalues, eigenvectors) of hermitian -- operator 'a' obtained after 'n' triangularizations of 'a' -- where -- 'es' is a list of base vectors -- Note: For a moment this applies only to Hermitian operators -- until we decide what would be the best way to compute eigenvectors -- of a triangular matrix: the method from module Orthogonal, power -- iteration, etc. = (ls, xs) where (t, q) = triangular2 n b b = matrix es a ls = [ tk!!k | (tk, k) <- zip t [0..length t - 1] ] xs = [compose qk es | qk <- q] adjoint :: Ord a => [Ket a] -> (Ket a -> Ket a) -> (Ket a -> Ket a) adjoint es a -- A Hermitian conjugate of operator a, -- (or a-dagger, or adjoint to a) -- where 'es' is a list of base vectors = operator es ms where ms = [[ conjugate (toBra ei <> vj) | vj <- v] | ei <- es] v = [a ej | ej <- es] ---------------------------------------------------------------------------- -- Category: Conversion from operators to matrices and vice versa ---------------------------------------------------------------------------- operator :: Ord a => [Ket a] -> [[Scalar]] -> Ket a -> Ket a operator bss ms x -- Definition of an operator corresponding -- to a matrix 'ms' given as a list of scalar -- columns -- where -- 'bss' (basis) is a complete list of base vectors -- 'x' is any ket vector from this space = a >< x where a u = case (findIndex (u == ) bss) of Just k -> compose (ms !! k) bss Nothing -> error "Out of bounds" matrix :: Ord a => [Ket a] -> (Ket a -> Ket a) -> [[Scalar]] matrix bss a -- List of scalar columns representing -- the operator 'a' in a given 'basis' = [[ei' <> vj | ei' <- e'] | vj <- v] where v = [a ej | ej <- bss] e' = [toBra ei | ei <- bss] ---------------------------------------------------------------------------- -- Category: Test data -- ---------------------------------------------------------------------------- matrixA :: [[Scalar]] matrixA -- Test matrix A represented as list of scalar columns. = [ [1, 2, 4, 1, 5] , [2, 3, 2, 6, 4] , [4, 2, 5, 2, 3] , [1, 6, 2, 7, 2] , [5, 4, 3, 2, 9] ] opA :: Ket Int -> Ket Int opA = operator basisA matrixA basisA :: [Ket Int] basisA = map Ket [1..5::Int] -- or: map Ket "abcde", etc. --------------------------------------------------------------------------- -- Copyright: -- -- (C) 2001 Numeric Quest, All rights reserved -- -- Email: jans@numeric-quest.com -- -- http://www.numeric-quest.com -- -- License: -- -- GNU General Public License, GPL -- ---------------------------------------------------------------------------