X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2FLinear%2FMatrix.hs;h=ea6bc5772422c620daa3057c0177a946442fc690;hb=ae914d13235a4582077a5cb2b1edd630d9c6ad62;hp=66b22f9f9d964e843e596678c0f7ebe34e8e9a22;hpb=af25e6f32f6787a747be63093adc10915ad60068;p=numerical-analysis.git diff --git a/src/Linear/Matrix.hs b/src/Linear/Matrix.hs index 66b22f9..ea6bc57 100644 --- a/src/Linear/Matrix.hs +++ b/src/Linear/Matrix.hs @@ -35,7 +35,6 @@ import Data.Vector.Fixed ( ) import qualified Data.Vector.Fixed as V ( and, - foldl, fromList, head, length, @@ -45,22 +44,23 @@ import qualified Data.Vector.Fixed as V ( toList, zipWith ) -import Data.Vector.Fixed.Boxed (Vec) -import Data.Vector.Fixed.Cont (Arity, arity) -import Linear.Vector -import Normed - -import NumericPrelude hiding ((*), abs) -import qualified NumericPrelude as NP ((*)) -import qualified Algebra.Algebraic as Algebraic -import Algebra.Algebraic (root) -import qualified Algebra.Additive as Additive -import qualified Algebra.Ring as Ring -import qualified Algebra.Module as Module -import qualified Algebra.RealRing as RealRing -import qualified Algebra.ToRational as ToRational -import qualified Algebra.Transcendental as Transcendental -import qualified Prelude as P +import Data.Vector.Fixed.Cont ( Arity, arity ) +import Linear.Vector ( Vec, delete, element_sum ) +import Normed ( Normed(..) ) + +import NumericPrelude hiding ( (*), abs ) +import qualified NumericPrelude as NP ( (*) ) +import qualified Algebra.Absolute as Absolute ( C ) +import Algebra.Absolute ( abs ) +import qualified Algebra.Additive as Additive ( C ) +import qualified Algebra.Algebraic as Algebraic ( C ) +import Algebra.Algebraic ( root ) +import qualified Algebra.Ring as Ring ( C ) +import qualified Algebra.Module as Module ( C ) +import qualified Algebra.RealRing as RealRing ( C ) +import qualified Algebra.ToRational as ToRational ( C ) +import qualified Algebra.Transcendental as Transcendental ( C ) +import qualified Prelude as P ( map ) data Mat m n a = (Arity m, Arity n) => Mat (Vec m (Vec n a)) type Mat1 a = Mat N1 N1 a @@ -252,21 +252,26 @@ cholesky m = construct r -- | Returns True if the given matrix is upper-triangular, and False --- otherwise. +-- otherwise. The parameter @epsilon@ lets the caller choose a +-- tolerance. -- -- Examples: -- --- >>> let m = fromList [[1,0],[1,1]] :: Mat2 Int +-- >>> let m = fromList [[1,1],[1e-12,1]] :: Mat2 Double -- >>> is_upper_triangular m -- False --- --- >>> let m = fromList [[1,2],[0,3]] :: Mat2 Int --- >>> is_upper_triangular m +-- >>> is_upper_triangular' 1e-10 m -- True -- -is_upper_triangular :: (Eq a, Ring.C a, Arity m, Arity n) - => Mat m n a -> Bool -is_upper_triangular m = +-- TODO: +-- +-- 1. Don't cheat with lists. +-- +is_upper_triangular' :: (Ord a, Ring.C a, Absolute.C a, Arity m, Arity n) + => a -- ^ The tolerance @epsilon@. + -> Mat m n a + -> Bool +is_upper_triangular' epsilon m = and $ concat results where results = [[ test i j | i <- [0..(nrows m)-1]] | j <- [0..(ncols m)-1] ] @@ -274,11 +279,36 @@ is_upper_triangular m = test :: Int -> Int -> Bool test i j | i <= j = True - | otherwise = m !!! (i,j) == 0 + -- use "less than or equal to" so zero is a valid epsilon + | otherwise = abs (m !!! (i,j)) <= epsilon + + +-- | Returns True if the given matrix is upper-triangular, and False +-- otherwise. A specialized version of 'is_upper_triangular\'' with +-- @epsilon = 0@. +-- +-- Examples: +-- +-- >>> let m = fromList [[1,0],[1,1]] :: Mat2 Int +-- >>> is_upper_triangular m +-- False +-- +-- >>> let m = fromList [[1,2],[0,3]] :: Mat2 Int +-- >>> is_upper_triangular m +-- True +-- +-- TODO: +-- +-- 1. The Ord constraint is too strong here, Eq would suffice. +-- +is_upper_triangular :: (Ord a, Ring.C a, Absolute.C a, Arity m, Arity n) + => Mat m n a -> Bool +is_upper_triangular = is_upper_triangular' 0 -- | Returns True if the given matrix is lower-triangular, and False --- otherwise. +-- otherwise. This is a specialized version of 'is_lower_triangular\'' +-- with @epsilon = 0@. -- -- Examples: -- @@ -290,8 +320,9 @@ is_upper_triangular m = -- >>> is_lower_triangular m -- False -- -is_lower_triangular :: (Eq a, +is_lower_triangular :: (Ord a, Ring.C a, + Absolute.C a, Arity m, Arity n) => Mat m n a @@ -299,6 +330,29 @@ is_lower_triangular :: (Eq a, is_lower_triangular = is_upper_triangular . transpose +-- | Returns True if the given matrix is lower-triangular, and False +-- otherwise. The parameter @epsilon@ lets the caller choose a +-- tolerance. +-- +-- Examples: +-- +-- >>> let m = fromList [[1,1e-12],[1,1]] :: Mat2 Double +-- >>> is_lower_triangular m +-- False +-- >>> is_lower_triangular' 1e-12 m +-- True +-- +is_lower_triangular' :: (Ord a, + Ring.C a, + Absolute.C a, + Arity m, + Arity n) + => a -- ^ The tolerance @epsilon@. + -> Mat m n a + -> Bool +is_lower_triangular' epsilon = (is_upper_triangular' epsilon) . transpose + + -- | Returns True if the given matrix is triangular, and False -- otherwise. -- @@ -316,8 +370,9 @@ is_lower_triangular = is_upper_triangular . transpose -- >>> is_triangular m -- False -- -is_triangular :: (Eq a, +is_triangular :: (Ord a, Ring.C a, + Absolute.C a, Arity m, Arity n) => Mat m n a @@ -355,8 +410,9 @@ class (Eq a, Ring.C a) => Determined p a where instance (Eq a, Ring.C a) => Determined (Mat (S Z) (S Z)) a where determinant (Mat rows) = (V.head . V.head) rows -instance (Eq a, +instance (Ord a, Ring.C a, + Absolute.C a, Arity n, Determined (Mat (S n) (S n)) a) => Determined (Mat (S (S n)) (S (S n))) a where @@ -430,8 +486,8 @@ instance (Algebraic.C a, ToRational.C a, Arity m) => Normed (Mat (S m) N1 a) where - -- | Generic p-norms. The usual norm in R^n is (norm_p 2). We treat - -- all matrices as big vectors. + -- | Generic p-norms for vectors in R^n that are represented as nx1 + -- matrices. -- -- Examples: -- @@ -475,15 +531,10 @@ instance (Algebraic.C a, -- frobenius_norm :: (Algebraic.C a, Ring.C a) => Mat m n a -> a frobenius_norm (Mat rows) = - sqrt $ vsum $ V.map row_sum rows + sqrt $ element_sum $ V.map row_sum rows where - -- | The \"sum\" function defined in fixed-vector requires a 'Num' - -- constraint whereas we want to use the classes from - -- numeric-prelude. - vsum = V.foldl (+) (fromInteger 0) - -- | Square and add up the entries of a row. - row_sum = vsum . V.map (^2) + row_sum = element_sum . V.map (^2) -- Vector helpers. We want it to be easy to create low-dimension