dynobud-1.4.0.0: src/Dyno/OcpHomotopy.hs
{-# OPTIONS_GHC -Wall #-}
{-# Language ScopedTypeVariables #-}
{-# Language PolyKinds #-}
module Dyno.OcpHomotopy
( runOcpHomotopy
) where
import Data.Vector ( Vector )
import qualified Data.Traversable as T
import Casadi.MX ( MX )
import Dyno.Ocp
import Dyno.Vectorize ( Vectorize, Id(..), None(..) )
import Dyno.View.View ( View(..), J, JTuple(..), JNone(..) )
import Dyno.View.JV ( JV, catJV, catJV' )
import Dyno.View.Viewable ( Viewable )
import Dyno.TypeVecs ( Dim )
import Dyno.Solvers ( Solver )
import Dyno.Nlp ( Nlp(..), NlpOut(..) )
import Dyno.NlpUtils ( HomotopyParams(..), solveNlp, solveNlpHomotopy )
import Dyno.DirectCollocation.Types ( CollTraj(..), CollOcpConstraints )
import Dyno.DirectCollocation.Formulate ( CollProblem(..), makeCollProblem )
import Dyno.DirectCollocation.Quadratures ( QuadratureRoots )
tupleToCollTraj ::
forall x z u p n deg a
. ( Dim deg, Dim n, Viewable a, Vectorize x, Vectorize z, Vectorize u, Vectorize p )
=> JTuple (CollTraj x z u None n deg) (JV p) a
-> J (CollTraj x z u p n deg) a
tupleToCollTraj (JTuple x0 p) = cat x1
where
x1 :: CollTraj x z u p n deg a
x1 = CollTraj tf p stages0 xf
CollTraj tf _ stages0 xf = split x0
collTrajToTuple ::
forall x z u p n deg a .
( Viewable a
, Vectorize x, Vectorize z, Vectorize u, Vectorize p
, Dim deg, Dim n )
=> J (CollTraj x z u p n deg) a
-> JTuple (CollTraj x z u None n deg) (JV p) a
collTrajToTuple x0 = JTuple (cat x1) pfp
where
x1 :: CollTraj x z u None n deg a
x1 = CollTraj tf (catJV' None) stages0 xf
CollTraj tf pfp stages0 xf = split x0
convertNlp ::
forall x z u p r c h n deg a
. ( Viewable a
, Vectorize x, Vectorize z, Vectorize u, Vectorize p
, Dim deg, Dim n
)
=> Nlp (CollTraj x z u p n deg) JNone (CollOcpConstraints x r c h n deg) a
-> Nlp (CollTraj x z u None n deg) (JV p) (CollOcpConstraints x r c h n deg) a
convertNlp nlp0 = nlp
where
nlp = Nlp { nlpX0 = x0
, nlpBG = nlpBG nlp0
, nlpP = fp0
, nlpFG = fg
, nlpBX = bx
, nlpLamX0 = fmap ((\(JTuple ret _) -> ret) . collTrajToTuple) (nlpLamX0 nlp0)
, nlpLamG0 = nlpLamG0 nlp0
, nlpScaleF = nlpScaleF nlp0
, nlpScaleX = fmap ((\(JTuple ret _) -> ret) . collTrajToTuple) (nlpScaleX nlp0)
, nlpScaleG = nlpScaleG nlp0
}
fg :: J (CollTraj x z u None n deg) a -> J (JV p) a
-> (J (JV Id) a, J (CollOcpConstraints x r c h n deg) a)
fg x fp = (f,g')
where
(f,g') = nlpFG nlp0 x' (cat JNone)
x' :: J (CollTraj x z u p n deg) a
x' = tupleToCollTraj (JTuple x fp)
JTuple x0 fp0 = collTrajToTuple (nlpX0 nlp0)
JTuple bx _ = collTrajToTuple (nlpBX nlp0)
runOcpHomotopy ::
forall x z u p r o c h q n deg t
. ( Dim n, Dim deg
, Vectorize x, Vectorize z, Vectorize u, Vectorize p
, Vectorize r, Vectorize o, Vectorize c, Vectorize h, Vectorize q
, T.Traversable t )
=> Double -> HomotopyParams
-> OcpPhase x z u p r o c h q
-> J (CollTraj x z u p n deg) (Vector Double)
-> QuadratureRoots -> Bool -> Bool -> Solver -> Solver -> p Double -> t (p Double)
-> (CollProblem x z u p r o c h q n deg
-> IO ([String] -> J (CollTraj x z u p n deg) (Vector Double) -> IO Bool)
)
-> IO (t (NlpOut (CollTraj x z u p n deg)
(CollOcpConstraints x r c h n deg)
(Vector Double)))
runOcpHomotopy step0 homotopyParams ocpHomotopy guess roots useStartupCallback useHomotopyCallback
startupSolver homotopySolver param0 nominalParams makeCallback = do
cp0 <- makeCollProblem roots ocpHomotopy guess
callbackHeh <- makeCallback cp0
let nlp0 = cpNlp cp0
let nlpHomotopy :: Nlp
(CollTraj x z u None n deg)
(JV p)
(CollOcpConstraints x r c h n deg)
MX
nlpHomotopy = (convertNlp nlp0) {nlpP = catJV param0}
let callback :: [String]
-> J (CollTraj x z u p n deg) (Vector Double)
-> IO Bool
callback moarMsgs traj = callbackHeh moarMsgs traj
scb = if useStartupCallback then Just (callback ["homotopy startup solve"]) else Nothing
putStrLn "running startup solver..."
(msg0,opt0') <- solveNlp startupSolver nlp0 scb
opt0 <- case msg0 of
Left msg' -> error msg'
Right _ -> return opt0'
let homoGuessX :: J (CollTraj x z u None n deg) (Vector Double)
JTuple homoGuessX _ = collTrajToTuple $ xOpt opt0
JTuple homoGuessLX _ = collTrajToTuple $ lambdaXOpt opt0
homoGuessLG :: J (CollOcpConstraints x r c h n deg) (Vector Double)
homoGuessLG = lambdaGOpt opt0
pFinals :: t (J (JV p) (Vector Double))
pFinals = fmap catJV nominalParams
homoCallback :: J (JTuple (CollTraj x z u None n deg) (JV p)) (Vector Double)
-> IO Bool
homoCallback traj0 = callback [ "homotopy stepping"
] (tupleToCollTraj (split traj0))
putStrLn "\ninitial solve done, starting homotopy steps"
let hcb = if useHomotopyCallback then Just homoCallback else Nothing
pscale :: Maybe (J (JV p) (Vector Double))
pscale = fmap catJV (ocpPScale ocpHomotopy)
opt1s <- solveNlpHomotopy step0 homotopyParams
homotopySolver
pscale
(nlpHomotopy { nlpX0 = homoGuessX
, nlpLamX0 = Just homoGuessLX
, nlpLamG0 = Just homoGuessLG
})
pFinals
hcb Nothing
let f :: NlpOut (JTuple (CollTraj x z u None n deg) (JV p))
(CollOcpConstraints x r c h n deg)
(Vector Double)
-> NlpOut (CollTraj x z u p n deg)
(CollOcpConstraints x r c h n deg)
(Vector Double)
f nlpOut =
NlpOut
{ fOpt = fOpt nlpOut
, xOpt = g (xOpt nlpOut)
, gOpt = gOpt nlpOut
, lambdaXOpt = g (lambdaXOpt nlpOut)
, lambdaGOpt = lambdaGOpt nlpOut
}
where
g :: J (JTuple (CollTraj x z u None n deg) (JV p)) (Vector Double)
-> J (CollTraj x z u p n deg) (Vector Double)
g = tupleToCollTraj . split
ret :: t (NlpOut
(CollTraj x z u p n deg)
(CollOcpConstraints x r c h n deg)
(Vector Double))
ret = fmap f opt1s
return ret