more gp loop/formatting
This commit is contained in:
parent
0ebfb13e04
commit
b57a802f11
@ -1,11 +1,13 @@
|
|||||||
-- | The main file containing information about the GP loop and various population transformation functions.
|
-- | The main file containing information about the GP loop and various population transformation functions.
|
||||||
module HushGP.GP where
|
module HushGP.GP where
|
||||||
|
|
||||||
import HushGP.Genome
|
|
||||||
import HushGP.GP.PushArgs
|
|
||||||
import Control.Parallel.Strategies
|
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Data.List (sort)
|
import Control.Parallel.Strategies
|
||||||
|
import Data.List (sort, uncons)
|
||||||
|
import HushGP.GP.PushArgs
|
||||||
|
import HushGP.Genome
|
||||||
|
import HushGP.State
|
||||||
|
|
||||||
-- import Debug.Trace (trace, traceStack)
|
-- import Debug.Trace (trace, traceStack)
|
||||||
|
|
||||||
-- | Using a PushArgs object, generates a population of the specified size with the
|
-- | Using a PushArgs object, generates a population of the specified size with the
|
||||||
@ -17,21 +19,62 @@ generatePopulation pushArgs = do
|
|||||||
|
|
||||||
-- | Evaluates a population of plushies with the error function passed in via PushArgs and sorts them.
|
-- | Evaluates a population of plushies with the error function passed in via PushArgs and sorts them.
|
||||||
-- TODO: Need to make this runnable in parallel too.
|
-- TODO: Need to make this runnable in parallel too.
|
||||||
evaluatePopulation :: PushArgs -> [Individual] -> [Individual]
|
evaluatePopulation :: PushArgs -> ([[Gene]], [Gene]) -> [Individual] -> [Individual]
|
||||||
evaluatePopulation pushArgs population = sort $ zipWith updateIndividual (map (errorFunction pushArgs pushArgs (trainingData pushArgs) . plushy) population) population
|
evaluatePopulation pushArgs passedTrainingData population = sort $ zipWith updateIndividual (map (errorFunction pushArgs pushArgs passedTrainingData . plushy) population) population
|
||||||
|
|
||||||
-- | A helper function used in evaluatePopulation. Takes a [Double] as the error scores and an individual.
|
-- | A helper function used in evaluatePopulation. Takes a [Double] as the error scores and an individual.
|
||||||
-- Updates the error fields in an individual, and returns it.
|
-- Updates the error fields in an individual, and returns it.
|
||||||
updateIndividual :: [Double] -> Individual -> Individual
|
updateIndividual :: [Double] -> Individual -> Individual
|
||||||
updateIndividual errors ind = ind{totalFitness = Just (sum errors), fitnessCases = Just errors}
|
updateIndividual errors ind = ind {totalFitness = Just (sum errors), fitnessCases = Just errors}
|
||||||
|
|
||||||
-- | The start of the gp loop. TODO: Make this more accurate later.
|
-- | The start of the gp loop. TODO: Make this more accurate later.
|
||||||
gpLoop :: PushArgs -> IO ()
|
gpLoop :: PushArgs -> IO ()
|
||||||
gpLoop pushArgs = do
|
gpLoop pushArgs = do
|
||||||
unEvaledPopulation <- generatePopulation pushArgs
|
unEvaledPopulation <- generatePopulation pushArgs
|
||||||
let evaledPop = evaluatePopulation pushArgs unEvaledPopulation
|
-- let evaledPop = evaluatePopulation pushArgs unEvaledPopulation
|
||||||
print evaledPop
|
-- print evaledPop
|
||||||
|
print "gamer"
|
||||||
|
|
||||||
-- | The guts of the GP loop. Where the work gets done after the initialization happens
|
-- | The guts of the GP loop. Where the work gets done after the initialization happens
|
||||||
-- in the main gpLoop function.
|
-- in the main gpLoop function. The first Int holds the generation count. The second Int
|
||||||
-- gpLoop'
|
-- holds the evaluation count. The list of Individuals is the population. The last parameter is
|
||||||
|
-- the training data (possibly downsampled).
|
||||||
|
gpLoop' :: PushArgs -> Int -> Int -> [Individual] -> ([[Gene]], [Gene]) -> IO ()
|
||||||
|
gpLoop' pushArgs generation evaluations population indexedTrainingData = do
|
||||||
|
print "Put information about each generation here."
|
||||||
|
when bestIndPassesDownsample $ print $ "Semi Success Generation: " <> show generation
|
||||||
|
let nextAction | (bestIndPassesDownsample && ((case totalFitness (updateIndividual (errorFunction epsilonPushArgs epsilonPushArgs indexedTrainingData (plushy bestInd)) bestInd) of (Just x) -> x; _ -> error "Error: Best downsample individual has no fitness!") <= solutionErrorThreshold epsilonPushArgs)) || (not (enableDownsampling epsilonPushArgs) && ((case totalFitness bestInd of (Just x) -> x; _ -> error "error: Best non-downsample individual has no fitness!") <= solutionErrorThreshold epsilonPushArgs)) =
|
||||||
|
do
|
||||||
|
print $ "Successful generation: " <> show generation
|
||||||
|
print $ "Successful plushy: " <> show (plushy bestInd)
|
||||||
|
print $ "Successful program: " <> show (plushyToPush $ plushy bestInd)
|
||||||
|
when (useSimplification epsilonPushArgs) $
|
||||||
|
do
|
||||||
|
let simplifiedPlushy = undefined -- TODO: simplification later
|
||||||
|
print "Total test error simplified: " <> undefined -- Implement later
|
||||||
|
print $ "Simplified plushy: " <> undefined -- show simplifiedPlushy
|
||||||
|
print $ "Simplified program: " <> undefined -- show plushyToPush simplifiedPlushy
|
||||||
|
| (not (enableDownsampling epsilonPushArgs) && (generation >= maxGenerations epsilonPushArgs)) || (enableDownsampling epsilonPushArgs && (evaluations >= (maxGenerations epsilonPushArgs * length population * length (fst indexedTrainingData)))) =
|
||||||
|
print "Incomplete Run, saving the best so far."
|
||||||
|
| otherwise = gpLoop' pushArgs (succ generation)
|
||||||
|
(evaluations + (populationSize pushArgs * length (fst $ trainingData pushArgs)) + (if generation `mod` downsampleParentsGens pushArgs == 0 then length parentReps * (length (fst indexedTrainingData) - length (fst $ trainingData pushArgs)) else 0) + (if bestIndPassesDownsample then length (fst indexedTrainingData) - length (fst $ trainingData pushArgs) else 0))
|
||||||
|
nextAction
|
||||||
|
where
|
||||||
|
-- \| This will have downsampling added to it later.
|
||||||
|
loopTrainData :: ([[Gene]], [Gene])
|
||||||
|
loopTrainData = indexedTrainingData
|
||||||
|
-- \| This will have downsampling functionality added later.
|
||||||
|
parentReps :: [Individual]
|
||||||
|
parentReps = []
|
||||||
|
-- \| This will have downsampling functionality added later.
|
||||||
|
repEvaluatedPop :: [Individual]
|
||||||
|
repEvaluatedPop = []
|
||||||
|
evaledPop :: [Individual]
|
||||||
|
evaledPop = evaluatePopulation pushArgs indexedTrainingData population
|
||||||
|
bestInd :: Individual
|
||||||
|
bestInd = case uncons evaledPop of Just (x, _) -> x; _ -> error "Error: Population is empty!"
|
||||||
|
bestIndPassesDownsample :: Bool
|
||||||
|
bestIndPassesDownsample = False -- TODO: fix this later
|
||||||
|
epsilonPushArgs :: PushArgs
|
||||||
|
epsilonPushArgs = pushArgs {epsilons = Nothing} -- TODO: And this
|
||||||
|
gpLoop' _ _ _ _ _ = error "How did this happen?"
|
||||||
|
@ -77,7 +77,7 @@ data PushArgs = PushArgs
|
|||||||
-- | Whether to use mutli-threading.
|
-- | Whether to use mutli-threading.
|
||||||
useMultiThreading :: Bool,
|
useMultiThreading :: Bool,
|
||||||
-- | Max total error for solutions.
|
-- | Max total error for solutions.
|
||||||
solutionErrorThreshold :: Int,
|
solutionErrorThreshold :: Double,
|
||||||
-- | Limit of push interpreter steps in push program evaluation.
|
-- | Limit of push interpreter steps in push program evaluation.
|
||||||
stepLimit :: Int,
|
stepLimit :: Int,
|
||||||
-- | For tournament selection, amount of individuals in each tournament.
|
-- | For tournament selection, amount of individuals in each tournament.
|
||||||
@ -90,7 +90,9 @@ data PushArgs = PushArgs
|
|||||||
umadRate :: Float,
|
umadRate :: Float,
|
||||||
-- | Genetic operators and probabilities for their use, should sum to one
|
-- | Genetic operators and probabilities for their use, should sum to one
|
||||||
-- Takes a Map of String -> Float where the string is the genetic operator
|
-- Takes a Map of String -> Float where the string is the genetic operator
|
||||||
variation :: Map.Map String Float
|
variation :: Map.Map String Float,
|
||||||
|
-- | The epsilons calculated for epsilon lexicase selection. Only used for epsilon lexicase selection.
|
||||||
|
epsilons :: Maybe [Double]
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | The default values for which all runs of Hush derive
|
-- | The default values for which all runs of Hush derive
|
||||||
@ -128,12 +130,13 @@ defaultPushArgs = PushArgs {
|
|||||||
simplificationSteps = 1000,
|
simplificationSteps = 1000,
|
||||||
simplificationVerbose = False,
|
simplificationVerbose = False,
|
||||||
useMultiThreading = False, -- False for now, change to True later.
|
useMultiThreading = False, -- False for now, change to True later.
|
||||||
solutionErrorThreshold = 0,
|
solutionErrorThreshold = 0.0,
|
||||||
ssxNotBmx = False,
|
ssxNotBmx = False,
|
||||||
stepLimit = 1000,
|
stepLimit = 1000,
|
||||||
tournamentSize = 5,
|
tournamentSize = 5,
|
||||||
testingData = ([], []),
|
testingData = ([], []),
|
||||||
trainingData = ([], []),
|
trainingData = ([], []),
|
||||||
umadRate = 0.1,
|
umadRate = 0.1,
|
||||||
variation = Map.fromList [("umad", 1.0)]
|
variation = Map.fromList [("umad", 1.0)],
|
||||||
|
epsilons = Nothing
|
||||||
}
|
}
|
||||||
|
@ -3,20 +3,22 @@ module HushGP.Genome where
|
|||||||
import Data.List
|
import Data.List
|
||||||
import Data.List.Split
|
import Data.List.Split
|
||||||
import Data.Map qualified as Map
|
import Data.Map qualified as Map
|
||||||
|
import HushGP.GP.PushArgs
|
||||||
import HushGP.Instructions.Opens
|
import HushGP.Instructions.Opens
|
||||||
import HushGP.State
|
import HushGP.State
|
||||||
import HushGP.Utility
|
import HushGP.Utility
|
||||||
import HushGP.GP.PushArgs
|
|
||||||
-- import HushGP.Instructions
|
-- import HushGP.Instructions
|
||||||
-- import Debug.Trace
|
-- import Debug.Trace
|
||||||
|
|
||||||
-- | The structure for an individual containing the genome, the totalFitness, and
|
-- | The structure for an individual containing the genome, the totalFitness, and
|
||||||
-- the individual fitness cases for lexicase.
|
-- the individual fitness cases for lexicase.
|
||||||
data Individual = Individual {
|
data Individual = Individual
|
||||||
plushy :: [Gene],
|
{ plushy :: [Gene],
|
||||||
totalFitness :: Maybe Double,
|
totalFitness :: Maybe Double,
|
||||||
fitnessCases :: Maybe [Double]
|
fitnessCases :: Maybe [Double]
|
||||||
} deriving (Show, Eq)
|
}
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
instance Ord Individual where
|
instance Ord Individual where
|
||||||
ind0 <= ind1 = totalFitness ind0 <= totalFitness ind1
|
ind0 <= ind1 = totalFitness ind0 <= totalFitness ind1
|
||||||
@ -70,29 +72,31 @@ plushyToPush plushy = plushyToPush' (concatMap (\x -> if isOpenerList x then x <
|
|||||||
-- | Internal function used to convert a plushy genome with opens in it into its push phenotype.
|
-- | Internal function used to convert a plushy genome with opens in it into its push phenotype.
|
||||||
plushyToPush' :: [Gene] -> [Gene] -> [Gene]
|
plushyToPush' :: [Gene] -> [Gene] -> [Gene]
|
||||||
plushyToPush' openPlushy push
|
plushyToPush' openPlushy push
|
||||||
| null openPlushy = if any isOpen push
|
| null openPlushy =
|
||||||
|
if any isOpen push
|
||||||
then plushyToPush' [Close] push
|
then plushyToPush' [Close] push
|
||||||
else push
|
else push
|
||||||
| firstPlushy == Close = if any isOpen push
|
| firstPlushy == Close =
|
||||||
then plushyToPush' (drop 1 openPlushy) (if numOpen (push !! openIndex) == 1 then preOpen <> [Block postOpen] else preOpen <> [Block postOpen] <> [decOpen (Open (numOpen (push !! openIndex)))])
|
if any isOpen push
|
||||||
else plushyToPush' (drop 1 openPlushy) push
|
then plushyToPush' (drop 1 openPlushy) (if numOpen (push !! openIndex) == 1 then preOpen <> [Block postOpen] else preOpen <> [Block postOpen] <> [decOpen (Open (numOpen (push !! openIndex)))])
|
||||||
|
else plushyToPush' (drop 1 openPlushy) push
|
||||||
| firstPlushy == Skip =
|
| firstPlushy == Skip =
|
||||||
case uncons openPlushy of
|
case uncons openPlushy of
|
||||||
Just (_, _ : xs) -> plushyToPush' xs push
|
Just (_, _ : xs) -> plushyToPush' xs push
|
||||||
_ -> plushyToPush' (drop 1 openPlushy) push
|
_ -> plushyToPush' (drop 1 openPlushy) push
|
||||||
| otherwise = plushyToPush' (drop 1 openPlushy) (push <> [firstPlushy])
|
| otherwise = plushyToPush' (drop 1 openPlushy) (push <> [firstPlushy])
|
||||||
where
|
where
|
||||||
firstPlushy :: Gene
|
firstPlushy :: Gene
|
||||||
firstPlushy
|
firstPlushy =
|
||||||
= case uncons openPlushy of
|
case uncons openPlushy of
|
||||||
Just (g, _) -> g
|
Just (g, _) -> g
|
||||||
_ -> error "This shouldn't happen"
|
_ -> error "This shouldn't happen"
|
||||||
postOpen :: [Gene]
|
postOpen :: [Gene]
|
||||||
postOpen = reverse (takeWhile (not . isOpen) (reverse push))
|
postOpen = reverse (takeWhile (not . isOpen) (reverse push))
|
||||||
openIndex :: Int
|
openIndex :: Int
|
||||||
openIndex = length push - length postOpen - 1
|
openIndex = length push - length postOpen - 1
|
||||||
numOpen :: Gene -> Int
|
numOpen :: Gene -> Int
|
||||||
numOpen (Open n) = n
|
numOpen (Open n) = n
|
||||||
numOpen _ = 0
|
numOpen _ = 0
|
||||||
preOpen :: [Gene]
|
preOpen :: [Gene]
|
||||||
preOpen = take openIndex push
|
preOpen = take openIndex push
|
||||||
|
@ -40,15 +40,17 @@ noOpStateFuncBlock = StateFunc (instructionNoOpBlock, "instructionNoOpBlock")
|
|||||||
-- | All of the instructions declared in all the instruction submodules
|
-- | All of the instructions declared in all the instruction submodules
|
||||||
allInstructions :: [Gene]
|
allInstructions :: [Gene]
|
||||||
allInstructions =
|
allInstructions =
|
||||||
noOpStateFunc : noOpStateFuncBlock : allIntInstructions
|
noOpStateFunc
|
||||||
<> allFloatInstructions
|
: noOpStateFuncBlock
|
||||||
<> allBoolInstructions
|
: allIntInstructions
|
||||||
<> allCharInstructions
|
<> allFloatInstructions
|
||||||
<> allCodeInstructions
|
<> allBoolInstructions
|
||||||
<> allExecInstructions
|
<> allCharInstructions
|
||||||
<> allStringInstructions
|
<> allCodeInstructions
|
||||||
<> allVectorIntInstructions
|
<> allExecInstructions
|
||||||
<> allVectorFloatInstructions
|
<> allStringInstructions
|
||||||
<> allVectorCharInstructions
|
<> allVectorIntInstructions
|
||||||
<> allVectorStringInstructions
|
<> allVectorFloatInstructions
|
||||||
<> allVectorBoolInstructions
|
<> allVectorCharInstructions
|
||||||
|
<> allVectorStringInstructions
|
||||||
|
<> allVectorBoolInstructions
|
||||||
|
@ -21,8 +21,8 @@ data Gene
|
|||||||
| GeneVectorBool [Bool]
|
| GeneVectorBool [Bool]
|
||||||
| GeneVectorString [String]
|
| GeneVectorString [String]
|
||||||
| GeneVectorChar [Char]
|
| GeneVectorChar [Char]
|
||||||
-- | State -> State is the function itself. String stores the name of the function.
|
| -- | State -> State is the function itself. String stores the name of the function.
|
||||||
| StateFunc (State -> State, String)
|
StateFunc (State -> State, String)
|
||||||
| PlaceInput Int
|
| PlaceInput Int
|
||||||
| Close
|
| Close
|
||||||
| Open Int
|
| Open Int
|
||||||
|
Loading…
x
Reference in New Issue
Block a user