simplification added

This commit is contained in:
Rowan Torbitzky-Lane 2025-03-06 00:14:03 -06:00
parent c46c53616f
commit 72c339e8b0
3 changed files with 54 additions and 17 deletions

View File

@ -9,6 +9,8 @@ import HushGP.GP.Individual
import HushGP.GP.PushArgs import HushGP.GP.PushArgs
import HushGP.GP.PushData import HushGP.GP.PushData
import HushGP.GP.Variation import HushGP.GP.Variation
import HushGP.GP.Selection
import HushGP.GP.Simplification
import HushGP.Genome import HushGP.Genome
import System.Random import System.Random
import System.Random.Shuffle import System.Random.Shuffle
@ -46,7 +48,7 @@ gpLoop pushArgs@(PushArgs {trainingData = tData}) = do
-- the training data (possibly downsampled). -- the training data (possibly downsampled).
gpLoop' :: PushArgs -> Int -> Int -> [Individual] -> [PushData] -> IO () gpLoop' :: PushArgs -> Int -> Int -> [Individual] -> [PushData] -> IO ()
gpLoop' gpLoop'
pushArgs@(PushArgs {enableDownsampling = enableDS, solutionErrorThreshold = seThresh, downsampleParentsGens = dsParentGens, downsampleParentRate = dsParentRate, trainingData = tData, elitism = isElite, populationSize = popSize}) pushArgs@(PushArgs {enableDownsampling = enableDS, solutionErrorThreshold = seThresh, downsampleParentsGens = dsParentGens, downsampleParentRate = dsParentRate, trainingData = trData, elitism = isElite, populationSize = popSize, useSimplification = useSimp, errorFunction = errorFunc, maxGenerations = maxGens, testingData = teData})
generation generation
evaluations evaluations
population population
@ -60,23 +62,24 @@ gpLoop'
else pure [] else pure []
let nextAction let nextAction
| ( bestIndPassesDownsample | ( bestIndPassesDownsample
&& ( (case totalFitness (updateIndividual (errorFunction epsilonPushArgs epsilonPushArgs indexedTrainingData (plushy bestInd)) bestInd) of (Just x) -> x; _ -> error "Error: Best downsample individual has no fitness!") && ( (case totalFitness (updateIndividual (errorFunc epsilonPushArgs indexedTrainingData (plushy bestInd)) bestInd) of (Just x) -> x; _ -> error "Error: Best downsample individual has no fitness!")
<= solutionErrorThreshold epsilonPushArgs <= solutionErrorThreshold epsilonPushArgs
) )
) )
|| (not (enableDownsampling epsilonPushArgs) && ((case totalFitness bestInd of (Just x) -> x; _ -> error "error: Best non-downsample individual has no fitness!") <= solutionErrorThreshold epsilonPushArgs)) = || (not enableDS && ((case totalFitness bestInd of (Just x) -> x; _ -> error "error: Best non-downsample individual has no fitness!") <= seThresh)) =
do do
print $ "Successful generation: " <> show generation print $ "Successful generation: " <> show generation
print $ "Successful plushy: " <> show (plushy bestInd) print $ "Successful plushy: " <> show (plushy bestInd)
print $ "Successful program: " <> show (plushyToPush pushArgs (plushy bestInd)) print $ "Successful program: " <> show (plushyToPush pushArgs (plushy bestInd))
when (useSimplification epsilonPushArgs) $ print $ "Total test error: " <> show (errorFunc epsilonPushArgs teData (plushy bestInd))
when useSimp $
do do
let simplifiedPlushy = undefined -- TODO: simplification later simplifiedPlushy <- autoSimplifyPlushy pushArgs (plushy bestInd)
print "Total test error simplified: " <> undefined -- Implement later print $ "Simplified plushy: " <> show simplifiedPlushy
print $ "Simplified plushy: " <> undefined -- show simplifiedPlushy print $ "Simplified program: " <> show (plushyToPush pushArgs simplifiedPlushy)
print $ "Simplified program: " <> undefined -- show plushyToPush simplifiedPlushy print $ "Total simplified test error: " <> show (errorFunc epsilonPushArgs teData simplifiedPlushy)
| (not (enableDownsampling epsilonPushArgs) && (generation >= maxGenerations epsilonPushArgs)) | (not enableDS && (generation >= maxGens))
|| (enableDownsampling epsilonPushArgs && (evaluations >= (maxGenerations epsilonPushArgs * length population * length indexedTrainingData))) = || (enableDS && (evaluations >= (maxGens * length population * length indexedTrainingData))) =
print $ "Best individual: " <> show (plushy bestInd) print $ "Best individual: " <> show (plushy bestInd)
| otherwise = do | otherwise = do
newPop <- if isElite then replicateM (popSize - 1) (newIndividual epsilonPushArgs evaledPop) else replicateM popSize (newIndividual epsilonPushArgs evaledPop) newPop <- if isElite then replicateM (popSize - 1) (newIndividual epsilonPushArgs evaledPop) else replicateM popSize (newIndividual epsilonPushArgs evaledPop)
@ -86,14 +89,14 @@ gpLoop'
( evaluations ( evaluations
+ (populationSize pushArgs * length (trainingData pushArgs)) + (populationSize pushArgs * length (trainingData pushArgs))
+ (if generation `mod` downsampleParentsGens pushArgs == 0 then length parentReps * (length indexedTrainingData - length (trainingData pushArgs)) else 0) + (if generation `mod` downsampleParentsGens pushArgs == 0 then length parentReps * (length indexedTrainingData - length (trainingData pushArgs)) else 0)
+ (if bestIndPassesDownsample then length indexedTrainingData - length tData else 0) + (if bestIndPassesDownsample then length indexedTrainingData - length trData else 0)
) )
( if isElite ( if isElite
then bestInd : newPop then bestInd : newPop
else newPop else newPop
) )
( if enableDS && ((generation `mod` dsParentGens) == 0) ( if enableDS && ((generation `mod` dsParentGens) == 0)
then updateCaseDistances repEvaluatedPop indexedTrainingData indexedTrainingData (informedDownsamplingType pushArgs) (solutionErrorThreshold pushArgs / fromIntegral @Int @Double (length indexedTrainingData)) then updateCaseDistances repEvaluatedPop indexedTrainingData indexedTrainingData (informedDownsamplingType pushArgs) (seThresh / fromIntegral @Int @Double (length indexedTrainingData))
else indexedTrainingData else indexedTrainingData
) )
nextAction nextAction
@ -105,10 +108,10 @@ gpLoop'
then evaluatePopulation pushArgs indexedTrainingData population then evaluatePopulation pushArgs indexedTrainingData population
else [] else []
evaledPop :: [Individual] evaledPop :: [Individual]
evaledPop = evaluatePopulation pushArgs tData population evaledPop = evaluatePopulation pushArgs trData population
bestInd :: Individual bestInd :: Individual
bestInd = case uncons evaledPop of Just (x, _) -> x; _ -> error "Error: Population is empty!" bestInd = case uncons evaledPop of Just (x, _) -> x; _ -> error "Error: Population is empty!"
bestIndPassesDownsample :: Bool bestIndPassesDownsample :: Bool
bestIndPassesDownsample = enableDS && (extractTotalFitness bestInd <= seThresh) bestIndPassesDownsample = enableDS && (extractTotalFitness bestInd <= seThresh)
epsilonPushArgs :: PushArgs epsilonPushArgs :: PushArgs
epsilonPushArgs = pushArgs {epsilons = Nothing} -- TODO: And this epsilonPushArgs = pushArgs {epsilons = Just $ epsilonList evaledPop}

