{-# OPTIONS_GHC -fno-warn-name-shadowing #-} {-# OPTIONS_GHC -Wall #-} module Main where import Numeric.Optimization.NLOPT.Bindings import qualified Data.Vector.Storable as V import qualified System.Exit as E import Control.Monad (when) objective :: ScalarFunction () objective params g _ = do case g of Just grad -> V.copy grad $ V.fromList [0.0, 0.5] Nothing -> return () return $ sqrt $ params V.! 1 constraint :: ScalarFunction (Double, Double) constraint params g (a, b) = do case g of Just grad -> V.copy grad $ V.fromList [3 * a * t * t, -1.0] Nothing -> return () return f where [x0, x1] = V.toList params t = (a * x0 + b) f = t * t * t - x1 lowerBounds :: V.Vector Double lowerBounds = V.fromList [-1e222, 0.0] checkReturn :: Result -> IO () checkReturn c = when (not $ isSuccess c) $ do putStrLn $ "NLOPT error '" ++ show c ++ "'!" E.exitFailure xinit :: V.Vector Double xinit = V.fromList [1.234, 5.678] expectedParams :: V.Vector Double expectedParams = V.fromList [0.33333337491594595,0.2962962707981303] expectedMinimum :: Double expectedMinimum = 0.5443310305302559 main :: IO () main = do Just opt <- create LD_MMA 2 putStrLn "Got optimizer." bnd <- set_lower_bounds opt lowerBounds checkReturn bnd putStrLn "Set lower bounds." obj <- set_min_objective opt objective () checkReturn obj putStrLn "Set min objective." cnst1 <- add_inequality_constraint opt constraint (2, 0) 1e-8 checkReturn cnst1 putStrLn "Added inequality constraint #1." cnst2 <- add_inequality_constraint opt constraint (-1, 1) 1e-8 checkReturn cnst2 putStrLn "Added inequality constraint #2." tol <- set_xtol_rel opt 1e-4 checkReturn tol putStrLn "Set param tolerance." Output result cost params <- optimize opt xinit checkReturn result let verr = V.sum . V.map (abs) $ V.zipWith (-) params expectedParams ferr = abs $ cost - expectedMinimum if verr > 1e-12 || ferr > 1e-12 then do putStrLn "Solution error!" putStrLn $ "Expected minimum of " ++ show expectedMinimum ++ " and got " ++ show cost putStrLn $ "Expected " ++ show expectedParams ++ " and got " ++ show params E.exitFailure else putStrLn $ "Found minimum at f" ++ show params ++ " = " ++ show cost