{-# LANGUAGE RankNTypes #-}
module Test.Mutagen.Test.Queue
(
MutationQueue (..)
, emptyMutationQueue
, mutationQueueSize
, enqueueMutationCandidate
, dequeueNextMutationCandidate
, MutationCandidate (..)
, MutationBatch (..)
, newMutationBatch
, newMutationBatchFromParent
, createOrInheritMutationBatch
, nextMutation
)
where
import Control.Monad.Extra (concatMapM)
import Data.Maybe (fromMaybe)
import Data.PQueue.Prio.Min (MinPQueue)
import qualified Data.PQueue.Prio.Min as PQueue
import Test.Mutagen.Fragment.Store (FragmentStore)
import Test.Mutagen.Mutant (Concretized (..), MutantKind, concretize)
import Test.Mutagen.Mutation (Mutable (..), MutationOrder, Pos)
import Test.Mutagen.Property (Args)
import Test.Mutagen.Tracer.Trace (Trace)
type Priority = Int
newtype MutationQueue
= MutationQueue (MinPQueue Priority (MutationCandidate Args))
emptyMutationQueue :: MutationQueue
emptyMutationQueue :: MutationQueue
emptyMutationQueue = MinPQueue Priority (MutationCandidate Args) -> MutationQueue
MutationQueue MinPQueue Priority (MutationCandidate Args)
forall a. Monoid a => a
mempty
mutationQueueSize :: MutationQueue -> Int
mutationQueueSize :: MutationQueue -> Priority
mutationQueueSize (MutationQueue MinPQueue Priority (MutationCandidate Args)
q) = MinPQueue Priority (MutationCandidate Args) -> Priority
forall k a. MinPQueue k a -> Priority
PQueue.size MinPQueue Priority (MutationCandidate Args)
q
enqueueMutationCandidate
:: Priority
-> MutationCandidate Args
-> MutationQueue
-> MutationQueue
enqueueMutationCandidate :: Priority
-> MutationCandidate Args -> MutationQueue -> MutationQueue
enqueueMutationCandidate Priority
prio MutationCandidate Args
candidate (MutationQueue MinPQueue Priority (MutationCandidate Args)
queue) =
MinPQueue Priority (MutationCandidate Args) -> MutationQueue
MutationQueue (Priority
-> MutationCandidate Args
-> MinPQueue Priority (MutationCandidate Args)
-> MinPQueue Priority (MutationCandidate Args)
forall k a. Ord k => k -> a -> MinPQueue k a -> MinPQueue k a
PQueue.insert Priority
prio MutationCandidate Args
candidate MinPQueue Priority (MutationCandidate Args)
queue)
dequeueNextMutationCandidate
:: MutationQueue
-> (Priority, MutationCandidate Args, MutationQueue)
dequeueNextMutationCandidate :: MutationQueue -> (Priority, MutationCandidate Args, MutationQueue)
dequeueNextMutationCandidate (MutationQueue MinPQueue Priority (MutationCandidate Args)
queue) =
let ((Priority
prio, MutationCandidate Args
candidate), MinPQueue Priority (MutationCandidate Args)
queue') = MinPQueue Priority (MutationCandidate Args)
-> ((Priority, MutationCandidate Args),
MinPQueue Priority (MutationCandidate Args))
forall k a. Ord k => MinPQueue k a -> ((k, a), MinPQueue k a)
PQueue.deleteFindMin MinPQueue Priority (MutationCandidate Args)
queue
in (Priority
prio, MutationCandidate Args
candidate, MinPQueue Priority (MutationCandidate Args) -> MutationQueue
MutationQueue MinPQueue Priority (MutationCandidate Args)
queue')
data MutationCandidate args
= MutationCandidate
{ forall args. MutationCandidate args -> args
mcArgs :: args
, forall args. MutationCandidate args -> Trace
mcTrace :: Trace
, forall args. MutationCandidate args -> MutationBatch args
mcBatch :: MutationBatch args
}
data MutationBatch args
= MutationBatch
{ forall args. MutationBatch args -> args
mbArgs :: args
, forall args. MutationBatch args -> [Pos]
mbPastPositions :: [Pos]
, forall args. MutationBatch args -> [Concretized args]
mbCurrBatch :: [Concretized args]
, forall args. MutationBatch args -> [Pos]
mbNextPositions :: [Pos]
, forall args. MutationBatch args -> MutationOrder
mbMutationOrder :: MutationOrder
, forall args. MutationBatch args -> Bool
mbTestPassed :: Bool
, forall args. MutationBatch args -> Priority
mbRandomMutationSize :: Int
, forall args. MutationBatch args -> Priority
mbNumRandomMutations :: Int
, forall args. MutationBatch args -> Priority
mbNumFragMutations :: Int
, forall args. MutationBatch args -> Priority
mbMaxMutationDepth :: Int
}
newMutationBatch
:: (Mutable a)
=> MutationOrder
-> Int
-> Int
-> Int
-> Int
-> Maybe [Pos]
-> Bool
-> a
-> MutationBatch a
newMutationBatch :: forall a.
Mutable a =>
MutationOrder
-> Priority
-> Priority
-> Priority
-> Priority
-> Maybe [Pos]
-> Bool
-> a
-> MutationBatch a
newMutationBatch
MutationOrder
mutationOrder
Priority
numRandomMutations
Priority
randomMutationSize
Priority
numFragMutations
Priority
maxMutationDepth
Maybe [Pos]
evaluatedPositions
Bool
testPassed
a
args =
MutationBatch
{ mbArgs :: a
mbArgs = a
args
, mbPastPositions :: [Pos]
mbPastPositions = [Pos]
forall a. Monoid a => a
mempty
, mbNextPositions :: [Pos]
mbNextPositions = [Pos]
nextPositions
, mbCurrBatch :: [Concretized a]
mbCurrBatch = [Concretized a]
forall a. Monoid a => a
mempty
, mbMutationOrder :: MutationOrder
mbMutationOrder = Tree a -> [a]
MutationOrder
mutationOrder
, mbTestPassed :: Bool
mbTestPassed = Bool
testPassed
, mbRandomMutationSize :: Priority
mbRandomMutationSize = Priority
randomMutationSize
, mbNumRandomMutations :: Priority
mbNumRandomMutations = Priority
numRandomMutations
, mbMaxMutationDepth :: Priority
mbMaxMutationDepth = Priority
maxMutationDepth
, mbNumFragMutations :: Priority
mbNumFragMutations = Priority
numFragMutations
}
where
nextPositions :: [Pos]
nextPositions =
[Pos] -> Maybe [Pos] -> [Pos]
forall a. a -> Maybe a -> a
fromMaybe (Tree Pos -> [Pos]
MutationOrder
mutationOrder (a -> Tree Pos
forall a. Mutable a => a -> Tree Pos
positions a
args)) Maybe [Pos]
evaluatedPositions
newMutationBatchFromParent
:: (Mutable a)
=> MutationBatch a
-> Maybe [Pos]
-> Bool
-> a
-> MutationBatch a
newMutationBatchFromParent :: forall a.
Mutable a =>
MutationBatch a -> Maybe [Pos] -> Bool -> a -> MutationBatch a
newMutationBatchFromParent
MutationBatch a
batch
Maybe [Pos]
evaluatedPos
Bool
testPassed
a
args =
MutationBatch a
batch
{ mbArgs = args
, mbNextPositions = nextPositions
, mbPastPositions = mempty
, mbTestPassed = testPassed
, mbCurrBatch = mempty
, mbMaxMutationDepth = mbMaxMutationDepth batch - 1
}
where
nextPositions :: [Pos]
nextPositions =
[Pos] -> Maybe [Pos] -> [Pos]
forall a. a -> Maybe a -> a
fromMaybe (MutationBatch a -> MutationOrder
forall args. MutationBatch args -> MutationOrder
mbMutationOrder MutationBatch a
batch (a -> Tree Pos
forall a. Mutable a => a -> Tree Pos
positions a
args)) Maybe [Pos]
evaluatedPos
createOrInheritMutationBatch
:: MutationOrder
-> Int
-> Int
-> Int
-> Int
-> Args
-> Maybe (MutationBatch Args)
-> Maybe [Pos]
-> Bool
-> MutationBatch Args
createOrInheritMutationBatch :: MutationOrder
-> Priority
-> Priority
-> Priority
-> Priority
-> Args
-> Maybe (MutationBatch Args)
-> Maybe [Pos]
-> Bool
-> MutationBatch Args
createOrInheritMutationBatch
MutationOrder
mutationOrder
Priority
randomMutations
Priority
maxGenSize
Priority
randomFragments
Priority
maxMutationDepth
Args
args
Maybe (MutationBatch Args)
parentBatch
Maybe [Pos]
evaluatedPos
Bool
isPassed =
case Maybe (MutationBatch Args)
parentBatch of
Just MutationBatch Args
mb ->
MutationBatch Args
-> Maybe [Pos] -> Bool -> Args -> MutationBatch Args
forall a.
Mutable a =>
MutationBatch a -> Maybe [Pos] -> Bool -> a -> MutationBatch a
newMutationBatchFromParent
MutationBatch Args
mb
Maybe [Pos]
evaluatedPos
Bool
isPassed
Args
args
Maybe (MutationBatch Args)
Nothing ->
MutationOrder
-> Priority
-> Priority
-> Priority
-> Priority
-> Maybe [Pos]
-> Bool
-> Args
-> MutationBatch Args
forall a.
Mutable a =>
MutationOrder
-> Priority
-> Priority
-> Priority
-> Priority
-> Maybe [Pos]
-> Bool
-> a
-> MutationBatch a
newMutationBatch
Tree a -> [a]
MutationOrder
mutationOrder
Priority
randomMutations
Priority
maxGenSize
Priority
randomFragments
Priority
maxMutationDepth
Maybe [Pos]
evaluatedPos
Bool
isPassed
Args
args
nextMutation
:: (Mutable a)
=> FragmentStore
-> MutationBatch a
-> IO (Maybe (a, MutantKind, MutationBatch a))
nextMutation :: forall a.
Mutable a =>
FragmentStore
-> MutationBatch a -> IO (Maybe (a, MutantKind, MutationBatch a))
nextMutation FragmentStore
_ MutationBatch a
batch
| MutationBatch a -> Priority
forall args. MutationBatch args -> Priority
mbMaxMutationDepth MutationBatch a
batch Priority -> Priority -> Bool
forall a. Eq a => a -> a -> Bool
== Priority
0 = Maybe (a, MutantKind, MutationBatch a)
-> IO (Maybe (a, MutantKind, MutationBatch a))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (a, MutantKind, MutationBatch a)
forall a. Maybe a
Nothing
nextMutation FragmentStore
fs MutationBatch a
batch = do
case MutationBatch a -> [Concretized a]
forall args. MutationBatch args -> [Concretized args]
mbCurrBatch MutationBatch a
batch of
[] -> do
case MutationBatch a -> [Pos]
forall args. MutationBatch args -> [Pos]
mbNextPositions MutationBatch a
batch of
[] -> Maybe (a, MutantKind, MutationBatch a)
-> IO (Maybe (a, MutantKind, MutationBatch a))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (a, MutantKind, MutationBatch a)
forall a. Maybe a
Nothing
Pos
pos : [Pos]
ps -> do
let mutants :: [Mutant a]
mutants = Pos -> (forall x. Mutable x => Mutation x) -> Mutation a
forall a.
Mutable a =>
Pos -> (forall x. Mutable x => Mutation x) -> Mutation a
inside Pos
pos Mutation x
forall x. Mutable x => Mutation x
mutate (MutationBatch a -> a
forall args. MutationBatch args -> args
mbArgs MutationBatch a
batch)
queue <-
(Mutant a -> IO [Concretized a])
-> [Mutant a] -> IO [Concretized a]
forall (m :: * -> *) a b. Monad m => (a -> m [b]) -> [a] -> m [b]
concatMapM
( (Priority, Priority)
-> (Priority, FragmentStore) -> Mutant a -> IO [Concretized a]
forall a.
Typeable a =>
(Priority, Priority)
-> (Priority, FragmentStore) -> Mutant a -> IO [Concretized a]
concretize
(MutationBatch a -> Priority
forall args. MutationBatch args -> Priority
mbNumRandomMutations MutationBatch a
batch, MutationBatch a -> Priority
forall args. MutationBatch args -> Priority
mbRandomMutationSize MutationBatch a
batch)
(MutationBatch a -> Priority
forall args. MutationBatch args -> Priority
mbNumRandomMutations MutationBatch a
batch, FragmentStore
fs)
)
[Mutant a]
mutants
case queue of
[] -> do
let mb' :: MutationBatch a
mb' =
MutationBatch a
batch
{ mbNextPositions = ps
, mbPastPositions = pos : mbPastPositions batch
}
FragmentStore
-> MutationBatch a -> IO (Maybe (a, MutantKind, MutationBatch a))
forall a.
Mutable a =>
FragmentStore
-> MutationBatch a -> IO (Maybe (a, MutantKind, MutationBatch a))
nextMutation FragmentStore
fs MutationBatch a
mb'
Concretized MutantKind
kind a
a : [Concretized a]
as -> do
let mb' :: MutationBatch a
mb' =
MutationBatch a
batch
{ mbNextPositions = ps
, mbPastPositions = pos : mbPastPositions batch
, mbCurrBatch = as
}
Maybe (a, MutantKind, MutationBatch a)
-> IO (Maybe (a, MutantKind, MutationBatch a))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((a, MutantKind, MutationBatch a)
-> Maybe (a, MutantKind, MutationBatch a)
forall a. a -> Maybe a
Just (a
a, MutantKind
kind, MutationBatch a
mb'))
Concretized MutantKind
kind a
a : [Concretized a]
as -> do
Maybe (a, MutantKind, MutationBatch a)
-> IO (Maybe (a, MutantKind, MutationBatch a))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((a, MutantKind, MutationBatch a)
-> Maybe (a, MutantKind, MutationBatch a)
forall a. a -> Maybe a
Just (a
a, MutantKind
kind, MutationBatch a
batch{mbCurrBatch = as}))