packages feed

ideas-0.6: src/Domain/Logic/Exercises.hs

-----------------------------------------------------------------------------
-- Copyright 2010, 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)
--
-- Exercise for the logic domain, used for the OUNL course 
-- "Discrete Wiskunde A (DWA)"
--
-----------------------------------------------------------------------------
module Domain.Logic.Exercises 
   ( dnfExercise, dnfUnicodeExercise
   ) where

import Common.Context
import Common.Derivation
import Common.Exercise
import Common.Navigator
import Common.Rewriting (differenceMode)
import Common.Strategy
import Data.Maybe
import Domain.Logic.BuggyRules
import Domain.Logic.Formula
import Domain.Logic.Generator
import Domain.Logic.Parser
import Domain.Logic.Rules
import Domain.Logic.Strategies
import Test.QuickCheck

-- Currently, we use the DWA strategy
dnfExercise :: Exercise SLogic
dnfExercise = makeExercise
   { description    = "Proposition to DNF"
   , exerciseCode   = makeCode "logic" "dnf"
   , status         = Stable
   , parser         = parseLogicPars
   , prettyPrinter  = ppLogicPars
   , equivalence    = eqLogic
   , similarity     = equalLogicA
   , isReady        = isDNF
   , isSuitable     = suitable
   , extraRules     = map liftToContext (logicRules ++ buggyRules)
   , strategy       = dnfStrategyDWA
   , navigation     = navigator
   , difference     = differenceMode eqLogic
   , testGenerator  = Just (restrictGenerator suitable arbitrary)
   , randomExercise = useGenerator (const True) logicExercise
   }

-- Direct support for unicode characters
dnfUnicodeExercise :: Exercise SLogic
dnfUnicodeExercise = dnfExercise
   { description   = description dnfExercise ++ " (unicode support)"
   , exerciseCode  = makeCode "logic" "dnf-unicode"
   , parser        = parseLogicUnicodePars
   , prettyPrinter = ppLogicUnicodePars
   }

logicExercise :: Int -> Gen SLogic
logicExercise n = 
   let (gen, (minStep, maxStep)) 
          | n == 1    = generateLevel Easy
          | n == 3    = generateLevel Difficult 
          | otherwise = generateLevel Normal 
       ok p = let n = fromMaybe maxBound (stepsRemaining maxStep p)
              in countEquivalences p <= 2 && n >= minStep && n <= maxStep
   in restrictGenerator ok gen

suitable :: SLogic -> Bool
suitable = (<=2) . countEquivalences

stepsRemaining :: Int -> SLogic -> Maybe Int
stepsRemaining i = 
   lengthMax i . derivationTree dnfStrategyDWA . inContext dnfExercise

-- QuickCheck property to monitor the number of steps needed 
-- to normalize a random proposition (30-40% is ok)
{-
testGen :: Property
testGen = forAll generateLogic $ \p -> 
   let n = steps p
   in countEquivalences p <= 2 ==> label (show (n >= 4 && n <= 12)) True
   
testme :: IO ()
testme = quickCheck testGen 

start = ((r :<->: p) :||: (q :->: s)) :&&: (Not s :<->: (p :||: r))
 where
  (p, q, r, s) = (Var "p", Var "q", Var "r", Var "s")

go = derivation . emptyState dnfExercise
-}