guarded-rewriting-0.1: performance/PM/Arith/Rules.hs
module PM.Arith.Rules where
import Common.Arith
import Test.QuickCheck
import Data.Ratio
type Rule a = a -> Maybe a
type PropRule = Rule (Prop (Equation Expr))
type EqRule = Rule (Equation Expr)
type ExprRule = Rule Expr
rules :: [PropRule]
rules = [ somewhereProp $ applyOne propRules
, liftToProp $ applyOne eqRules
, liftToProp $ liftToEq $ somewhereExpr $ applyOne exprRules
]
where
propRules :: [PropRule]
propRules =
[ coverPowerEven, divisionByZero
, eqSame, eqDifferent
, andTrueLeft, andTrueRight, andFalseLeft, andFalseRight
, orTrueLeft, orTrueRight, orFalseLeft, orFalseRight
, notTrue, notFalse
]
eqRules :: [EqRule]
eqRules =
[ coverPlusLeft, coverPlusRight, coverMinLeft, coverMinRight
, coverTimesLeft, coverTimesRight, coverDivLeft, coverDivRight
, coverPowerOdd
]
exprRules :: [ExprRule]
exprRules = [timesZeroLeft, timesZeroRight]
go = quickCheck $ forAll (sized propGen) (isSolved . solve rules)
-- Rules
coverPlusLeft :: EqRule
coverPlusLeft (a :+: b :==: c)
| hasVaria a && noVaria b =
Just (a :==: c :-: b)
coverPlusLeft _ = Nothing
coverPlusRight :: EqRule
coverPlusRight (a :+: b :==: c)
| noVaria a && hasVaria b =
Just (b :==: c :-: a)
coverPlusRight _ = Nothing
coverMinLeft :: EqRule
coverMinLeft (a :-: b :==: c)
| hasVaria a && noVaria b =
Just (a :==: c :+: b)
coverMinLeft _ = Nothing
coverMinRight :: EqRule
coverMinRight (a :-: b :==: c)
| noVaria a && hasVaria b =
Just (b :==: a :-: c)
coverMinRight _ = Nothing
coverTimesLeft :: EqRule
coverTimesLeft (a :**: Const b :==: c)
| hasVaria a && b /= 0 =
Just (a :==: c :/: Const b)
coverTimesLeft _ = Nothing
coverTimesRight :: EqRule
coverTimesRight (Const a :**: b :==: c)
| a /= 0 && hasVaria b =
Just (b :==: c :/: Const a)
coverTimesRight _ = Nothing
coverDivLeft :: EqRule
coverDivLeft (a :/: Const b :==: c)
| hasVaria a && b /= 0 =
Just (a :==: c :**: Const b)
coverDivLeft _ = Nothing
coverDivRight :: EqRule
coverDivRight (Const a :/: b :==: c)
| hasVaria b =
Just (b :==: Const a :/: c) -- and b should not be zero here!
coverDivRight _ = Nothing
coverPowerEven :: PropRule
coverPowerEven (VarP (a :^: Const n :==: b))
| hasVaria a && n > 0 && isEven n =
let new = b :^: Const (1/n) in
Just (VarP (a :==: new) :\/: VarP (a :==: Const 0 :-: new))
coverPowerEven _ = Nothing
coverPowerOdd :: EqRule
coverPowerOdd (a :^: Const n :==: b)
| hasVaria a && n > 0 && isOdd n =
Just (a :==: b :^: Const (1/n))
coverPowerOdd _ = Nothing
timesZeroLeft :: ExprRule
timesZeroLeft (Const 0 :**: _) =
Just (Const 0)
timesZeroLeft _ = Nothing
timesZeroRight :: ExprRule
timesZeroRight (_ :**: Const 0) =
Just (Const 0)
timesZeroRight _ = Nothing
divisionByZero :: PropRule
divisionByZero (VarP (a :==: b))
| hasDivisionByZero a || hasDivisionByZero b =
Just F
divisionByZero _ = Nothing
--------------------------------------------------------
-- Rules for comparing the two sides of an equation
eqSame :: PropRule
eqSame (VarP (a :==: b)) | a == b = Just T
eqSame _ = Nothing
eqDifferent :: PropRule
eqDifferent (VarP (Const a :==: Const b)) | a /= b = Just F
eqDifferent _ = Nothing
----------------------------------
-- Propagating boolean constants
andTrueLeft :: PropRule
andTrueLeft (T :/\: p) = Just p
andTrueLeft _ = Nothing
andTrueRight :: PropRule
andTrueRight (p :/\: T) = Just p
andTrueRight _ = Nothing
andFalseLeft :: PropRule
andFalseLeft (F :/\: _) = Just F
andFalseLeft _ = Nothing
andFalseRight :: PropRule
andFalseRight (_ :/\: F) = Just F
andFalseRight _ = Nothing
orTrueLeft :: PropRule
orTrueLeft (T :\/: _) = Just T
orTrueLeft _ = Nothing
orTrueRight :: PropRule
orTrueRight (_ :\/: T) = Just T
orTrueRight _ = Nothing
orFalseLeft :: PropRule
orFalseLeft (F :\/: p) = Just p
orFalseLeft _ = Nothing
orFalseRight :: PropRule
orFalseRight (p :\/: F) = Just p
orFalseRight _ = Nothing
notTrue :: PropRule
notTrue (Not T) = Just F
notTrue _ = Nothing
notFalse :: PropRule
notFalse (Not F) = Just T
notFalse _ = Nothing