ideas-0.7: src/Domain/Math/Polynomial/Strategies.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)
--
-----------------------------------------------------------------------------
module Domain.Math.Polynomial.Strategies
( linearStrategy, linearMixedStrategy, linearStrategyG
, quadraticStrategy, quadraticStrategyG
, higherDegreeStrategy, higherDegreeStrategyG
, findFactorsStrategy, findFactorsStrategyG
) where
import Prelude hiding (repeat, replicate, fail)
import Common.Strategy
import Common.Navigator
import Common.Id
import Common.Uniplate (transform)
import Common.View
import Common.Context
import Domain.Math.Equation.CoverUpRules hiding (coverUpPlus)
import Domain.Math.Polynomial.Rules
import Domain.Math.Numeric.Views
import Domain.Math.Data.OrList
import Domain.Math.Data.Relation
import Domain.Math.Expr
import Domain.Math.Polynomial.CleanUp
import Data.Maybe
import Common.Rewriting
------------------------------------------------------------
-- Linear equations
linearStrategy :: LabeledStrategy (Context (Equation Expr))
linearStrategy = cleanUpStrategy (applyTop (fmap cleanUpSimple)) linearStrategyG
linearMixedStrategy :: LabeledStrategy (Context (Equation Expr))
linearMixedStrategy =
let f = applyTop (fmap (transform (simplify mixedFractionView) . cleanUpSimple))
cfg = [ (byName ruleNormalizeMixedFraction, Reinsert)
, (byName ruleNormalizeRational, Remove)
]
in cleanUpStrategy f (configureNow (configure cfg linearStrategyG))
linearStrategyG :: IsTerm a => LabeledStrategy (Context a)
linearStrategyG =
label "Linear Equation" $
label "Phase 1" (repeat (
use removeDivision
<|> multi (showId distributeTimes) (somewhere (useC parentNotNegCheck <*> use distributeTimes))
<|> multi (showId merge) (once (use merge))))
<*> label "Phase 2" (repeat (
(use flipEquation |> use varToLeft)
<|> use (coverUpPlusWith oneVar)
<|> use (coverUpMinusLeftWith oneVar)
<|> use (coverUpMinusRightWith oneVar)
<|> use coverUpTimes
<|> use coverUpNegate
))
<*> repeat (once
( use ruleNormalizeRational
<|> remove (use ruleNormalizeMixedFraction)
))
------------------------------------------------------------
-- Quadratic equations
quadraticStrategy :: LabeledStrategy (Context (OrList (Relation Expr)))
quadraticStrategy =
cleanUpStrategy (applyTop cleanUpRelations) quadraticStrategyG
quadraticStrategyG :: IsTerm a => LabeledStrategy (Context a)
quadraticStrategyG =
label "Quadratic Equation Strategy" $ repeat $
-- Relaxed strategy: even if there are "nice" factors, allow use of quadratic formula
somewhere (generalForm <|> generalABCForm)
|> somewhere zeroForm
|> somewhere constantForm
|> simplifyForm
|> topForm
where
-- ax^2 + bx + c == 0, without quadratic formula
generalForm = label "general form" $
use commonFactorVar
<|> use noLinFormula
<|> use simplerPolynomial
<|> remove (use bringAToOne)
<|> use niceFactors
<|> use coverUpPower -- to deal with special case x^2=0
generalABCForm = label "abc form" $
useC abcFormula
zeroForm = label "zero form" $
use mulZero
-- expr == c
constantForm = label "constant form" $
use (coverUpPlusWith oneVar)
<|> use (coverUpMinusLeftWith oneVar)
<|> use (coverUpMinusRightWith oneVar)
<|> use coverUpTimes
<|> use coverUpNegate
<|> use coverUpNumerator
<|> use squareBothSides
<|> use factorLeftAsSquare
-- simplifies square roots, or do an approximation
simplifyForm =
label "square root simplification" (
multi (showId simplerSquareRoot) (somewhere (use simplerSquareRoot)))
<|>
remove (label "approximate result" (
multi (showId ruleApproximate) (somewhere (use ruleApproximate))))
topForm = label "top form" $
somewhere (use cancelTerms <|> use sameFactor)
|> ( somewhere (use sameConFactor)
<|> multi (showId merge) (somewhere (use merge))
<|> somewhere (use distributionSquare)
<|> multi (showId distributeTimes) (somewhere
(useC parentNotNegCheck <*> use distributeTimes))
<|> multi (showId distributeDivision) (somewhere
(once (use distributeDivision)))
<|> somewhere (use flipEquation)
)
|> somewhere (use moveToLeft <|> remove (use prepareSplitSquare))
-----------------------------------------------------------
-- Higher degree equations
higherDegreeStrategy :: LabeledStrategy (Context (OrList (Relation Expr)))
higherDegreeStrategy =
cleanUpStrategy (applyTop cleanUpRelations) higherDegreeStrategyG
higherDegreeStrategyG :: IsTerm a => LabeledStrategy (Context a)
higherDegreeStrategyG = label "higher degree" $
higherForm
<*> label "quadratic" quadraticStrategyG
<*> afterSubst
where
higherForm = label "higher degree form" $ repeat $
somewhere (use allPowerFactors)
|> somewhere (
use coverUpPower
<|> use mulZero
<|> use sameFactor
<|> use coverUpTimes
<|> use exposeSameFactor
<|> use (coverUpPlusWith oneVar)
<|> use (coverUpMinusLeftWith oneVar)
<|> use (coverUpMinusRightWith oneVar)
<|> use sameConFactor
<|> useC higherSubst)
|> somewhere (use moveToLeft)
afterSubst = label "afterwards" $ try $
useC substBackVar <*> repeat (somewhere (use coverUpPower))
-----------------------------------------------------------
-- Finding factors in an expression
findFactorsStrategy :: LabeledStrategy (Context Expr)
findFactorsStrategy = cleanUpStrategy (applyTop cleanUpSimple) $
label "find factors" $ replicate 10 $ try findFactorsStrategyG
findFactorsStrategyG :: IsTerm a => LabeledStrategy (Context a)
findFactorsStrategyG = label "find factor step" $
somewhereTimes $
use niceFactorsNew <|> use commonFactorVarNew
<|> use factorVariablePower <|> use simplerLinearFactor
somewhereTimes :: IsStrategy f => f (Context a) -> Strategy (Context a)
somewhereTimes = somewhereWith "SomewhereTimes" $ \c ->
if isTimesC c then [0 .. arity c-1] else []
isTimesC :: Context a -> Bool
isTimesC = maybe False (isJust . isTimes :: Term -> Bool) . currentT