ipopt-hs 0.3.0.0 → 0.4.0.0
raw patch · 10 files changed
+894/−80 lines, 10 filesdep +criteriondep +lineardep +optimizationdep ~addep ~containersdep ~lens
Dependencies added: criterion, linear, optimization, random-shuffle, template-haskell, uu-parsinglib
Dependency ranges changed: ad, containers, lens
Files
- Ipopt.hs +3/−7
- Ipopt/AnyRF.hs +7/−1
- Ipopt/NLP.hs +22/−12
- Ipopt/Options.hs +347/−0
- Ipopt/PP.hs +5/−5
- Ipopt/Raw.chs +29/−20
- Nlopt/NLP.hs +52/−0
- Nlopt/Raw.chs +366/−0
- examples/AllTests.hs +35/−17
- ipopt-hs.cabal +28/−18
Ipopt.hs view
@@ -5,7 +5,7 @@ module Ipopt ( -- * high-level -- ** variables- var', var, varFresh,+ var', var, varFresh', varFresh, AnyRF(..), Identity(..), -- ** functions addG, addF,@@ -15,10 +15,7 @@ module Control.Monad.State, solveNLP', -- *** solver options- -- $solverOptRef- addIpoptNumOption,- addIpoptStrOption, - addIpoptIntOption,+ ipopts, setIpoptProblemScaling, openIpoptOutputFile, @@ -30,11 +27,10 @@ ) where import Ipopt.PP+import Ipopt.Options import Ipopt.NLP import Ipopt.Raw import Ipopt.AnyRF import Control.Monad.State import Control.Monad.Identity (Identity(..)) --- $solverOptRef--- see <http://www.coin-or.org/Ipopt/documentation/node39.html ipopt's options reference>
Ipopt/AnyRF.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ConstraintKinds, RankNTypes, TypeFamilies, FlexibleInstances #-} {- | Description: representing functions that can be differentiated The 'AnyRF' wrapper holds functions that can be used@@ -32,7 +33,8 @@ data AnyRF cb = AnyRF (forall a. AnyRFCxt a => Vector a -> cb a) -- | RealFloat gives most numerical operations,--- 'VectorSpace' is involved to allow using definitions from the splines package+-- 'VectorSpace' is involved to allow using definitions from the+-- <http://hackage.haskell.org/package/splines splines> package type AnyRFCxt a = (RealFloat a, VectorSpace a, Scalar a ~ a) -- *** helpers for defining instances@@ -118,6 +120,10 @@ negateV = negate -- * orphan instances ++-- $orphans+-- these belong somewhere between the @ad@ package and @vector-space@+ instance (Num a, AD.Mode f) => VectorSpace.AdditiveGroup (AD.AD f a) where zeroV = AD.zero (^+^) = (AD.<+>)
Ipopt/NLP.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE TemplateHaskell #-} -- | Description : a EDSL for describing nonlinear programs ----- see usage in @examples/Test3.hs@+-- see usage in @examples/Test3.hs@ (and other examples) -- -- IPOPT does support naming variables if you use c++ -- (by overriding a @virtual void finalize_metadata@), but@@ -47,18 +47,25 @@ data NLPState = NLPState { -- | current maximum index _nMax :: Ix,- -- | what namespace (see 'inEnv')+ -- | what namespace are we currently in (see 'inEnv') _currentEnv :: [String],+ -- | fully qualified (see 'inEnv') name _variables :: M.Map String Ix,- _variablesInv :: IxMap String, -- invert variables map+ -- | invert _variables+ _variablesInv :: IxMap String, -- | human-readable descriptions for the constraint, objective and -- variables _constraintLabels, _objLabels :: IntMap String, _varLabels :: IxMap String,+ -- | in what environments is a given var used? _varEnv :: IxMap (S.Set [String]), _constraintEnv, _objEnv :: IntMap [String], _nlpfun :: NLPFun,+ -- | the default @(xL,xU)@ for @xL < x < xU@ _defaultBounds :: (Double,Double),+ -- | for nlopt (lower/upper)+ _defaultConstraintTol :: (Double,Double),+ _constraintTol :: Seq (Double,Double), -- | inital state variable for the solver _initX :: Vector Double } deriving (Show)@@ -78,7 +85,9 @@ mempty mempty mempty mempty -- env (mempty :: NLPFun)- (-1/0, 1/0)+ (-1/0, 1/0) -- bounds at infinity+ (1e-6,1e-6) -- arbitrary constraint tol+ mempty V.empty type NLPT = StateT NLPState@@ -125,9 +134,8 @@ p <- liftIO (createIpoptProblemAD xl xu gl gu (F.sum . fs) (V.fromList . toList . gs)) liftIO (setOpts p)- x0 <- uses initX (V.convert . V.map CDouble)+ x0 <- uses initX V.convert r <- liftIO (ipoptSolve p =<< VS.thaw x0)- liftIO $ freeIpoptProblem p return r -- | add a constraint@@ -141,6 +149,7 @@ nlpfun . funG %= \(AnyRF fs) -> AnyRF $ \x -> fs x Seq.|> runIdentity (f x) n <- use (nlpfun . boundG . to Seq.length) copyEnv constraintEnv n+ join $ uses defaultConstraintTol $ \t -> constraintTol %= (<> Seq.singleton t) addDesc constraintLabels d n {- | add a piece of the objective function, which is added in the form@@ -195,7 +204,7 @@ F.traverse_ (narrowBounds n) bs return n --- | a combination of 'var'' and from'Ix'+-- | a combination of 'var'' and 'ixToVar' var bs s = ixToVar <$> var' bs Nothing s {- | 'var', except this causes the solver to get a new variable,@@ -205,20 +214,21 @@ and the different letters can take different values (between 0 and 10) in the optimal solution (depending on what you do with @a@ and similar-in the objective function).+in the objective function and other constraints). -} varFresh' :: (Monad m, Functor m) => Maybe (Double,Double) -> String -> NLPT m Ix varFresh' bs s = do existing <- gets (^? variables . ix s) case existing of- Just a -> return a- Nothing -> do+ Just _ -> do m <- use variables let n = M.size m + 1 -- get the first of "x", "x1", "x1_", "x1__", "x1___" Just sUniq <- return $ find (`M.notMember` m) $ s : iterate (++"_") (s ++ show n) var' bs Nothing sUniq+ Nothing -> var' bs Nothing s +-- | see 'varFresh'' varFresh bs s = fmap ixToVar $ varFresh' bs s -- *** namespace@@ -302,6 +312,6 @@ -- * internal seqToVecs :: MonadIO m => Seq (Double,Double) -> m (Vec,Vec) seqToVecs x = let (a,b) = unzip (toList x) in liftIO $ do- a' <- VS.thaw (VS.map CDouble (VS.fromList a))- b' <- VS.thaw (VS.map CDouble (VS.fromList b))+ a' <- VS.thaw (VS.fromList a)+ b' <- VS.thaw (VS.fromList b) return (a',b')
+ Ipopt/Options.hs view
@@ -0,0 +1,347 @@+{-# LANGUAGE TemplateHaskell #-}+-- | Description: a quasiquote for the solver's options+module Ipopt.Options where++import Text.ParserCombinators.UU+import Text.ParserCombinators.UU.Utils+import Text.ParserCombinators.UU.BasicInstances hiding (Parser)++import Ipopt.Raw+import Language.Haskell.TH.Quote+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import Control.Monad+import Data.Char+import qualified Data.Map as M++{- | an expression-only quasiquote intended to be the second argument for+'Ipopt.NLP.solveNLP'' (so @solveNLP [ipopts| tol = 1e-3 |]@). This is a shortcut+for calling 'addIpoptNumOption' 'addIpoptStrOption' or 'addIpoptIntOption'. ++Refer to <http://www.coin-or.org/Ipopt/documentation/node39.html ipopt's options reference>,+the syntax is like @option_name = value;option2 = value2@. The semicolons are optional and+whitespace alone can separate the option name from the value. A few examples of the parser:++>>> :set -XQuasiQuotes+>>> let f = [ipopts| tol = 1e-3; print_level = 0 |]+>>> :t f+f :: IpProblem -> IO ()++>>> let p x = uuParseTest parseOpts x+>>> p "tol = 3"+([("tol",ANum 3.0)],[])++>>> p "tol = 3 tol = 4" -- the last one wins. No warnings done (yet).+([("tol",ANum 3.0),("tol",ANum 4.0)],[])++>>> p "tol = 3\n\ntol = 4"+([("tol",ANum 3.0),("tol",ANum 4.0)],[])++>>> p "acceptable_iter = 25; output_file = foobar" -- quotation marks optional+([("acceptable_iter",AInt 25),("output_file",AStr "foobar")],[])++>>> p "output_file = \"foo bar\"" -- but needed here+([("output_file",AStr "foo bar")],[])++>>> putStrLn $ (++"...") $ take 100 $ show $ p "atol = 1.8" -- typo gets corrected+([("tol",ANum 1.8)],[-- Deleted 'a' at position LineColPos 0 0 0 expecting one of [Whitespace, ...++>>> p "tol = $xY" -- interpolating haskell variables+([("tol",AVar OptionNum "xY")],[])++-}+ipopts :: QuasiQuoter+ipopts = QuasiQuoter { quoteExp = \s -> do+ Loc _filename _pkg _mod (lStart,cStart) (lEnd,cEnd) <- location+ let (settings, errs) = parse ((,) <$> parseOpts <*> pEnd)+ (createStr (LineColPos 0 lStart cStart) s)+ unless (null errs) $ reportWarning (unlines (map show errs))+ [| \c -> $( foldr+ (\(n,v) next -> [| do $(addIpoptOpt 'c n v); $next |])+ [| return () |]+ settings)+ |],+ quotePat = error "ipopts",+ quoteDec = error "ipopts",+ quoteType = error "ipopts"+ }++uuParseTest p x = parse ((,) <$> p <*> pEnd)+ (createStr (LineColPos 0 0 0) x)++addIpoptOpt :: Name -> String -> OptionVal -> ExpQ+addIpoptOpt c n (AStr s) = [| addIpoptStrOption $(varE c) n s |]+addIpoptOpt c n (AInt i) = [| addIpoptIntOption $(varE c) n (i :: Int) |]+addIpoptOpt c n (ANum i) = [| addIpoptNumOption $(varE c) n $(liftDouble i) |]+addIpoptOpt c n (AVar OptionNum x) = [| addIpoptNumOption $(varE c) n ($(dyn x)::Double) |]+addIpoptOpt c n (AVar OptionInt x) = [| addIpoptIntOption $(varE c) n ($(dyn x)::Int) |]+addIpoptOpt c n (AVar OptionBool x) = [| addIpoptStrOption $(varE c) n+ (if $(dyn x) then "yes" else "no") |]+addIpoptOpt c n (AVar OptionStr x) = [| addIpoptStrOption $(varE c) n $(dyn x) |]++-- | what 'lift' should do for Double+liftDouble :: Double -> ExpQ+liftDouble n | isNaN n = [| 0/0 :: Double |]+ | isInfinite n, n > 0 = [| 1/0 :: Double |]+ | isInfinite n, n < 0 = [| - 1 / 0 :: Double |]+ | otherwise = [| $(litE (rationalL (toRational n))) :: Double |]++parseOpts = pSpaces *> pListSep (optional (pSymbol ";") *> pSpaces) (parseOpt <* pSpaces)++parseOpt =+ pAny (\(a,b) -> (,) <$>+ pSymbol a <*+ pSymbol "=" <*>+ (parseVar b <<|> parseLit b ))+ (M.toList ipoptOptions)+ where+ parseVar b = AVar b <$> (pSym '$' *> hsIdent)++ -- [_a-z][A-Za-z_']*+ hsIdent = (:) <$> (pRange ('a','z') <|> pSym '_')+ <*> pMany (pRange ('A','Z') <|>+ pRange ('a','z') <|>+ pSym '_' <|>+ pSym '\'')+ parseLit b = case b of+ OptionNum -> ANum <$> pDouble+ OptionBool -> AStr <$> pAny pSymbol ["yes","no"]+ OptionStr -> AStr <$> (strLit <<|> pMany notSpaceOrSemicolonAscii)+ OptionInt -> AInt <$> pInteger++ notSpaceOrSemicolonAscii = pRange ('!',':') <|> pRange ('<','~')+ + strLit = pSym '"' *>+ pMany+ (pSatisfy (/= '"')+ (Insertion "\\\"" '"' 0))+ <* pSym '"'++data OptionVal = ANum Double | AStr String | AInt Int+ | AVar OptionType String -- ^ @$x@+ deriving (Show)+data OptionType = OptionNum+ | OptionStr+ | OptionInt+ | OptionBool -- ^ actually string yes or string no+ deriving (Show,Eq)++-- | a list of all the options in+-- <http://www.coin-or.org/Ipopt/documentation/node39.html>+ipoptOptions :: M.Map String OptionType+ipoptOptions = M.fromList [+ ("print_level", OptionInt),+ ("print_user_options", OptionBool),+ ("print_options_documentation", OptionBool),+ ("print_frequency_iter", OptionInt),+ ("print_frequency_time", OptionNum),+ ("output_file", OptionStr),+ ("file_print_level", OptionInt),+ ("option_file_name", OptionStr),+ ("print_info_string", OptionBool),+ ("inf_pr_output", OptionStr),+ ("print_timing_statistics" , OptionBool),+ -- tolerances+ ("tol", OptionNum),+ ("max_iter", OptionInt),+ ("max_cpu_time", OptionNum),+ ("dual_inf_tol", OptionNum),+ ("constr_viol_tol", OptionNum),+ ("compl_inf_tol", OptionNum),+ ("acceptable_tol", OptionNum),+ ("acceptable_iter", OptionInt),+ ("acceptable_constr_viol_tol", OptionNum),+ ("acceptable_dual_inf_tol", OptionNum),+ ("acceptable_compl_inf_tol", OptionNum),+ ("acceptable_obj_change_tol", OptionNum),+ ("diverging_iterates_tol", OptionNum),++ -- scaling+ ("obj_scaling_factor", OptionNum),+ ("nlp_scaling_method", OptionStr),+ ("nlp_scaling_max_gradient", OptionNum),+ ("nlp_scaling_min_value", OptionNum),++ -- NLP+ ("bound_relax_factor", OptionNum),+ ("honor_original_bounds", OptionBool),+ ("check_derivatives_for_naninf", OptionBool),+ ("nlp_lower_bound_inf", OptionNum),+ ("nlp_upper_bound_inf", OptionNum),+ ("fixed_variable_treatment", OptionStr),+ ("jac_c_constant", OptionBool),+ ("jac_d_constant", OptionBool),+ ("hessian_constant", OptionBool),+++ -- initialization+ ("bound_frac", OptionNum),+ ("bound_push", OptionNum),+ ("slack_bound_frac", OptionNum),+ ("slack_bound_push", OptionNum),+ ("bound_mult_init_val", OptionNum),+ ("constr_mult_init_max", OptionNum),+ ("bound_mult_init_method", OptionStr),++ -- barrier parameter+ ("mehrotra_algorithm", OptionBool),+ ("mu_strategy", OptionStr),+ ("mu_oracle", OptionStr),+ ("quality_function_max_section_steps", OptionInt),+ ("fixed_mu_oracle", OptionStr),+ ("adaptive_mu_globalization", OptionStr),+ ("mu_init", OptionNum),+ ("mu_max_fact", OptionNum),+ ("mu_max", OptionNum),+ ("mu_min", OptionNum),+ ("mu_target", OptionNum),+ ("barrier_tol_factor", OptionNum),+ ("mu_linear_decrease_factor", OptionNum),+ ("mu_superlinear_decrease_power", OptionNum),+++ -- multiplier updates+ ("alpha_for_y", OptionStr),+ ("alpha_for_y_tol", OptionNum),+ ("recalc_y", OptionBool),+ ("recalc_y_feas_tol", OptionNum),++ -- line search+ ("max_soc", OptionInt),+ ("watchdog_shortened_iter_trigger", OptionInt),+ ("watchdog_trial_iter_max", OptionInt),+ ("accept_every_trial_step", OptionBool),+ ("corrector_type", OptionStr),++ -- warm start+ ("warm_start_init_point", OptionBool),+ ("warm_start_bound_push", OptionNum),+ ("warm_start_bound_frac", OptionNum),+ ("warm_start_slack_bound_frac", OptionNum),+ ("warm_start_slack_bound_push", OptionNum),+ ("warm_start_mult_bound_push", OptionNum),+ ("warm_start_mult_init_max", OptionNum),++ -- restoration phase+ ("expect_infeasible_problem", OptionBool),+ ("expect_infeasible_problem_ctol", OptionNum),+ ("expect_infeasible_problem_ytol", OptionNum),+ ("start_with_resto", OptionBool),+ ("soft_resto_pderror_reduction_factor", OptionNum),+ ("required_infeasibility_reduction", OptionNum),+ ("bound_mult_reset_threshold", OptionNum),+ ("constr_mult_reset_threshold", OptionNum),+ ("evaluate_orig_obj_at_resto_trial", OptionBool),++ -- linear solver+ ("linear_solver", OptionStr),+ ("linear_system_scaling", OptionStr),+ ("linear_scaling_on_demand", OptionBool),+ ("max_refinement_steps", OptionInt),+ ("min_refinement_steps", OptionInt),++ -- hessian perturbation+ ("max_hessian_perturbation", OptionNum),+ ("min_hessian_perturbation", OptionNum),+ ("first_hessian_perturbation", OptionNum),+ ("perturb_inc_fact_first", OptionNum),+ ("perturb_inc_fact", OptionNum),+ ("perturb_dec_fact", OptionNum),+ ("jacobian_regularization_value", OptionNum),++ -- quasi newton+ ("hessian_approximation", OptionStr),+ ("limited_memory_update_type", OptionStr),+ ("limited_memory_max_history", OptionInt),+ ("limited_memory_max_skipping", OptionInt),+ ("limited_memory_initialization", OptionStr),+ ("limited_memory_init_val", OptionNum),+ ("limited_memory_init_val_max", OptionNum),+ ("limited_memory_init_val_min", OptionNum),+ ("limited_memory_special_for_resto", OptionBool),++ -- derivative test+ ("derivative_test", OptionStr),+ ("derivative_test_perturbation", OptionNum),+ ("derivative_test_tol", OptionNum),+ ("derivative_test_print_all", OptionBool),+ ("derivative_test_first_index", OptionInt),+ ("point_perturbation_radius", OptionNum),++ -- ma27+ ("ma27_pivtol", OptionNum),+ ("ma27_pivtolmax", OptionNum),+ ("ma27_liw_init_factor", OptionNum),+ ("ma27_la_init_factor", OptionNum),+ ("ma27_meminc_factor", OptionNum),++ -- ma57+ ("ma57_pivtol", OptionNum),+ ("ma57_pivtolmax", OptionNum),+ ("ma57_pre_alloc", OptionNum),+ ("ma57_pivot_order", OptionInt),+ ("ma57_automatic_scaling", OptionBool),+ ("ma57_block_size", OptionInt),+ ("ma57_node_amalgamation", OptionInt),+ ("ma57_small_pivot_flag", OptionInt),++ -- ma77+ ("ma77_print_level", OptionInt),+ ("ma77_buffer_lpage", OptionInt),+ ("ma77_buffer_npage", OptionInt),+ ("ma77_file_size", OptionInt),+ ("ma77_maxstore", OptionInt),+ ("ma77_nemin", OptionInt),+ ("ma77_order", OptionStr),+ ("ma77_small", OptionNum),+ ("ma77_static", OptionNum),+ ("ma77_u", OptionNum),+ ("ma77_umax", OptionNum),++ -- ma86+ ("ma86_print_level", OptionInt),+ ("ma86_nemin", OptionInt),+ ("ma86_order", OptionStr),+ ("ma86_scaling", OptionStr),+ ("ma86_small", OptionNum),+ ("ma86_static", OptionNum),+ ("ma86_u", OptionNum),+ ("ma86_umax", OptionNum),++ -- ma97+ ("ma97_print_level", OptionInt),+ ("ma97_nemin", OptionInt),+ ("ma97_order", OptionStr),+ ("ma97_scaling", OptionStr),+ ("ma97_scaling1", OptionStr),+ ("ma97_scaling2", OptionStr),+ ("ma97_scaling3", OptionStr),+ ("ma97_small", OptionNum),+ ("ma97_solve_blas3", OptionBool),+ ("ma97_switch1", OptionStr),+ ("ma97_switch2", OptionStr),+ ("ma97_switch3", OptionStr),+ ("ma97_u", OptionNum),+ ("ma97_umax", OptionNum),++ -- mumps+ ("mumps_pivtol", OptionNum),+ ("mumps_pivtolmax", OptionNum),+ ("mumps_mem_percent", OptionInt),+ ("mumps_permuting_scaling", OptionInt),+ ("mumps_pivot_order", OptionInt),+ ("mumps_scaling", OptionInt),++ -- paradiso+ ("pardiso_matching_strategy", OptionStr),+ ("pardiso_max_iterative_refinement_steps", OptionInt),+ ("pardiso_msglvl", OptionInt),+ ("pardiso_order", OptionStr),++ -- wsmp+ ("wsmp_num_threads", OptionInt),+ ("wsmp_ordering_option", OptionInt),+ ("wsmp_pivtol", OptionNum),+ ("wsmp_pivtolmax", OptionNum),+ ("wsmp_scaling", OptionInt),+ ("wsmp_singularity_threshold:", OptionNum)]
Ipopt/PP.hs view
@@ -11,6 +11,7 @@ import Text.Printf import qualified Data.IntMap as IM import qualified Data.Vector.Storable as VS+import qualified Data.Vector.Generic as VG import Data.Vector (Vector) import qualified Data.Vector as V import Control.Monad.State@@ -24,8 +25,6 @@ makeLensesWith (lensRules & lensField .~ stripPrefix "_ipOptSolved_") ''IpOptSolved -- * pretty printing-ppSoln :: (MonadIO m, Functor m) =>- NLPState -> NLPT m (IpOptSolved Vector) -> m (IpOptSolved Vector, Doc) ppSoln state0 problem = flip evalStateT state0 $ runWriterT $ do s <- lift problem st <- get@@ -34,16 +33,17 @@ br tell $ "obj_tot" <> double (s^.objective) join $ uses (nlpfun . funF) $ \(AnyRF f) -> case sortBy (comparing fst) $- toList (f (s^.x)) `zip` [1 .. ] of+ toList (f (s^.x&VG.convert)) `zip` [1 .. ] of [_] -> return () [] -> return () xs -> for_ xs $ \(x,i) -> tell $ "obj" <> int i <> colon <$> double x for_ (st ^. variablesInv . from ixMap . to IM.toList) $ \(k,desc) -> do br- tell $ string desc <> "(" <> int k <> ")" <> "=" <> string (printf "%.3g" (s ^?! x . ix k))+ tell $ string desc <> "(" <> int k <> ")" <> "=" <>+ string (printf "%.3g" (s ^?! x . ix k)) br- tell $ "g" <$> foldMap (\e -> mempty <$$> double e) (s ^. g)+ tell $ "g" <$> foldMap (\e -> mempty <$$> double e) (s ^. g & VG.convert :: V.Vector Double) return s
Ipopt/Raw.chs view
@@ -104,7 +104,8 @@ {#enum AlgorithmMode as ^ {underscoreToCase} deriving (Show) #} -newtype IpProblem = IpProblem { unIpProblem :: Ptr ()}+{#pointer IpoptProblem as IpProblem foreign newtype #}+ipp x = withIpProblem x type family UnFunPtr a type instance UnFunPtr (FunPtr a) = a@@ -163,15 +164,21 @@ wrapIpH fSparsity fEval = wrapIpH1 (wrapIpH2 fSparsity fEval) -vmUnsafeWith = VM.unsafeWith+vmUnsafeWith :: Vec -> (Ptr CDouble -> IO r) -> IO r+vmUnsafeWith v f = VM.unsafeWith v (f . castPtr) -- | Vector of numbers-type Vec = VM.IOVector IpNumber+type Vec = VM.IOVector Double +-- depend on CDouble being just a newtype on Double which+-- is the same as the IpNumber defined in the ipopt header, so this+-- should cause a compile failure if that's not the case...+_ = CDouble (5 :: Double) :: IpNumber+ fromVec :: VG.Vector v Double => Vec -> IO (v Double) fromVec mv = do v <- VS.freeze mv - return (VG.convert (VS.map (\(CDouble a) -> a) v))+ return (VG.convert v) createIpoptProblem :: Vec -> Vec -> Vec -> Vec@@ -180,31 +187,33 @@ | lx <- VM.length xL, lx == VM.length xU, lg <- VM.length gL,- lg == VM.length gU = createIpoptProblem3 lx xL xU lg gL gU nJac nHess 0 f g gradF jacG hess+ lg == VM.length gU = do+ p <- createIpoptProblem3 lx xL xU lg gL gU nJac nHess 0 f g gradF jacG hess+ p' <- newForeignPtr freeIpoptProblem (castPtr p)+ return (IpProblem (castForeignPtr p')) | otherwise = error "dimensions wrong!" + {#fun CreateIpoptProblem as createIpoptProblem3 { `Int', vmUnsafeWith* `Vec', vmUnsafeWith* `Vec', `Int', vmUnsafeWith* `Vec', vmUnsafeWith* `Vec', `Int', `Int', `Int', id `IpF', id `IpG', id `IpGradF',- id `IpJacG', id `IpH' } -> `IpProblem' IpProblem #}-_ = {#fun AddIpoptNumOption as ^- { unIpProblem `IpProblem', `String', `Double' } -> `Bool' #}+ id `IpJacG', id `IpH' } -> `Ptr IpProblem' id #} -_ = {#fun AddIpoptStrOption as ^- { unIpProblem `IpProblem', `String', `String' } -> `Bool' #}+{#fun AddIpoptNumOption as ^ { ipp* `IpProblem', `String', `Double' } -> `Bool' #} -_ = {#fun AddIpoptIntOption as ^- { unIpProblem `IpProblem', `String', `Int' } -> `Bool' #}+{#fun AddIpoptStrOption as ^ { ipp* `IpProblem', `String', `String' } -> `Bool' #} -_ = {#fun FreeIpoptProblem as ^- { unIpProblem `IpProblem' } -> `()' #}+{#fun AddIpoptIntOption as ^ { ipp* `IpProblem', `String', `Int' } -> `Bool' #} -_ = {#fun OpenIpoptOutputFile as ^- { unIpProblem `IpProblem', `String', `Int' } -> `Bool' #}+foreign import ccall unsafe "&FreeIpoptProblem"+ freeIpoptProblem :: FunPtr (Ptr () -> IO ())+-- {#fun FreeIpoptProblem as ^ { ipp* `IpProblem' } -> `()' #} -_ = {#fun SetIpoptProblemScaling as ^- { unIpProblem `IpProblem',+{#fun OpenIpoptOutputFile as ^ { ipp* `IpProblem', `String', `Int' } -> `Bool' #}++{#fun SetIpoptProblemScaling as ^+ { ipp* `IpProblem', `Double', vmUnsafeWith* `Vec', vmUnsafeWith* `Vec'@@ -253,8 +262,8 @@ mult_x_L' mult_x_U' -_ = {#fun IpoptSolve as ipoptSolve2- { unIpProblem `IpProblem',+{#fun IpoptSolve as ipoptSolve2+ { ipp* `IpProblem', vmUnsafeWith* `Vec', vmUnsafeWith* `Vec', alloca- `Double' peekFloatConv*,
+ Nlopt/NLP.hs view
@@ -0,0 +1,52 @@+module Nlopt.NLP where++import Nlopt.Raw+import Ipopt.NLP+import Ipopt.AnyRF+import qualified Data.Sequence as Seq+import qualified Data.Vector.Generic as VG+import qualified Data.Vector.Storable as VS+import qualified Data.Vector.Storable.Mutable as VM+import qualified Data.Vector as V+import Control.Monad+import Control.Monad.State+import Control.Lens+import Foreign.C+import Control.Monad.Trans+import qualified Data.Foldable as F+import Control.Lens++solveNlopt :: (VG.Vector v Double, MonadIO m)+ => NloptAlgorithm+ -> (NLOpt -> IO t) -- ^ set additional options+ -> NLPT m (v Double, Double, NloptResult) -- ^ @x,objective,exitCode@+solveNlopt alg moreOpts = do+ (xl,xu) <- join $ uses (nlpfun . boundX) seqToVecs+ gSeq <- use (nlpfun . boundG)+ let ng = Seq.length gSeq++ AnyRF fs <- use (nlpfun . funF)+ AnyRF gs <- use (nlpfun . funG)++ m <- liftIO . nloptCreate alg . (+1) =<< use (nMax . varIx)++ x0 <- join $ uses initX (liftIO . VS.thaw . VG.convert)++ gTol <- liftIO . VS.thaw . VS.fromList+ =<< uses constraintTol (F.concatMap (\(a,b) -> [a,b]))+ + (status,obj) <- liftIO $ do+ nloptSetMinObjective m (toFuncAD (F.sum . fs))+ nloptSetLowerBounds m xl+ nloptSetUpperBounds m xu++ let toLE :: (AnyRFCxt a) => Seq.Seq a -> V.Vector a+ toLE xs = V.fromList $ concatMap (\(x,(l,u)) -> [realToFrac l-x,x- realToFrac u])+ (F.toList xs `zip` F.toList gSeq)+ -- XXX drop constraints with bounds more than 1e20 or so? as ipopt does+ nloptAddInequalityMconstraint m (2*ng) (toFuncMAD (toLE . gs)) gTol+ moreOpts m+ nloptOptimize m x0++ x <- liftIO (VS.freeze x0)+ return (VG.convert x, obj, status)
+ Nlopt/Raw.chs view
@@ -0,0 +1,366 @@+{-# LANGUAGE TypeFamilies,DeriveDataTypeable, RankNTypes, ConstraintKinds, FlexibleContexts #-}+module Nlopt.Raw where++import Ipopt.AnyRF++import Foreign.C.Types+import Foreign.Ptr+import Foreign.Marshal+import Foreign.Storable+import Data.Int+import C2HS++import qualified Data.Vector.Storable.Mutable as VM+import qualified Data.Vector as V+import qualified Data.Vector.Storable as VS+import qualified Data.Vector.Generic as VG++import Control.Exception+import Data.Typeable+import Numeric.AD (grad, jacobian, hessian)+import Control.Monad++#include "nlopt.h"++-- * converting haskell functions++{- $conventions++NLOpt has three different types for functions 'FunPtrFunc' 'FunPtrMFunc' and 'FunPtrPrecond'.++[@AD@] means derivatives are calculated, and the haskell function does no IO.++[@G@] mean you are providing the derivatives++[@M@] means m functions are calculated at a time++-}++-- | an exact hessian calculated with AD. See 'toPrecondG'+-- XXX BFGS approx could also be done...+toPrecondAD :: (forall a. AnyRFCxt a => V.Vector a -> a) -> Precond+toPrecondAD f n xs vs r _usrData =+ toPrecondG (\x v -> return (hessian f x `mXv` v)) n xs vs r _usrData++-- | see <http://ab-initio.mit.edu/wiki/index.php/NLopt_Reference#Preconditioning_with_approximate_Hessians>+-- only applies to 'NLOPT_LD_CCSAQ'+toPrecondG :: (VG.Vector vec Double, v ~ vec Double)+ => (v -> v -> IO v) -- ^ given @x,v@ calculate @H(x)v@ where H the hessian+ -> Precond+toPrecondG f n xs vs r _usrData = do+ xs' <- ptrToV n xs+ vs' <- ptrToV n vs+ copyInto n r =<< f xs' vs'++toFuncM :: VG.Vector v Double => (v Double -> IO (v Double) ) -> MFunc+toFuncM f m r n xs _g _usrData = do+ copyInto m r =<< f =<< ptrToV n xs++-- | @n@ and @m@ type variables indicate the vector size as+-- number of inputs and number of outputs respectively+toFuncMG :: (VG.Vector n Double, VG.Vector n (m Double), n ~ m)+ => (n Double -> IO (m Double) ) -- @f@+ -> (n Double -> IO (n (m Double))) -- @grad f@+ -> MFunc+toFuncMG f g m r n xs g' _usrData = do+ xs' <- ptrToV n xs+ copyInto m r =<< f xs'+ -- probably should do this better...+ copyInto (n*m) g' . VG.concat . VG.toList =<< g xs'++toFuncMAD :: (forall a. AnyRFCxt a => V.Vector a -> V.Vector a) -> MFunc+toFuncMAD f m r n xs g _usrData = do+ xs' <- ptrToV n xs+ copyInto m r (f xs')+ -- grad[i*n + j] should be satisfied...+ copyInto (n*m) g (V.concat (V.toList (jacobian f xs')))++toFunc :: (VG.Vector v Double) => (v Double -> IO Double) -> Func+toFunc f n xs _g _usrData = fmap CDouble $ f =<< ptrToV n xs++-- | where the gradient happens via AD+toFuncAD :: (forall a. AnyRFCxt a => V.Vector a -> a) -> Func+toFuncAD f n xs g _usrData = do+ xs' <- ptrToV n xs+ copyInto n g (grad f xs')+ return (CDouble (f xs'))++toFuncG :: (VG.Vector v Double) => (v Double -> IO Double) -- ^ @f@+ -> (v Double -> IO (v Double)) -- ^ @grad(f)@+ -> Func+toFuncG f g n xs g' _usrData = do+ xs' <- ptrToV n xs+ copyInto n g' =<< g xs'+ CDouble `fmap` f xs'++type family UnFunPtr a+type instance UnFunPtr (FunPtr a) = a++type Func = UnFunPtr FunPtrFunc+type MFunc = UnFunPtr FunPtrMFunc+type Precond = UnFunPtr FunPtrPrecond++type FunPtrFunc = {# type nlopt_func #}+type FunPtrMFunc = {# type nlopt_mfunc #}+type FunPtrPrecond = {# type nlopt_precond #}++{#pointer *nlopt_opt as NLOpt foreign newtype #}+{#enum nlopt_algorithm as ^ {} deriving (Show,Bounded,Ord,Eq) #}++-- | negative (above NLOPT_SUCCESS) values of these are thrown as exceptions. The positive ones are+-- return values.+{#enum nlopt_result as ^ {} deriving (Show,Typeable) #}++instance Exception NloptResult++checkEC :: CInt -> IO NloptResult+checkEC n | n < 0 = throwIO e+ | otherwise = return e+ where e = fromCInt n :: NloptResult++{#fun nlopt_srand as ^ { `Int' } -> `()' #}+{#fun nlopt_srand_time as ^ { } -> `()' #}+{#fun nlopt_version as ^ {+ alloca- `Int' peekInt*,+ alloca- `Int' peekInt*,+ alloca- `Int' peekInt*} -> `()' #}+{#fun nlopt_create as ^ { toCInt `NloptAlgorithm', `Int' } -> `NLOpt' ptrToNLOpt * #}+{#fun nlopt_copy as ^ { withNLOpt_* `NLOpt' } -> `NLOpt' ptrToNLOpt * #}++-- | should not need to be called manually+{#fun nlopt_destroy as ^ { id `Ptr ()' } -> `()' #}++{#fun nlopt_optimize as ^ {+ withNLOpt_* `NLOpt', vmUnsafeWith* `Vec', alloca- `Double' peekDouble* }+ -> `NloptResult' checkEC* #}++{#fun nlopt_set_min_objective as ^ {+ withNLOpt_* `NLOpt', withFunc* `Func', withNull- `()' }+ -> `NloptResult' checkEC* #}+{#fun nlopt_set_max_objective as ^ {+ withNLOpt_* `NLOpt', withFunc* `Func', withNull- `()' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_set_precond_min_objective as ^ {+ withNLOpt_* `NLOpt',+ withFunc* `Func',+ withPrecond* `Precond',+ withNull- `()' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_set_precond_max_objective as ^ {+ withNLOpt_* `NLOpt',+ withFunc* `Func',+ withPrecond* `Precond',+ withNull- `()' } -> `NloptResult' checkEC* #}++{#fun nlopt_get_algorithm as ^ { withNLOpt_* `NLOpt' } -> `NloptAlgorithm' fromCInt #}+{#fun nlopt_get_dimension as ^ { withNLOpt_* `NLOpt' } -> `Int' #}++-- * constraints+{#fun nlopt_set_lower_bounds as ^ { withNLOpt_* `NLOpt', vmUnsafeWith* `Vec' }+ -> `NloptResult' checkEC* #}+{#fun nlopt_set_upper_bounds as ^ { withNLOpt_* `NLOpt', vmUnsafeWith* `Vec' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_get_lower_bounds as ^ { withNLOpt_* `NLOpt', vmUnsafeWith* `Vec' }+ -> `NloptResult' checkEC* #}+{#fun nlopt_get_upper_bounds as ^ { withNLOpt_* `NLOpt', vmUnsafeWith* `Vec' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_set_lower_bounds1 as ^ { withNLOpt_* `NLOpt', `Double' }+ -> `NloptResult' checkEC* #}+{#fun nlopt_set_upper_bounds1 as ^ { withNLOpt_* `NLOpt', `Double' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_remove_inequality_constraints as ^ { withNLOpt_* `NLOpt' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_add_inequality_constraint as ^+ { withNLOpt_* `NLOpt',+ withFunc* `Func',+ withNull- `()',+ `Double' } -> `NloptResult' checkEC* #}++{#fun nlopt_add_precond_inequality_constraint as ^+ { withNLOpt_* `NLOpt',+ withFunc* `Func',+ withPrecond* `Precond',+ withNull- `()',+ `Double' } -> `NloptResult' checkEC* #}++{#fun nlopt_add_inequality_mconstraint as ^+ { withNLOpt_* `NLOpt',+ `Int',+ withMFunc* `MFunc',+ withNull- `()',+ vmUnsafeWith* `Vec' } -> `NloptResult' checkEC* #}++{#fun nlopt_remove_equality_constraints as ^ { withNLOpt_* `NLOpt' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_add_equality_constraint as ^+ { withNLOpt_* `NLOpt',+ withFunc* `Func',+ withNull- `()',+ `Double' } -> `NloptResult' checkEC* #}++{#fun nlopt_add_precond_equality_constraint as ^+ { withNLOpt_* `NLOpt',+ withFunc* `Func',+ withPrecond* `Precond',+ withNull- `()',+ `Double' } -> `NloptResult' checkEC* #}++{#fun nlopt_add_equality_mconstraint as ^+ { withNLOpt_* `NLOpt',+ `Int',+ withMFunc* `MFunc',+ withNull- `()',+ vmUnsafeWith* `Vec' } -> `NloptResult' checkEC* #}++-- * stopping criteria+{#fun nlopt_set_stopval as ^ { withNLOpt_* `NLOpt', `Double' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_get_stopval as ^ { withNLOpt_* `NLOpt' } -> `Double' #}++{#fun nlopt_set_ftol_rel as ^ { withNLOpt_* `NLOpt', `Double' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_get_ftol_rel as ^ { withNLOpt_* `NLOpt' } -> `Double' #}++{#fun nlopt_set_ftol_abs as ^ { withNLOpt_* `NLOpt', `Double' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_get_ftol_abs as ^ { withNLOpt_* `NLOpt' } -> `Double' #}++{#fun nlopt_set_xtol_rel as ^ { withNLOpt_* `NLOpt', `Double' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_get_xtol_rel as ^ { withNLOpt_* `NLOpt' } -> `Double' #}++{#fun nlopt_set_xtol_abs1 as ^ { withNLOpt_* `NLOpt', `Double' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_set_xtol_abs as ^ { withNLOpt_* `NLOpt', vmUnsafeWith* `Vec' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_get_xtol_abs as ^ { withNLOpt_* `NLOpt', vmUnsafeWith* `Vec' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_set_maxeval as ^ { withNLOpt_* `NLOpt', `Int' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_get_maxeval as ^ { withNLOpt_* `NLOpt' } -> `Int' #}++{#fun nlopt_set_maxtime as ^ { withNLOpt_* `NLOpt', `Double' }+ -> `NloptResult' checkEC* #}++{#fun nlopt_get_maxtime as ^ { withNLOpt_* `NLOpt' } -> `Double' #}++{#fun nlopt_force_stop as ^ { withNLOpt_* `NLOpt' } -> `NloptResult' checkEC* #}+{#fun nlopt_set_force_stop as ^ { withNLOpt_* `NLOpt', `Int' } -> `NloptResult' checkEC* #}+{#fun nlopt_get_force_stop as ^ { withNLOpt_* `NLOpt' } -> `Int' #}+++-- * more algorithm-specific parameters+{#fun nlopt_set_local_optimizer as ^+ { withNLOpt_* `NLOpt', withNLOpt_* `NLOpt' } -> `NloptResult' checkEC* #}++{#fun nlopt_set_population as ^+ { withNLOpt_* `NLOpt', `Int' } -> `NloptResult' checkEC* #}++{#fun nlopt_get_population as ^ { withNLOpt_* `NLOpt' } -> `Int' #}++{#fun nlopt_set_vector_storage as ^+ { withNLOpt_* `NLOpt', `Int' } -> `NloptResult' checkEC* #}++{#fun nlopt_get_vector_storage as ^ { withNLOpt_* `NLOpt' } -> `Int' #}++{#fun nlopt_set_initial_step as ^ { withNLOpt_* `NLOpt',+ vmUnsafeWith* `Vec' } -> `NloptResult' checkEC* #}++{#fun nlopt_get_initial_step as ^ { withNLOpt_* `NLOpt',+ vmUnsafeWith* `Vec',+ vmUnsafeWith* `Vec' } -> `NloptResult' checkEC* #}++{#fun nlopt_set_initial_step1 as ^ { withNLOpt_* `NLOpt',+ `Double' } -> `NloptResult' checkEC* #}++-- * utils for ffi++-- $note+-- much is copied from Ipopt.Raw++withNLOpt_ x f = withNLOpt x (f . castPtr)++vmUnsafeWith :: VM.IOVector Double -> (Ptr CDouble -> IO b) -> IO b+vmUnsafeWith v f = VM.unsafeWith v (f . castPtr)++ptrToVS :: Integral n => n -> Ptr CDouble -> IO Vec+ptrToVS n p = do+ fp <- newForeignPtr_ (castPtr p)+ return (VM.unsafeFromForeignPtr0 fp (fromIntegral n))++ptrToV :: (VG.Vector v Double, Integral n) => n -> Ptr CDouble -> IO (v Double)+ptrToV n p = fmap V.convert $ VS.unsafeFreeze =<< ptrToVS n p++copyInto _ p _ | p == nullPtr = return ()+copyInto n dest src = do+ to <- ptrToVS n dest+ VM.copy to =<< VS.unsafeThaw (V.convert src)++type Vec = VM.IOVector Double++toCInt x = fromIntegral (fromEnum x)+fromCInt x = toEnum (fromIntegral x)+peekInt ptr = fmap fromIntegral (peek ptr)+++ptrToNLOpt :: Ptr () -> IO NLOpt+ptrToNLOpt p = do+ fp <- newForeignPtr nloptDestroyFP p+ return (NLOpt (castForeignPtr fp))++foreign import ccall "wrapper" mkNloptFinalizer :: (Ptr () -> IO ()) -> IO (FunPtr (Ptr () -> IO ()))++foreign import ccall unsafe "& nlopt_destroy" nloptDestroyFP :: FunPtr (Ptr () -> IO ())++foreign import ccall "wrapper" mkFunc :: Func -> IO (FunPtr Func)+foreign import ccall "wrapper" mkPrecond :: Precond -> IO (FunPtr Precond)+foreign import ccall "wrapper" mkMFunc :: MFunc -> IO (FunPtr MFunc)++withFunc :: Func -> (FunPtr Func -> IO b) -> IO b+withFunc f g = do+ f' <- mkFunc f+ r <- g f'+ -- freeHaskellFunPtr f'+ return r++withPrecond :: Precond -> (FunPtr Precond -> IO b) -> IO b+withPrecond f g = do+ f' <- mkPrecond f+ r <- g f'+ -- freeHaskellFunPtr f'+ return r++withMFunc :: MFunc -> (FunPtr MFunc -> IO b) -> IO b+withMFunc f g = do+ f' <- mkMFunc f+ r <- g f'+ -- freeHaskellFunPtr f'+ return r++withNull f = f nullPtr++-- | c2hs generates CDouble peek a Double instead+peekDouble :: Ptr CDouble -> IO Double+peekDouble p = peek (castPtr p)+++-- | naive matrix × vector+mXv :: Num a => V.Vector (V.Vector a) -> V.Vector a -> V.Vector a+mXv m v = V.map (V.sum . V.zipWith (*) v) m++-- * c2hs-generated
examples/AllTests.hs view
@@ -1,23 +1,41 @@-import Test1-import Test2-import Test3-import Test4-import Test5+import Ipopt.PP+import HS71manual+import HS71ad+import HS71nlpMonad+import HS71adN+import HS71nlpMonadN+-- import HS71c+import Spline1 import System.Environment --- probably should get autogenerated if lots of examples get generated...+import Text.Printf+import qualified Data.Vector.Storable as V+import Text.PrettyPrint.ANSI.Leijen (putDoc)+import Text.Read+import Control.Lens+import Nlopt.Raw++ppError v x = do+ let x_official = V.fromList [1, 4.74299964, 3.82114998, 1.37940829]++ let sse :: Double+ sse = V.sum $ V.zipWith (\a b -> (a-b)^2) (x^.v) x_official+ printf "\n||x - x_official|| = %f\n" sse+ main = do as <- getArgs case as of [] -> error "run like: ipopt-hs_Tests 1\nipopt-hs_Tests all"- ["1"] -> main1- ["2"] -> main2- ["3"] -> main3- ["4"] -> main4- ["5"] -> main5- ["all"] -> do- main1- main2- main3- main4- main5+ [a] | Just n <- readMaybe a,+ n < length examples -> examples !! n+ ["all"] -> sequence_ examples++-- probably should get autogenerated if lots of examples get generated...+examples = + [ppError x =<< hs71manual+ ,ppError x =<< hs71ad+ ,ppError (_1.x) =<< hs71nlpMonad+ ,ppError _1 =<< hs71adN NLOPT_LD_SLSQP+ ,ppError (_1.to V.convert) =<< hs71nlpMonadN NLOPT_LD_SLSQP+ ,spline1+ ]
ipopt-hs.cabal view
@@ -1,5 +1,5 @@ name: ipopt-hs-version: 0.3.0.0+version: 0.4.0.0 synopsis: haskell binding to ipopt including automatic differentiation description: a haskell binding to the nonlinear programming solver ipopt <http://projects.coin-or.org/Ipopt>@@ -14,11 +14,10 @@ A embedded language, similar to the one provided by glpk-hs, is defined in "Ipopt.NLP". The goal is to define problems at a level similar to other "algebraic modeling languages", but retain some- of the safety and flexibility available in haskell.- .- Refer to @examples/Test1.hs@ for an example where the derivatives- are computed by hand, @Test2.hs@ for the use of- 'createIpoptProblemAD' and @Test3.hs@ for the highest level.+ of the safety and flexibility available in haskell. There is some+ overhead <http://code.haskell.org/~aavogt/ipopt-hs/examples/bench.html>+ but at least on the small 4-variable constrained optimization+ problem. . Current limitations include: .@@ -27,13 +26,9 @@ somehow. Currently it is done because AD needs a Traversable structure, but Storable vectors are not traversable. .- * sparseness of derivatives isn't used to decide which way to calculate (forward vs. backward mode)- .- * probably doesn't work if @IpStdCInterface.h@ has Number =/= 'CDouble'+ * sparseness of derivatives isn't used . * no binding to SetIntermediateCallback- .- * garbage collection of 'IpProblem' won't free C-side resources license: BSD3 license-file: LICENSE author: Adam Vogt <vogt.adam@gmail.com>@@ -46,6 +41,10 @@ description: build executable from examples/ default: False +flag nlopt+ description: also include nlopt bindings+ default: True+ source-repository head type: darcs location: http://code.haskell.org/~aavogt/ipopt-hs@@ -56,15 +55,24 @@ Ipopt.Raw, Ipopt.Sparsity, Ipopt.NLP,+ Ipopt.Options, Ipopt.PP++ if flag(nlopt)+ exposed-modules: Nlopt.Raw,+ Nlopt.NLP+ pkgconfig-depends: nlopt+ other-modules: C2HS build-depends: base < 5,- vector ==0.10.*,- ad ==3.4.*,- containers == 0.5.*,- mtl == 2.*,- lens >= 3.10,+ ad >=3.4, ansi-wl-pprint >= 0.6.7,+ containers < 0.6,+ lens >= 3.10 && < 5,+ mtl == 2.*,+ template-haskell,+ uu-parsinglib >= 2.8,+ vector ==0.10.*, vector-space >= 0.8.6 default-language: Haskell2010 default-extensions: ConstraintKinds,@@ -80,15 +88,17 @@ build-tools: c2hs - executable ipopt-hs_Tests main-is: AllTests.hs build-depends: base <= 5, vector ==0.10.*, ipopt-hs, lens, mtl, ansi-wl-pprint,- Rlang-QQ, vector-space, splines, ad+ Rlang-QQ, vector-space, splines, ad,+ criterion, random-shuffle,+ optimization >= 0.1.3, linear hs-source-dirs: examples default-language: Haskell2010+ other-extensions: QuasiQuotes other-modules: Paths_ipopt_hs if !flag(build_examples) buildable: False