aern2-mfun-0.2.9.0: src/AERN2/BoxFun/Type.hs
module AERN2.BoxFun.Type where
import MixedTypesNumPrelude
import AERN2.Linear.Vector.Type (Vector, (!))
import qualified AERN2.Linear.Vector.Type as V
import AERN2.MP.Ball
import AERN2.AD.Differential
import qualified AERN2.Linear.Matrix.Type as M
import AERN2.Util.Util
import AERN2.BoxFun.Box
import Numeric.CollectErrors
data BoxFun =
BoxFun
{
dimension :: Integer
, bf_eval :: Vector (Differential (CN MPBall)) -> Differential (CN MPBall)
, domain :: Vector (CN MPBall)
}
instance Show BoxFun where
show (BoxFun d _f b) = show d ++ " dimensional BoxFun, domain: " ++ show b
boundaryRestrictions :: BoxFun -> [BoxFun]
boundaryRestrictions (BoxFun d ev dom) =
concat
[
[
BoxFun
(d - 1)
(
\v ->
ev $ V.map (\j -> if j == i then (setPrecision $ getPrecision v) $ differential 2 $ upperBound (dom ! i) else if j < i then v ! j else v ! (j - 1)) $ V.enumFromTo 0 (d - 1)
)
(V.map (\j -> if j >= i then dom ! (j + 1) else dom ! j) $ V.enumFromTo 0 (d - 2))
,
BoxFun
(d - 1)
(
\v ->
ev $ V.map (\j -> if j == i then (setPrecision $ getPrecision v) $ differential 2 $ lowerBound (dom ! i) else if j < i then v ! j else v ! (j - 1)) $ V.enumFromTo 0 (d - 1)
)
(V.map (\j -> if j >= i then dom ! (j + 1) else dom ! j) $ V.enumFromTo 0 (d - 2))
]
|
i <- [0 .. d - 1]
]
valueGradientHessian :: BoxFun -> Vector (CN MPBall) -> (CN MPBall, Vector (CN MPBall), M.Matrix (CN MPBall))
valueGradientHessian (BoxFun d e _) v =
(value, grad, hess)
where
vgh i j = e (w i j)
triangle =
V.map (\i-> V.map (\j -> vgh i j) $ V.enumFromTo 0 i) $ V.enumFromTo 0 (d - 1)
value = diff_x $ (triangle ! 0) ! 0
grad = V.map (\i -> diff_dx $ (triangle ! i) ! 0) $ V.enumFromTo 0 (d - 1)
hess = M.create d d (\i j -> diff_d2x $ if i > j then (triangle ! i) ! j else (triangle ! j) ! i)
w i j = V.imap (\k x -> OrderTwo x (delta i k) (delta j k) (pure $ mpBall 0)) v
delta :: Integer -> Integer -> CN MPBall
delta i k = if i == k then (cn $ mpBall 1) else (cn $ mpBall 0)
valueGradient :: BoxFun -> Vector (CN MPBall) -> (CN MPBall, Vector (CN MPBall))
valueGradient (BoxFun d e _) v =
aux (d - 1) [] (pure $ mpBall 0)
where
tangent k =
V.imap (\i x -> OrderOne x (delta i k)) v
valgrad k =
let
etk = e (tangent k)
in
(diff_x etk, diff_dx etk)
aux k ret val =
if k < 0 then
(val, V.fromList ret)
else
let
(val2,g) = valgrad k
in
aux (k - 1) (g : ret) val2
delta :: Integer -> Integer -> CN MPBall
delta i k = if i == k then (cn $ mpBall 1) else (cn $ mpBall 0)
apply :: BoxFun -> Vector (CN MPBall) -> CN MPBall
apply (BoxFun _d e _) v =
diff_x (e v')
where
v' = V.map (\x -> differential 0 x) v
applyMinimum :: BoxFun -> CN MPBall
applyMinimum h = fst $ endpointsAsIntervals (apply h (domain h))
applyMinimumOnBox :: BoxFun -> Vector (CN MPBall) -> CN MPBall
applyMinimumOnBox h hbox = fst $ endpointsAsIntervals (apply h hbox)
applyMaximum :: BoxFun -> CN MPBall
applyMaximum h = snd $ endpointsAsIntervals (apply h (domain h))
applyMaximumOnBox :: BoxFun -> Vector (CN MPBall) -> CN MPBall
applyMaximumOnBox h hbox = snd $ endpointsAsIntervals (apply h hbox)
gradient :: BoxFun -> Vector (CN MPBall) -> Vector (CN MPBall)
gradient (BoxFun d e _) v =
aux (d - 1) []
where
tangent k =
V.imap (\i x -> OrderOne x (delta i k)) v
grad k =
-- diff_dx $ e (tangent k)
case e (tangent k) of
OrderZero _ -> noValueNumErrorCertain (NumError "details")
val -> diff_dx $ val
aux k ret =
if k < 0 then
V.fromList ret
else
aux (k - 1) (grad k : ret)
delta :: Integer -> Integer -> CN MPBall
delta i k = if i == k then (cn $ mpBall 1) else (cn $ mpBall 0)
hessian :: BoxFun -> Vector (CN MPBall) -> M.Matrix (CN MPBall)
hessian (BoxFun d e _) v =
M.create d d a
where
a i j = diff_d2x $ e (w i j)
w i j = V.imap (\k x -> OrderTwo x (delta i k) (delta j k) (pure $ mpBall 0)) v
delta :: Integer -> Integer -> CN MPBall
delta i k = if i == k then (cn $ mpBall 1) else (cn $ mpBall 0)
jacobian :: [BoxFun] -> Vector (CN MPBall) -> M.Matrix (CN MPBall)
jacobian fs v =
M.create (length fs) highestDiminseionInFs a
where
highestDiminseionInFs = maximum (map dimension fs)
a i j = diff_dx $ bf_eval (fs!!i) (w j)
w j = V.imap (\k x -> OrderOne x (delta j k)) v
delta :: Integer -> Integer -> CN MPBall
delta i k = if i == k then (cn $ mpBall 1) else (cn $ mpBall 0)
gradientUsingGradient :: BoxFun -> Box -> Box
gradientUsingGradient f v =
V.zipWith fromEndpointsAsIntervals lowerBounds upperBounds
where
lowerBounds = firstDerivatives - secondDerivatives * V.map (fmap (mpBall . radius)) v
upperBounds = firstDerivatives + secondDerivatives * V.map (fmap (mpBall . radius)) v
firstDerivatives = head $ M.rows $ jacobian [f] (centre v)
secondDerivatives = fmap abs $ hessian f v
p = getPrecision v