packages feed

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 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