import qualified Algebra.ToRational as ToRational ( C )
import Linear.Matrix (
+ Col,
Mat(..),
(!!!),
(*),
-- | A generalized implementation for Jacobi, Gauss-Seidel, etc. All
-- that we really need to know is how to construct the matrix M, so we
-- take a function that does it as an argument.
-classical_iteration :: (Eq a, Field.C a, Arity m)
- => (Mat m m a -> Mat m m a)
- -> Mat m m a
- -> Mat m N1 a
- -> Mat m N1 a
- -> Mat m N1 a
+classical_iteration :: (Eq a, Field.C a, m ~ S n, Arity n)
+ => (Mat m m a -> Mat m m a)
+ -> Mat m m a
+ -> Col m a
+ -> Col m a
+ -> Col m a
classical_iteration m_function matrix b x_current =
x_next
where
-- | Perform one iteration of successive over-relaxation.
--
-sor_iteration :: forall m a.
- (Eq a, Field.C a, Arity m)
+sor_iteration :: forall m n a.
+ (Eq a, Field.C a, m ~ S n, Arity n)
=> a -- ^ Omega
-> Mat m m a -- ^ Matrix A
-> Mat m N1 a -- ^ Vector b
-- | Compute an infinite list of SOR iterations starting with the
-- vector x0.
-sor_iterations :: (Eq a, Field.C a, Arity m)
+sor_iterations :: (Eq a, Field.C a, m ~ S n, Arity n)
=> a
-> Mat m m a
-> Mat m N1 a
-- | Perform one iteration of Gauss-Seidel.
-gauss_seidel_iteration :: (Eq a, Field.C a, Arity m)
+gauss_seidel_iteration :: (Eq a, Field.C a, m ~ S n, Arity n)
=> Mat m m a
-> Mat m N1 a
-> Mat m N1 a
-- | Compute an infinite list of Gauss-Seidel iterations starting with
-- the vector x0.
-gauss_seidel_iterations :: (Eq a, Field.C a, Arity m)
+gauss_seidel_iterations :: (Eq a, Field.C a, m ~ S n, Arity n)
=> Mat m m a
-> Mat m N1 a
-> Mat m N1 a
-- >>> jacobi_iteration m b x1
-- ((0.0),(0.25))
--
-jacobi_iteration :: (Eq a, Field.C a, Arity m)
+jacobi_iteration :: (Eq a, Field.C a, m ~ S n, Arity n)
=> Mat m m a
-> Mat m N1 a
-> Mat m N1 a
-- | Compute an infinite list of Jacobi iterations starting with the
-- vector x0.
-jacobi_iterations :: (Eq a, Field.C a, Arity m)
+jacobi_iterations :: (Eq a, Field.C a, m ~ S n, Arity n)
=> Mat m m a
-> Mat m N1 a
-> Mat m N1 a
where
import qualified Algebra.Algebraic as Algebraic ( C )
-import Data.Vector.Fixed ( Arity )
+import Data.Vector.Fixed ( Arity, S )
import NumericPrelude hiding ( (*), abs )
import qualified NumericPrelude as NP ( (*) )
import qualified Algebra.Field as Field ( C )
(!!!),
cholesky,
construct,
+ diagonal,
+ dot,
+ ifoldl2,
is_lower_triangular,
is_upper_triangular,
ncols,
+ row,
+ set_idx,
+ zip2,
transpose )
-- True
--
forward_substitute :: forall a m. (Eq a, Field.C a, Arity m)
- => Mat m m a
- -> Col m a
- -> Col m a
-forward_substitute m' b'
- | not (is_lower_triangular m') =
+ => Mat (S m) (S m) a
+ -> Col (S m) a
+ -> Col (S m) a
+forward_substitute matrix b
+ | not (is_lower_triangular matrix) =
error "forward substitution on non-lower-triangular matrix"
- | otherwise = x'
- where
- x' = construct lambda
-
- -- Convenient accessor for the elements of b'.
- b :: Int -> a
- b k = b' !!! (k, 0)
-
- -- Convenient accessor for the elements of m'.
- m :: Int -> Int -> a
- m i j = m' !!! (i, j)
+ | otherwise = ifoldl2 f zero pairs
+ where
+ -- Pairs (m_ii, b_i) needed at each step.
+ pairs :: Col (S m) (a,a)
+ pairs = zip2 (diagonal matrix) b
- -- Convenient accessor for the elements of x'.
- x :: Int -> a
- x k = x' !!! (k, 0)
+ f :: Int -> Int -> Col (S m) a -> (a, a) -> Col (S m) a
+ f i _ x (mii, bi) = set_idx x (i,0) newval
+ where
+ newval = (bi - (x `dot` (transpose $ row matrix i))) / mii
- -- The second argument to lambda should always be zero here, so we
- -- ignore it.
- lambda :: Int -> Int -> a
- lambda 0 _ = (b 0) / (m 0 0)
- lambda k _ = ((b k) - sum [ (m k j) NP.* (x j) |
- j <- [0..k-1] ]) / (m k k)
-- | Solve the system m*x = b, where m is upper-triangular. Will
-- ((0.0),(0.0),(1.0))
--
backward_substitute :: forall m a. (Eq a, Field.C a, Arity m)
- => Mat m m a
- -> Col m a
- -> Col m a
+ => Mat (S m) (S m) a
+ -> Col (S m) a
+ -> Col (S m) a
backward_substitute m' b'
| not (is_upper_triangular m') =
error "backward substitution on non-upper-triangular matrix"
-- True
--
solve_positive_definite :: (Arity m, Algebraic.C a, Eq a, Field.C a)
- => Mat m m a
- -> Col m a
- -> Col m a
+ => Mat (S m) (S m) a
+ -> Col (S m) a
+ -> Col (S m) a
solve_positive_definite m b = x
where
r = cholesky m