View File

@ -7,6 +7,8 @@ import Data.List
import HushGP.State import HushGP.State
import HushGP.GP.PushArgs import HushGP.GP.PushArgs
import Debug.Trace
-- | Takes a list of Genes (a plushy), chunks it up into sizes of 1 (type is [[Gene]]). -- | Takes a list of Genes (a plushy), chunks it up into sizes of 1 (type is [[Gene]]).
-- and a list of indices for replacement (gets sorted before replacement). -- and a list of indices for replacement (gets sorted before replacement).
deleteAtMultiple :: [Int] -> [Gene] -> [Gene] deleteAtMultiple :: [Int] -> [Gene] -> [Gene]
@ -37,9 +39,18 @@ autoSimplifyPlushy pushArgs@PushArgs{simplificationVerbose = simpVerbose, errorF
autoSimplifyPlushy' :: PushArgs -> [Double] -> Int -> [Gene] -> IO [Gene] autoSimplifyPlushy' :: PushArgs -> [Double] -> Int -> [Gene] -> IO [Gene]
autoSimplifyPlushy' pushArgs@PushArgs{simplificationVerbose = simpVerbose, simplificationSteps = simpSteps, simplificationMaxAmt = simpK, errorFunction = eFunc, trainingData = tData} initialErrors step plushy autoSimplifyPlushy' pushArgs@PushArgs{simplificationVerbose = simpVerbose, simplificationSteps = simpSteps, simplificationMaxAmt = simpK, errorFunction = eFunc, trainingData = tData} initialErrors step plushy
| step < simpSteps = do | step < simpSteps = do
newPlushy <- deleteRandomAmt simpK plushy randAmt <- fst . uniformR (1 :: Int, simpK) <$> initStdGen
newPlushy <- deleteRandomAmt randAmt plushy
let newPlushyErrors = eFunc pushArgs tData newPlushy let newPlushyErrors = eFunc pushArgs tData newPlushy
let isBetter = newPlushyErrors <= initialErrors let isBetter = newPlushyErrors <= initialErrors
print "-----------------------------------------"
print $ "k: " <> show randAmt
print $ "step: " <> show step
print $ "newPlushy: " <> show newPlushy
print $ "plushy: " <> show plushy
print $ "isBetter: " <> show isBetter
print $ "initialErrors: " <> show initialErrors
print $ "newErrors: " <> show newPlushyErrors
autoSimplifyPlushy' pushArgs initialErrors (succ step) (if isBetter then newPlushy else plushy) autoSimplifyPlushy' pushArgs initialErrors (succ step) (if isBetter then newPlushy else plushy)
| otherwise = do | otherwise = do
when simpVerbose (print ("simplification end plushy length: " <> show (length plushy))) when simpVerbose (print ("simplification end plushy length: " <> show (length plushy)))

View File

@ -19,10 +19,30 @@ testPlushy = [
-- GeneFloat 3.2 -- GeneFloat 3.2
] ]
intSolutionPlushy :: [Gene]
intSolutionPlushy =
[ PlaceInput 0
, PlaceInput 0
, PlaceInput 0
, StateFunc (instructionIntMul, "instructionIntMul")
, StateFunc (instructionIntMul, "instructionIntMul")
-- , GeneInt 2
-- , PlaceInput 0
, GeneBool True -- A useless gene
-- , StateFunc (instructionIntMul, "instructionIntMul")
-- , GeneInt 6
-- , StateFunc (instructionIntAdd, "instructionIntAdd")
-- , StateFunc (instructionIntAdd, "instructionIntAdd")
-- , GeneInt 5 -- Also a useless gene
, GeneFloat 4.3
, GeneString "hello"
]
-- | The target function for this run. The function the gp -- | The target function for this run. The function the gp
-- is trying to evolve. -- is trying to evolve.
targetFunction :: Integer -> Integer targetFunction :: Integer -> Integer
targetFunction x = (x * x * x) + (2 * x) -- targetFunction x = (x * x * x) + (2 * x) + 6
targetFunction x = x * x * x
-- | The training data for the model. -- | The training data for the model.
intTrainData :: [PushData] intTrainData :: [PushData]
@ -91,7 +111,10 @@ intPushArgs = defaultPushArgs
variation = [("umad", 1.0), ("crossover", 0.0)], variation = [("umad", 1.0), ("crossover", 0.0)],
elitism = False, elitism = False,
enableDownsampling = False, enableDownsampling = False,
downsampleRate = 0.5 downsampleRate = 0.5,
simplificationVerbose = True,
simplificationMaxAmt = 4,
simplificationSteps = 200
} }
main :: IO () main :: IO ()