moo-1.2: Tests/Problems/Rosenbrock.hs
{- Minimize Rosenbrock function using real-valued genetic algorithm.
Optimal value x* = (1,...,1). F(x*) = 0.
-}
module Tests.Problems.Rosenbrock where
import Test.HUnit
import Text.Printf
import Data.List (intercalate)
import System.IO (hPutStrLn, stderr)
import Control.Monad (replicateM)
import Tests.Common
import Moo.GeneticAlgorithm.Types
import Moo.GeneticAlgorithm.Selection
import Moo.GeneticAlgorithm.Run
import Moo.GeneticAlgorithm.Random
pr _ = return ()
-- pr = hPutStrLn stderr
rosenbrock :: [Double] -> Double
rosenbrock xs = sum . map f $ zip xs (drop 1 xs)
where
f (x1, x2) = 100 * (x2 - x1^2)^2 + (x1 - 1)^2
testRosenbrock = TestList
[ "Rosenbrock 2D GM/UNDX/500 gens" ~: do
let tolerance = 1e-3 -- solution error
let maxiters = 500
let problem = RealMinimize rosenbrock [(-10,10),(-20,20)] [1,1]
let solver = solverReal problem 101 11 undx (Generations maxiters)
(pop, dist) <- runSolverReal problem solver
let best = takeGenome . head $ bestFirst Minimizing pop
pr ""
pr $ "best: " ++ (intercalate " " (map (printf "%.5f") best))
pr $ "error: " ++ (printf "%.5g" dist)
assertBool ("error >= " ++ show tolerance) (dist < tolerance)
, "Rosenbrock 2D GM/SBX/min residual, max 500 gens" ~: do
let tolerance = 1e-6 -- objective residual
let maxiters = 500
let problem = RealMinimize rosenbrock [(-20,20),(-20,20)] [1,1]
let stop = Generations maxiters `Or` IfObjective ((>= -tolerance) . maximum)
let solver = solverReal problem 101 11 sbx stop
(pop, dist) <- runSolverReal problem solver
let best = head $ bestFirst Minimizing pop
let bestG = takeGenome best
let bestF = takeObjectiveValue best
pr ""
pr $ "best: " ++ (intercalate " " (map (printf "%.5f") bestG))
pr $ "residual: " ++ (printf "%.5g" bestF)
assertBool ("residual < " ++ show (negate tolerance)) (bestF >= -tolerance)
, "Rosenbrock 2D GM/BLX-0.5/min residual, max 500 gens" ~: do
let tolerance = 1e-3 -- solution error
let maxiters = 500
let problem = RealMinimize rosenbrock [(-20,20),(-20,20)] [1,1]
let stop = Generations maxiters
let solver = solverReal problem 400 11 blxa stop
(pop, dist) <- runSolverReal problem solver
let bestG = takeGenome . head $ bestFirst Minimizing pop
pr ""
pr $ "best: " ++ (intercalate " " (map (printf "%.5f") bestG))
pr $ "error: " ++ (printf "%.5g" dist)
assertBool ("error = " ++ show dist ++ " >= " ++ show tolerance) (dist < tolerance)
, "Rosenbrock 2D GM/UNDX/GensNoChange 10" ~: do
let maxiters = 5000
let popsize = 101
let elite = 11
let nochange = 10
let select = tournamentSelect Minimizing 3 (popsize - elite)
let stop = (GensNoChange nochange (round.(*1e3).maximum) Nothing) `Or` (Generations maxiters)
let step = nextGeneration Minimizing rosenbrock select elite undx (gauss 1.0 2)
let log = WriteEvery 1 (\_ p -> [minimum . map takeObjectiveValue $ p])
let ga = loopWithLog log stop step
let init = replicateM popsize . replicateM 2 $ getRandomR (-10,10)
(pop, hist) <- runGA init ga
let best = takeGenome . head $ bestFirst Minimizing pop
pr ""
pr $ "best: " ++ (intercalate " " (map (printf "%.5f") best))
let lastbest = take nochange (reverse hist)
pr $ "last best: "
mapM_ pr (map show $ reverse lastbest)
assertBool "false positive on GensNoChange"
(all id $ zipWith (==) lastbest (drop 1 lastbest))
]