% Depth Limiting for Non-Deterministic Computations.
% Sebastian Fischer (sebf@informatik.uni-kiel.de)
This module provides a strategy transformer that extends the
evaluation context with a limit for the search depth.
>
>
> module CFLP.Strategies.DepthLimit (
>
> DepthLimiter(..), DepthLim, DepthLimCtx, limitDepth, setDepthLimit
>
> ) where
>
> import Control.Monad
>
> import CFLP.Control.Monad.Update
>
> import CFLP.Control.Strategy
>
> import CFLP.Strategies.DepthCounter
The interface of an evaluation context that can store a depth limit
is given by the following type class.
> class DepthLimiter c
> where
> depthLimit :: c -> Int
> resetDepthLimit :: c -> Int -> c -> c
We define uniform liftings for depth limiters over arbitrary context
transformers.
> instance (DepthLimiter c, Transformer t) => DepthLimiter (t c)
> where
> depthLimit = depthLimit . project
>
> resetDepthLimit _ l c = replace c (resetDepthLimit undefined l (project c))
The default limit is 100, but you can use the operation
`setDepthLimit` in computations to change it.
> defaultLimit :: Int
> defaultLimit = 100
>
> setDepthLimit :: (Monad s, DepthLimiter c, MonadUpdate c s)
> => c -> Int -> s ()
> setDepthLimit c l = update (return . resetDepthLimit c l)
A depth limiting context adds a depth limit to the evaluation context.
> data DepthLimCtx c = DepthLimCtx Int c
It is an instance of `DepthLimiter`.
> instance DepthLimiter (DepthLimCtx c)
> where
> depthLimit (DepthLimCtx l _) = l
>
> resetDepthLimit _ l (DepthLimCtx _ c) = DepthLimCtx l c
It also is a transformer for evaluation contexts
> instance Transformer DepthLimCtx
> where
> project (DepthLimCtx _ c) = c
> replace (DepthLimCtx l _) = DepthLimCtx l
We define a strategy transformer for depth limiting.
> newtype DepthLim s a = DepthLim { fromDepthLim :: s a }
> deriving (Monad, MonadPlus, Enumerable)
>
> type instance Ctx (DepthLim s) = DepthLimCtx (Ctx s)
> type instance Res (DepthLim s) = DepthLim (Res s)
The operation `depthCounter` the `Depth` constructor.
> limitDepth :: s a -> DepthLim s a
> limitDepth = DepthLim
The strategy-transformer instance increments the counter at each
non-deterministic choice and prunes the choices if the limit is
exceeded.
> instance (DepthCounter c, DepthLimiter c) => StrategyT c DepthLim
> where
> liftStrategy _ = DepthLim
> baseStrategy _ = fromDepthLim
>
> extendContext _ = DepthLimCtx defaultLimit
>
> extendChoices c _ xs
> | currentDepth c < depthLimit c
> = map (update (return . incrementDepth c)>>) xs
> | otherwise = []