dynobud-1.7.1.0: src/Dyno/NlpSolver.hs
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Dyno.NlpSolver
( NlpSolver
, runNlpSolver
, RunNlpOptions(..)
, runNlpSolverWith
, defaultRunnerOptions
-- * solve
, solve
, solve'
-- * inputs
, setX0
, setP
, setLbx
, setUbx
, setLbg
, setUbg
, setLamX0
, setLamG0
, getX0
, getP
, getLbx
, getUbx
, getLbg
, getUbg
, getLamX0
, getLamG0
-- * outputs
, getF
, getX
, getG
, getLamX
, getLamG
, getStat
, getNlpOut
-- * kkt conditions, evalKKT is in user units, evalScaledKKT is the internal one
, evalGradF
, evalJacG
, evalHessF
, evalHessLambdaG
, evalKKT
, evalScaledGradF
, evalScaledJacG
, evalScaledHessLag
, evalScaledHessF
, evalScaledHessLambdaG
, evalScaledKKT
-- * options
, Op.Opt(..)
, setOption
, reinit
-- * other
, MonadIO
, liftIO
, generateAndCompile
) where
import Text.Printf ( printf )
import Data.Time.Clock ( getCurrentTime, diffUTCTime )
import Data.Proxy ( Proxy(..) )
import System.Process ( callProcess, showCommandForUser )
import Control.Exception ( AsyncException( UserInterrupt ), try )
import Control.Concurrent ( forkIO, newEmptyMVar, takeMVar, putMVar )
import qualified Control.Applicative as A
import Control.Monad ( when, void )
import "mtl" Control.Monad.Reader ( MonadIO(..), MonadReader(..), ReaderT(..) )
import Data.Maybe ( fromMaybe )
import Data.IORef ( newIORef, readIORef, writeIORef )
import Data.Vector ( Vector )
import qualified Data.Vector as V
import Casadi.Core.Enums ( InputOutputScheme(..) )
import qualified Casadi.Core.Classes.Function as C
import qualified Casadi.Core.Classes.NlpSolver as C
import qualified Casadi.Core.Classes.GenericType as C
import qualified Casadi.Core.Classes.IOInterfaceFunction as C
import Casadi.Callback ( makeCallback )
import Casadi.DMatrix ( DMatrix, dnonzeros )
import Casadi.Function ( Function, externalFunction, generateCode )
import qualified Casadi.Option as Op
import qualified Casadi.GenericC as Gen
import Casadi.SharedObject ( soInit )
import Casadi.CMatrix ( CMatrix )
import qualified Casadi.CMatrix as CM
import Dyno.View.Unsafe.View ( unJ, mkJ )
import Dyno.View.Unsafe.M ( mkM )
import Dyno.FormatTime ( formatSeconds )
import Dyno.Vectorize ( Id(..) )
import Dyno.View.JV ( JV )
import Dyno.View.View ( View(..), J, fmapJ, d2v, v2d, jfill )
import Dyno.View.M ( M )
import qualified Dyno.View.M as M
import Dyno.View.Symbolic ( Symbolic, sym, mkScheme, mkFunction )
import Dyno.View.Viewable ( Viewable )
import Dyno.Nlp ( NlpOut(..), KKT(..) )
import Dyno.NlpScaling ( ScaleFuns(..), scaledFG, mkScaleFuns )
import Dyno.Solvers ( Solver(..), getSolverInternal )
import Dyno.SolverInternal ( SolverInternal(..) )
type VD a = J a (Vector Double)
type VMD a = J a (Vector (Maybe Double))
timeIt :: IO a -> IO (a, Double)
timeIt action = do
t0 <- getCurrentTime
ret <- action
t1 <- getCurrentTime
return (ret, realToFrac (diffUTCTime t1 t0))
getStat :: String -> NlpSolver x p g C.GenericType
getStat name = do
nlpState <- ask
liftIO $ C.function_getStat (isSolver nlpState) name
setInput ::
View xg
=> (ScaleFuns x g DMatrix -> (J xg DMatrix -> J xg DMatrix))
-> (NlpState x p g -> Int)
-> String
-> J xg (V.Vector Double)
-> NlpSolver x p g ()
setInput scaleFun getLen name x0 = do
nlpState <- ask
let x = unJ $ scaleFun (isScale nlpState) $ mkJ $ CM.fromDVector (unJ x0)
let nActual = (CM.size1 x, CM.size2 x)
nTypeLevel = (getLen nlpState, 1)
when (nTypeLevel /= nActual) $ error $
name ++ " dimension mismatch, " ++ show nTypeLevel ++
" (type-level) /= " ++ show nActual ++ " (given)"
liftIO $ C.ioInterfaceFunction_setInput__0 (isSolver nlpState) x name
return ()
setX0 :: forall x p g. View x => VD x -> NlpSolver x p g ()
setX0 = setInput xToXBar isNx "x0"
inf :: Double
inf = read "Infinity"
toLb :: View x => J x (Vector (Maybe Double)) -> J x (Vector Double)
toLb = fmapJ (fromMaybe (-inf))
toUb :: View x => J x (Vector (Maybe Double)) -> J x (Vector Double)
toUb = fmapJ (fromMaybe inf )
setLbx :: View x => VMD x -> NlpSolver x p g ()
setLbx = setInput xToXBar isNx "lbx" . toLb
setUbx :: View x => VMD x -> NlpSolver x p g ()
setUbx = setInput xToXBar isNx "ubx" . toUb
setLbg :: View g => VMD g -> NlpSolver x p g ()
setLbg = setInput gToGBar isNg "lbg" . toLb
setUbg :: View g => VMD g -> NlpSolver x p g ()
setUbg = setInput gToGBar isNg "ubg" . toUb
setP :: View p => VD p -> NlpSolver x p g ()
setP p = do
nlpState <- ask
isSetParam nlpState p
setInput (const id) isNp "p" p
setLamX0 :: View x => VD x -> NlpSolver x p g ()
setLamX0 = setInput lamXToLamXBar isNx "lam_x0"
setLamG0 :: View g => VD g -> NlpSolver x p g ()
setLamG0 = setInput lamGToLamGBar isNg "lam_g0"
getInput ::
View xg
=> (ScaleFuns x g DMatrix -> (J xg DMatrix -> J xg DMatrix))
-> String -> NlpSolver x p g (J xg (Vector Double))
getInput scaleFun name = do
nlpState <- ask
dmat <- liftIO $ C.ioInterfaceFunction_input__0 (isSolver nlpState) name
let scale = scaleFun (isScale nlpState)
return (mkJ $ dnonzeros $ unJ $ scale (mkJ dmat))
getX0 :: View x => NlpSolver x p g (VD x)
getX0 = getInput xbarToX "x0"
getLbx :: View x => NlpSolver x p g (VD x)
getLbx = getInput xbarToX "lbx"
getUbx :: View x => NlpSolver x p g (VD x)
getUbx = getInput xbarToX "ubx"
getLbg :: View g => NlpSolver x p g (VD g)
getLbg = getInput gbarToG "lbg"
getUbg :: View g => NlpSolver x p g (VD g)
getUbg = getInput gbarToG "ubg"
getP :: View p => NlpSolver x p g (VD p)
getP = getInput (const id) "p"
getLamX0 :: View x => NlpSolver x p g (VD x)
getLamX0 = getInput lamXBarToLamX "lam_x0"
getLamG0 :: View g => NlpSolver x p g (VD g)
getLamG0 = getInput lamGBarToLamG "lam_g0"
getOutput ::
View xg
=> (ScaleFuns x g DMatrix -> (J xg DMatrix -> J xg DMatrix))
-> String -> NlpSolver x p g (J xg (Vector Double))
getOutput scaleFun name = do
nlpState <- ask
dmat <- liftIO $ C.ioInterfaceFunction_output__0 (isSolver nlpState) name
let scale = scaleFun (isScale nlpState)
return (mkJ $ dnonzeros $ unJ $ scale (mkJ dmat))
getF :: NlpSolver x p g (VD (JV Id))
getF = getOutput fbarToF "f"
getX :: View x => NlpSolver x p g (VD x)
getX = getOutput xbarToX "x"
getG :: View g => NlpSolver x p g (VD g)
getG = getOutput gbarToG "g"
getLamX :: View x => NlpSolver x p g (VD x)
getLamX = getOutput lamXBarToLamX "lam_x"
getLamG :: View g => NlpSolver x p g (VD g)
getLamG = getOutput lamGBarToLamG "lam_g"
evalScaledGradF :: forall x p g . (View x, View g, View p)
=> NlpSolver x p g (J x DMatrix, J (JV Id) DMatrix)
evalScaledGradF = do
x0bar <- getInput (const id) "x0" :: NlpSolver x p g (J x (Vector Double))
pbar <- getInput (const id) "p" :: NlpSolver x p g (J p (Vector Double))
nlpState <- ask
let solver = isSolver nlpState :: C.NlpSolver
liftIO $ do
gradF <- C.nlpSolver_gradF solver
C.ioInterfaceFunction_setInput__0 gradF (unJ (v2d x0bar)) "x"
C.ioInterfaceFunction_setInput__0 gradF (unJ (v2d pbar)) "p"
C.function_evaluate gradF
gradF' <- C.ioInterfaceFunction_output__0 gradF "grad"
f' <- C.ioInterfaceFunction_output__0 gradF "f"
return (mkJ gradF', mkJ f')
evalGradF :: forall x p g . (View x, View g, View p)
=> NlpSolver x p g (J x DMatrix, J (JV Id) DMatrix)
evalGradF = do
nlpState <- ask
let scale = isScale nlpState
(gradF, f) <- evalScaledGradF
return (gradFBarToGradF scale gradF, fbarToF scale f)
evalScaledJacG :: forall x p g . (View x, View g, View p)
=> NlpSolver x p g (M g x DMatrix, J g DMatrix)
evalScaledJacG = do
x0bar <- getInput (const id) "x0" :: NlpSolver x p g (J x (Vector Double))
pbar <- getInput (const id) "p" :: NlpSolver x p g (J p (Vector Double))
nlpState <- ask
let solver = isSolver nlpState :: C.NlpSolver
-- todo: remove this workaround when casadi fixes https://github.com/casadi/casadi/issues/1345
if size (Proxy :: Proxy g) == 0
then return (M.zeros, M.uncol M.zeros)
else liftIO $ do
jacG <- C.nlpSolver_jacG solver
C.ioInterfaceFunction_setInput__0 jacG (unJ (v2d x0bar)) "x"
C.ioInterfaceFunction_setInput__0 jacG (unJ (v2d pbar)) "p"
C.function_evaluate jacG
jacG' <- C.ioInterfaceFunction_output__0 jacG "jac"
g' <- C.ioInterfaceFunction_output__0 jacG "g"
return (mkM jacG', mkJ g')
evalJacG :: forall x p g . (View x, View g, View p)
=> NlpSolver x p g (M g x DMatrix, J g DMatrix)
evalJacG = do
(jacG, g) <- evalScaledJacG
nlpState <- ask
let scale = isScale nlpState
return (jacGBarToJacG scale jacG, gbarToG scale g)
evalScaledHessLag :: forall x p g . (View x, View g, View p)
=> NlpSolver x p g (M x x DMatrix)
evalScaledHessLag = do
x0bar <- getInput (const id) "x0" :: NlpSolver x p g (J x (Vector Double))
pbar <- getInput (const id) "p" :: NlpSolver x p g (J p (Vector Double))
lamGbar <- getInput (const id) "lam_g0" :: NlpSolver x p g (J g (Vector Double))
nlpState <- ask
let solver = isSolver nlpState :: C.NlpSolver
liftIO $ do
hessLag <- C.nlpSolver_hessLag solver
C.ioInterfaceFunction_setInput__0 hessLag (unJ (v2d x0bar)) "x"
C.ioInterfaceFunction_setInput__0 hessLag (unJ (v2d pbar)) "p"
C.ioInterfaceFunction_setInput__0 hessLag (unJ (v2d lamGbar)) "lam_g"
C.ioInterfaceFunction_setInput__0 hessLag 1.0 "lam_f"
C.function_evaluate hessLag
hess' <- C.ioInterfaceFunction_output__0 hessLag "hess"
return (mkM hess')
-- | only valid at the solution
evalHessLag :: forall x p g . (View x, View g, View p)
=> NlpSolver x p g (M x x DMatrix)
evalHessLag = do
hess <- evalScaledHessLambdaG
nlpState <- ask
let scale = isScale nlpState
return (hessLagBarToHessLag scale hess)
evalScaledHessF :: forall x p g . (View x, View g, View p)
=> NlpSolver x p g (M x x DMatrix)
evalScaledHessF = do
x0bar <- getInput (const id) "x0" :: NlpSolver x p g (J x (Vector Double))
pbar <- getInput (const id) "p" :: NlpSolver x p g (J p (Vector Double))
let lamGbar = jfill 0 :: J g (Vector Double)
nlpState <- ask
let solver = isSolver nlpState :: C.NlpSolver
liftIO $ do
hessLag <- C.nlpSolver_hessLag solver
C.ioInterfaceFunction_setInput__0 hessLag (unJ (v2d x0bar)) "x"
C.ioInterfaceFunction_setInput__0 hessLag (unJ (v2d pbar)) "p"
C.ioInterfaceFunction_setInput__0 hessLag (unJ (v2d lamGbar)) "lam_g"
C.ioInterfaceFunction_setInput__0 hessLag 1.0 "lam_f"
C.function_evaluate hessLag
hess' <- C.ioInterfaceFunction_output__0 hessLag "hess"
return (mkM hess')
evalHessF :: forall x p g . (View x, View g, View p)
=> NlpSolver x p g (M x x DMatrix)
evalHessF = do
hess <- evalScaledHessLag
nlpState <- ask
let scale = isScale nlpState
return (hessFBarToHessF scale hess)
evalScaledHessLambdaG :: forall x p g . (View x, View g, View p)
=> NlpSolver x p g (M x x DMatrix)
evalScaledHessLambdaG = do
x0bar <- getInput (const id) "x0" :: NlpSolver x p g (J x (Vector Double))
pbar <- getInput (const id) "p" :: NlpSolver x p g (J p (Vector Double))
lamGbar <- getInput (const id) "lam_g0" :: NlpSolver x p g (J g (Vector Double))
nlpState <- ask
let solver = isSolver nlpState :: C.NlpSolver
liftIO $ do
hessLag <- C.nlpSolver_hessLag solver
C.ioInterfaceFunction_setInput__0 hessLag (unJ (v2d x0bar)) "x"
C.ioInterfaceFunction_setInput__0 hessLag (unJ (v2d pbar)) "p"
C.ioInterfaceFunction_setInput__0 hessLag (unJ (v2d lamGbar)) "lam_g"
C.ioInterfaceFunction_setInput__0 hessLag 0.0 "lam_f"
C.function_evaluate hessLag
hess' <- C.ioInterfaceFunction_output__0 hessLag "hess"
return (mkM hess')
-- | only valid at solution
evalHessLambdaG :: forall x p g . (View x, View g, View p)
=> NlpSolver x p g (M x x DMatrix)
evalHessLambdaG = do
hess <- evalScaledHessLambdaG
nlpState <- ask
let scale = isScale nlpState
return (hessLamGBarToHessLamG scale hess)
evalKKT :: (View x, View p, View g) => NlpSolver x p g (KKT x g)
evalKKT = do
(gradF,f) <- evalGradF
(jacG, g) <- evalJacG
hessF <- evalHessF
hessLambdaG <- evalHessLambdaG
hessLag <- evalHessLag
return $
KKT
{ kktF = f
, kktJacG = jacG
, kktG = g
, kktGradF = gradF
, kktHessLag = hessLag
, kktHessF = hessF
, kktHessLambdaG = hessLambdaG
}
evalScaledKKT :: (View x, View p, View g) => NlpSolver x p g (KKT x g)
evalScaledKKT = do
(gradF,f) <- evalScaledGradF
(jacG, g) <- evalScaledJacG
hessL <- evalScaledHessLag
hessF <- evalScaledHessF
hessLambdaG <- evalScaledHessLambdaG
return $
KKT
{ kktF = f
, kktJacG = jacG
, kktG = g
, kktGradF = gradF
, kktHessLag = hessL
, kktHessF = hessF
, kktHessLambdaG = hessLambdaG
}
setOption :: Gen.GenericC a => String -> a -> NlpSolver x p g ()
setOption name val = do
nlpState <- ask
let nlp = isSolver nlpState
liftIO $ Op.setOption nlp name val
reinit :: NlpSolver x p g ()
reinit = do
nlpState <- ask
let nlp = isSolver nlpState
liftIO $ soInit nlp
-- | solve with current inputs, return success or failure code
solve :: NlpSolver x p g (Either String String)
solve = do
nlpState <- ask
let nlp = isSolver nlpState
solveStatus <- liftIO $ do
stop <- newEmptyMVar -- mvar that will be filled when nlp finishes
_ <- forkIO (C.function_evaluate nlp >> putMVar stop ())
-- wait until nlp finishes
ret <- try (takeMVar stop)
case ret of Right () -> return () -- no exceptions
Left UserInterrupt -> do -- got ctrl-C
isInterrupt nlpState -- tell nlp to stop iterations
_ <- takeMVar stop -- wait for nlp to return
return ()
Left _ -> void (takeMVar stop) -- don't handle this one
genericStat <- C.function_getStat nlp "return_status"
strStat <- Gen.fromGeneric genericStat :: IO (Maybe String)
intStat <- Gen.fromGeneric genericStat :: IO (Maybe Int)
statDescription <- Gen.getDescription genericStat
case strStat of
Just strStat' -> return strStat'
Nothing -> case intStat of
Just intStat' -> return (show intStat')
Nothing -> error $ "nlp solver error: return status is not {string,int}, it's " ++
statDescription
return $ if solveStatus `elem` isSuccessCodes nlpState
then Right solveStatus
else Left solveStatus
-- | solve with current inputs, return lots of info on success, or message on failure
solve' :: (View x, View g) => NlpSolver x p g (Either String String, NlpOut x g (Vector Double))
solve' = do
solveStatus <- solve
nlpOut <- getNlpOut
return (solveStatus, nlpOut)
getNlpOut :: (View x, View g) => NlpSolver x p g (NlpOut x g (Vector Double))
getNlpOut = do
fopt <- getF
xopt <- getX
gopt <- getG
lamXOpt <- getLamX
lamGOpt <- getLamG
let nlpOut = NlpOut { fOpt = fopt
, xOpt = xopt
, gOpt = gopt
, lambdaXOpt = lamXOpt
, lambdaGOpt = lamGOpt
}
return nlpOut
data NlpState (x :: * -> *) (p :: * -> *) (g :: * -> *) =
NlpState
{ isNx :: Int
, isNg :: Int
, isNp :: Int
, isSolver :: C.NlpSolver
, isInterrupt :: IO ()
, isSuccessCodes :: [String]
, isScale :: ScaleFuns x g DMatrix
, isSetParam :: J p (Vector Double) -> NlpSolver x p g ()
}
newtype NlpSolver (x :: * -> *) (p :: * -> *) (g :: * -> *) a =
NlpSolver (ReaderT (NlpState x p g) IO a)
deriving ( Functor
, A.Applicative
, Monad
, MonadReader (NlpState x p g)
, MonadIO
)
generateAndCompile :: String -> Function -> IO Function
generateAndCompile name f = do
putStrLn $ "generating " ++ name ++ ".c"
writeFile (name ++ ".c") (generateCode f True)
-- C.function_generateCode__1 f (name ++ ".c") True
let cmd = "clang"
args = ["-fPIC","-shared","-Wall","-Wno-unused-variable",name++".c","-o",name++".so"]
putStrLn (showCommandForUser cmd args)
callProcess cmd args
externalFunction ("./"++name++".so")
data RunNlpOptions =
RunNlpOptions
{ verbose :: Bool
}
defaultRunnerOptions :: RunNlpOptions
defaultRunnerOptions =
RunNlpOptions
{ verbose = False
}
runNlpSolver ::
forall x p g a s .
(View x, View p, View g, Symbolic s)
=> Solver
-> (J x s -> J p s -> (J (JV Id) s, J g s))
-> Maybe (J x (Vector Double))
-> Maybe (J g (Vector Double))
-> Maybe Double
-> Maybe (J x (Vector Double) -> J p (Vector Double) -> IO Bool)
-> NlpSolver x p g a
-> IO a
runNlpSolver = runNlpSolverWith defaultRunnerOptions
runNlpSolverWith ::
forall x p g a s .
(View x, View p, View g, Symbolic s)
=> RunNlpOptions
-> Solver
-> (J x s -> J p s -> (J (JV Id) s, J g s))
-> Maybe (J x (Vector Double))
-> Maybe (J g (Vector Double))
-> Maybe Double
-> Maybe (J x (Vector Double) -> J p (Vector Double) -> IO Bool)
-> NlpSolver x p g a
-> IO a
runNlpSolverWith runnerOptions solverStuff nlpFun scaleX scaleG scaleF callback' (NlpSolver nlpMonad) = do
inputsX <- sym "x"
inputsP <- sym "p"
let scale :: forall sfa . (CMatrix sfa, Viewable sfa) => ScaleFuns x g sfa
scale = mkScaleFuns scaleX scaleG scaleF
let (obj, g) = scaledFG scale nlpFun inputsX inputsP
let inputsXMat = unJ inputsX
inputsPMat = unJ inputsP
objMat = unJ obj
gMat = unJ g
inputScheme <- mkScheme SCHEME_NLPInput [("x", inputsXMat), ("p", inputsPMat)]
outputScheme <- mkScheme SCHEME_NLPOutput [("f", objMat), ("g", gMat)]
when (verbose runnerOptions) $ do
putStrLn "************** initializing dynobud runNlpSolver ******************"
putStrLn "making nlp..."
(nlp, nlpTime) <- timeIt $ mkFunction "nlp" inputScheme outputScheme
when (verbose runnerOptions) $ printf "made nlp in %s\n" (formatSeconds nlpTime)
mapM_ (\(l,Op.Opt o) -> Op.setOption nlp l o) (functionOptions solverStuff)
when (verbose runnerOptions) $ putStrLn "init nlp..."
(_, nlpInitTime) <- timeIt $ soInit nlp
when (verbose runnerOptions) $ printf "nlp initialized in %s\n" (formatSeconds nlpInitTime)
when (verbose runnerOptions) $ putStrLn "function call..."
-- in case the user wants to do something (like codegen?)
(_, functionCallTime) <- timeIt $ functionCall solverStuff nlp
when (verbose runnerOptions) $ printf "function called in %s\n" (formatSeconds functionCallTime)
-- let eval 0 = error "finished"
-- eval k = do
-- putStrLn "setting input"
-- ioInterfaceFunction_setInput''' nlp (unJ nlpX0') (0::Int)
-- putStrLn $ "evaluating " ++ show k
-- C.function_evaluate nlp
-- eval (k-1 :: Int)
-- eval (300::Int)
-- casadiOptions_stopProfiling
-- _ <- error "done"
-- jac_sparsity <- C.function_jacSparsity nlp 0 1 True False
-- C.sparsity_spyMatlab jac_sparsity "jac_sparsity_reorder.m"
when (verbose runnerOptions) $ putStrLn "create solver..."
(solver, solverCreateTime) <- timeIt $ C.nlpSolver__0 (solverName (getSolverInternal solverStuff)) nlp
when (verbose runnerOptions) $ printf "created solver in %s\n" (formatSeconds solverCreateTime)
-- add callback if user provides it
intref <- newIORef False
paramRef <- newIORef (jfill 0)
let cb function' = do
callbackRet <- case callback' of
Nothing -> return True
Just callback -> do
xval <- fmap (d2v . xbarToX scale . mkJ . CM.densify) $
C.ioInterfaceFunction_output__2 function' 0
pval <- readIORef paramRef
callback xval pval
interrupt <- readIORef intref
return $ if callbackRet && not interrupt then 0
else fromIntegral (solverInterruptCode (getSolverInternal solverStuff))
casadiCallback <- makeCallback cb >>= C.genericType__0
Op.setOption solver "iteration_callback" casadiCallback
-- grad_f <- gradient nlp 0 0
-- soInit grad_f
-- jac_g <- jacobian nlp 0 1 True False
-- soInit jac_g
--
-- let eval 0 = error "finished"
-- eval k = do
-- putStrLn "setting input"
-- ioInterfaceFunction_setInput''' jac_g (unJ nlpX0') (0::Int)
-- putStrLn $ "evaluating " ++ show k
-- C.function_evaluate jac_g
-- eval (k-1 :: Int)
-- eval (40::Int)
-- nlp' <- generateAndCompile "nlp" nlp
-- grad_f' <- generateAndCompile "grad_f" grad_f
-- jac_g' <- generateAndCompile "jac_g" jac_g
-- _ <- error "lal"
-- Op.setOption solver "grad_f" grad_f'
-- Op.setOption solver "jac_g" jac_g'
-- set all the user options
mapM_ (\(l,Op.Opt o) -> Op.setOption solver l o) (defaultSolverOptions (getSolverInternal solverStuff)
++ options solverStuff)
when (verbose runnerOptions) $ putStrLn "initialize solver..."
(_, solverInitTime) <- timeIt $ soInit solver
when (verbose runnerOptions) $ printf "solver initialized in %s\n" (formatSeconds solverInitTime)
let proxy :: J f b -> Proxy f
proxy = const Proxy
nlpState = NlpState { isNx = size (proxy inputsX)
, isNp = size (proxy inputsP)
, isNg = size (proxy g)
, isSolver = solver
, isInterrupt = writeIORef intref True
, isSuccessCodes = successCodes (getSolverInternal solverStuff)
, isScale = scale
, isSetParam = liftIO . writeIORef paramRef
}
when (verbose runnerOptions) $ putStrLn "run NLP monad..."
(ret, retTime) <- timeIt $ liftIO $ runReaderT nlpMonad nlpState
when (verbose runnerOptions) $ printf "ran NLP monad in %s\n" (formatSeconds retTime)
return ret