gasp-1.4.0.0: Algebra/Morphism/Affine.hs
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Algebra.Morphism.Affine where
import Prelude (Eq(..), Ord(..), Functor(..), id,Bool(..),Show,otherwise)
import Algebra.Classes
import Algebra.Linear
import qualified Data.Map as M
import Data.Either
import Control.Applicative
import Algebra.Morphism.LinComb (LinComb(..))
import qualified Algebra.Morphism.LinComb as LC
data Affine x c = Affine c (LinComb x c)
deriving (Functor, Eq, Ord,Show)
instance Multiplicative c => Scalable c (Affine x c) where
k *^ x = k *< x
instance (Ord x, AbelianAdditive c,DecidableZero c) => AbelianAdditive (Affine x c)
instance (Ord x, AbelianAdditive c,Group c,DecidableZero c) => Group (Affine x c) where
negate = fmap negate
instance (Ord x, AbelianAdditive c,DecidableZero c) => Additive (Affine x c) where
(Affine c1 xs1) + (Affine c2 xs2) = Affine (c1 + c2) (xs1 + xs2)
zero = Affine zero zero
splitVar :: Ord x => Additive c => x -> Affine x c -> (c, Affine x c)
splitVar x (Affine c0 (LinComb m)) = (M.findWithDefault zero x m, Affine c0 (LinComb (M.delete x m)))
-- | @solve x f@ solves the equation @f == 0@ for x.
-- Let f = k x + e. If k == 0, return Left e. Otherwise, x and return Right -e/k. (The value of x)
solve :: (Ord scalar, Eq scalar, Field scalar, Ord x,DecidableZero scalar)
=> x -> Affine x scalar -> Either (Affine x scalar) (Bool,Affine x scalar)
solve x f = if k == zero then Left e else Right (k>zero,recip k *^ negate e)
where (k,e) = splitVar x f
-- | Constant affine expression
constant :: (AbelianAdditive c, DecidableZero c) => Ord x => c -> Affine x c
constant c = Affine c zero
isConstant :: Eq c => Ord x => DecidableZero c => Affine x c -> Either x c
isConstant (Affine k x) = case LC.toList x of
[] -> Right k
((v,_):_) -> Left v
var :: Multiplicative c => Additive c => v -> Affine v c
var x = Affine zero (LC.var x)
eval :: forall x c v. (Additive x, Scalable x x) => (c -> x) -> (v -> x) -> Affine v c -> x
eval fc fv (Affine c p) = fc c + LC.eval fc fv p
subst :: (Ord x, AbelianAdditive c, DecidableZero c, Multiplicative c) => (v -> Affine x c) -> Affine v c -> Affine x c
subst f (Affine c p) = constant c + LC.eval id f p
mapVars :: Ord x => (v -> x) -> Affine v c -> Affine x c
mapVars f (Affine k e) = Affine k (LC.mapVars f e)
traverseVars :: Ord x => Applicative f => (v -> f x) -> Affine v c -> f (Affine x c)
traverseVars f (Affine k e) = Affine k <$> LC.traverseVars f e