packages feed

guarded-rewriting-0.1: performance/Common/LogicStrategies.hs

-----------------------------------------------------------------------------
-- Copyright 2008, Open Universiteit Nederland. This file is distributed 
-- under the terms of the GNU General Public License. For more information, 
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer  :  bastiaan.heeren@ou.nl
-- Stability   :  provisional
-- Portability :  portable (depends on ghc)
--
-----------------------------------------------------------------------------
module Common.LogicStrategies where

import Prelude hiding (repeat)
import Common.LogicRules
import Common.Logic
import Common.LogicGenerator
import Test.QuickCheck hiding (label)
import System.Random
import Common.GuardedRewriting
import Control.Monad

type Strategy a = a -> [a]

label _ = id
(s <*> t) a = [c | b <- s a, c <- t b]
(s <|> t) a = s a ++ t a
many s = return <|> (s <*> many s)
repeat s = many s <*> notS s
alternatives = foldr (<|>) (const [])
notS s a = if null (s a) then [a] else []

-- --------------------------------------
-- Strategies
-- --------------------------------------
-- Same monad to that in the SYB3 paper
data S m a = S a (m a)

instance MonadPlus m => Monad (S m) where
  return x = S x mzero
  (S x xs) >>= k
    = S r (rs1 `mplus` rs2)
      where
        S r rs1 = k x
        rs2 = do x <- xs
                 let S r _ = k x
                 return r

-- This is like Stratego's one.
-- It applies f to one of the immediate children of x.
{-
one :: (Rewritable a, MonadPlus m, Functor m) => (a -> m a) -> a -> m a
one f x = fmap (from . In) rs
  where
    S _ rs = fmapM try_f $ out $ to x
    try_f x = S x (f_str x)
    f_str = fmap to . f . from
-}

-- Apply f once to one of the nodes of x
-- Mirrors the corresponding definition in Stratego
once :: (Rewritable a, MonadPlus m, Functor m) => (a -> m a) -> a -> m a
once f x = f x `mplus` one (once f) x


-- applies a strategy at one location
-- see http://ideas.cs.uu.nl/trac/browser/Feedback/trunk/src/Common/Strategy.hs
somewhere :: Rewritable a => Strategy a -> Strategy a
somewhere = once

lift :: Rewritable a => Rule' a -> Strategy a
lift r = (:[]) . rewrite' r

liftl :: Rewritable a => [Rule' a] -> Strategy a
liftl = alternatives . map lift

eliminateConstants :: Strategy (Logic)
eliminateConstants = repeat $ somewhere $
   alternatives $
      [ liftl ruleFalseZeroOr, liftl ruleTrueZeroOr, liftl ruleTrueZeroAnd
      , liftl ruleFalseZeroAnd, liftl ruleNotBoolConst, liftl ruleFalseInEquiv
      , liftl ruleTrueInEquiv, liftl ruleFalseInImpl, liftl ruleTrueInImpl
      ]

eliminateImplEquiv :: Strategy (Logic)
eliminateImplEquiv = repeat $ somewhere $
          lift ruleDefImpl
      <|> lift ruleDefEquiv
      
eliminateNots :: Strategy (Logic)
eliminateNots = repeat $ somewhere $ 
          lift ruleDeMorganAnd
      <|> lift ruleDeMorganOr
      <|> lift ruleNotNot
      
orToTop :: Strategy (Logic)
orToTop = repeat $ somewhere $ liftl ruleAndOverOr

toDNF :: Strategy (Logic)
toDNF =  label "Bring to dnf"
      $  label "Eliminate constants"                 eliminateConstants
     <*> label "Eliminate implications/equivalences" eliminateImplEquiv
     <*> label "Eliminate nots"                      eliminateNots 
     <*> label "Move ors to top"                     orToTop
     
propSound :: Logic -> Bool
propSound p = 
   case toDNF p of
      x:_ -> isDNF x
      _   -> False
      
propView :: Logic -> Bool
propView p = p == from (to p)

checks :: IO ()
checks = do
   quickCheck propView
   quickCheck propSound

main :: IO ()
main = print $ all checkOne [0..1000]
 where
   checkOne n = 
      propSound (generate n (mkStdGen n) generateLogic)