np-linear-0.1.1.1: src/Algebra/Linear/Subspace.hs
{-# LANGUAGE NoImplicitPrelude,RebindableSyntax #-}
{-# LANGUAGE ScopedTypeVariables,FlexibleContexts #-}
module Algebra.Linear.Subspace
(
Subspace
, fromGenerators
, span
, line
, empty
, fromRelations
, inside
, basis
, union
, intersection
, pullback
, image
, kernel
, dimension
) where
import Algebra.Linear
(
Vector
, Matrix
, Relation(Relation)
, getRelation
, satisfies
, solve
, equations
, matrixProduct
)
import qualified Algebra.Field
import NumericPrelude hiding (span)
import Data.List (transpose,genericLength)
import Data.Proxy (Proxy(Proxy))
import Data.Reflection (Reifies,reflect)
data Subspace k
= Generators Integer [Vector k] -- These are linearly independent.
| Relations Integer [Relation k] -- These might be redundant.
degree :: Subspace k -> Integer
degree (Generators d _) = d
degree (Relations d _) = d
instance (Show k) => Show (Subspace k) where
show (Generators d gs) = "Subspace (of space of dimension " ++ show d ++ ") generated by " ++ show gs
show (Relations d rs) = "Subspace (of space of dimension " ++ show d ++ ") defined by relations " ++ show (map getRelation rs)
fromGenerators :: (Algebra.Field.C k,Eq k) => Integer -> [Vector k] -> Subspace k
fromGenerators d gs = Relations d (equations d gs)
span :: (Algebra.Field.C k,Eq k) => [Vector k] -> Subspace k
span gs = fromGenerators d gs where
d = case gs of
g : _ -> genericLength g
[] -> error "Algebra.Linear.Subspace.fromGenerators: no generators"
line :: (Algebra.Field.C k,Eq k) => Vector k -> Subspace k
line = span . (: [])
empty :: Integer -> Subspace k
empty d = Generators d []
fromRelations :: Integer -> [Relation k] -> Subspace k
fromRelations = Relations
inside :: (Algebra.Field.C k,Eq k) => Subspace k -> Vector k -> Bool
inside s v = all (v `satisfies`) (toRelations s)
basis :: (Algebra.Field.C k,Eq k) => Subspace k -> [Vector k]
basis (Generators _ gs) = gs
basis (Relations d rs) = solve d rs
toRelations :: (Algebra.Field.C k,Eq k) => Subspace k -> [Relation k]
toRelations (Generators d gs) = equations d gs
toRelations (Relations _ rs) = rs
union :: (Algebra.Field.C k,Eq k) => Subspace k -> Subspace k -> Subspace k
union a b = fromGenerators (sameDegree a b) $ basis a ++ basis b
intersection :: (Algebra.Field.C k,Eq k) => Subspace k -> Subspace k -> Subspace k
intersection a b = Relations (sameDegree a b) $ toRelations a ++ toRelations b where
sameDegree :: Subspace k -> Subspace k -> Integer
sameDegree a b
| degree a == degree b = degree a
| otherwise = error "Algebra.Linear.Subspace.sameDegree: subspaces of different degree"
pullback :: (Algebra.Field.C k,Eq k) => Matrix k -> Subspace k -> Subspace k
pullback [] = error "Algebra.Linear.Subspace.pullback: empty matrix"
pullback m =
Relations d
. map Relation
. transpose
. matrixProduct (transpose m)
. transpose
. map getRelation
. toRelations
. intersection (image m)
where
d = genericLength (head m)
image :: (Algebra.Field.C k,Eq k) => Matrix k -> Subspace k
image rows = fromGenerators d . transpose $ rows where
d = genericLength rows
kernel :: Matrix k -> Subspace k
kernel [] = error "Algebra.Linear.Subspace.kernel: empty matrix"
kernel rows = Relations d . map Relation $ rows where
d = genericLength (head rows)
dimension :: (Algebra.Field.C k,Eq k) => Subspace k -> Integer
dimension = genericLength . basis