packages feed

ideas-0.7: src/Domain/Math/Power/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  :  alex.gerdes@ou.nl
-- Stability   :  provisional
-- Portability :  portable (depends on ghc)
--
-----------------------------------------------------------------------------

module Domain.Math.Power.Exercises    
   ( -- * Power exercises
     simplifyPowerExercise
   , powerOfExercise 
   , nonNegBrokenExpExercise
   , calcPowerExercise
   ) where

import Prelude hiding ( (^) )

import Common.Classes 
import Common.Context
import Common.Exercise
import Common.Navigator
import Common.Rewriting
import Common.Strategy hiding (not, replicate)
import Common.Utils (distinct)
import Common.View
import Data.Maybe
import Domain.Math.Examples.DWO3
import Domain.Math.Expr hiding (isPower)
import Domain.Math.Numeric.Views
import Domain.Math.Power.Rules
import Domain.Math.Power.Strategies
import Domain.Math.Power.NormViews
import Domain.Math.Power.Views


-- | Exercises ----------------------------------------------------------------

powerExercise :: LabeledStrategy (Context Expr) -> Exercise Expr
powerExercise s = makeExercise 
   { status        = Provisional
   , parser        = parseExpr
   , navigation    = navigator                     
   , strategy      = s
   }

simplifyPowerExercise :: Exercise Expr
simplifyPowerExercise = (powerExercise simplifyPowerStrategy)
   { exerciseId   = describe "simplify expression (powers)" $ 
                       newId "algebra.manipulation.exponents.simplify"
   , isReady      = isPowerAdd
   , isSuitable   = (`belongsTo` normPowerMapView)
   , equivalence  = viewEquivalent normPowerMapView
   , examples     = concat $  simplerPowers 
                           ++ powers1 ++ powers2 
                           ++ negExp1 ++ negExp2
                           ++ normPower1 ++ normPower2 ++ normPower3
   , ruleOrdering = ruleOrderingWithId $ map getId
                      [ root2power, subExponents, reciprocalVar, addExponents
                      , mulExponents, distributePower ]
   }

powerOfExercise :: Exercise Expr
powerOfExercise = (powerExercise powerOfStrategy)
   { exerciseId   = describe "write as a power of a" $ 
                       newId "algebra.manipulation.exponents.powerof"
   , isReady      = isSimplePower
   , isSuitable   = (`belongsTo` normPowerView)
   , equivalence  = viewEquivalent normPowerNonNegRatio
   , examples     = concat $  powersOfA ++ powersOfX 
                           ++ brokenExp1' ++ brokenExp2 ++ brokenExp3 
                           ++ normPower5' ++ normPower6
   , ruleOrdering = ruleOrderingWithId $ map getId
                      [ root2power, addExponents, subExponents, mulExponents
                      ,  distributePower, reciprocalVar ]
   }

nonNegBrokenExpExercise :: Exercise Expr
nonNegBrokenExpExercise = (powerExercise nonNegBrokenExpStrategy)
   { exerciseId   = describe "write with a non-negative exponent" $ 
                       newId "algebra.manipulation.exponents.nonnegative"
   , isReady      = isPower plainNatView
   , isSuitable   = (`belongsTo` normPowerNonNegDouble)
   , equivalence  = viewEquivalent normPowerNonNegDouble
   , examples     = concat $  nonNegExp ++ nonNegExp2 ++ negExp4 ++ negExp5 
                           ++ brokenExp1 
                           ++ normPower4' ++ normPower5
   , ruleOrdering = ruleOrderingWithId [ getId mulExponents
                                       , getId reciprocalFrac
                                       , getId reciprocalInv
                                       , getId power2root
                                       , getId distributePower ]
   }

calcPowerExercise :: Exercise Expr
calcPowerExercise = (powerExercise calcPowerStrategy)
   { exerciseId   = describe "simplify expression (powers)" $ 
                       newId "arithmetic.exponents"
   , isReady      = isPowerAdd
   , isSuitable   = (`belongsTo` normPowerMapView)
   , equivalence  = viewEquivalent normPowerMapView
   , examples     = concat $ negExp3 ++ normPower3' ++ normPower4
   }


-- | Ready checks -------------------------------------------------------------

isSimplePower :: Expr -> Bool
isSimplePower (Sym s [Var _, y]) 
                 | isPowerSymbol s = y `belongsTo` rationalView
isSimplePower _ = False

isPower :: View Expr a -> Expr -> Bool
isPower v expr = 
  let Just (_, xs) = match productView expr 
      f (Nat 1 :/: a) = g a
      f a = g a
      g (Sym s [Var _, a]) | isPowerSymbol s = isJust (match v a)
      g (Sym s [x, Nat _]) | isRootSymbol s = isPower v x 
      g (Sqrt x) = g x
      g (Var _) = True
      g a = a `belongsTo` rationalView
  in distinct (concatMap vars xs) && all f xs
     
isPowerAdd :: Expr -> Bool
isPowerAdd expr =
  let Just xs = match sumView expr
  in all (isPower rationalView) xs && not (applicable calcPowerPlus expr)