ideas-statistics-1.0: src/Domain/Hypothesis/Exercises.hs
-----------------------------------------------------------------------------
-- Copyright 2020, Ideas project team. This file is distributed under the
-- terms of the Apache License 2.0. For more information, see the files
-- "LICENSE.txt" and "NOTICE.txt", which are included in the distribution.
-----------------------------------------------------------------------------
module Domain.Hypothesis.Exercises (hypothesisExercise) where
import Control.Monad
import qualified Data.Map as M
import Data.List
import Data.Maybe
import Domain.Math.Data.Relation
import Domain.Hypothesis.Examples
import Domain.Hypothesis.Constraints
import Domain.Hypothesis.BuggyRules
import Domain.Hypothesis.Rules
import Domain.Hypothesis.Strategies
import Domain.Statistics.ComponentSet
import Domain.Statistics.Parser
import Ideas.Common.Library hiding (Predicate)
import Domain.Math.Expr.Data
import Ideas.Encoding.OpenMathSupport
import Ideas.Utils.Uniplate
import Ideas.Text.XML hiding (children)
import Prelude hiding (until)
-- Debug functions
css :: [ComponentSet]
css = mapMaybe fromContext $ concatMap terms $
mapMaybe (defaultDerivation hypothesisExercise) (examplesAsList hypothesisExercise)
_testPP :: IO ()
_testPP = forM_ css $ \x ->
let s = prettyPrinter hypothesisExercise x in
case parser hypothesisExercise s of
Right y | x == y -> putChar '.'
| otherwise -> error $ show (x, y)
Left msg -> error $ s ++ "\n" ++ msg
_testOM :: IO ()
_testOM = forM_ css $ \x ->
case toOpenMath hypothesisExercise x of
Right omobj ->
case fromOpenMath hypothesisExercise omobj of
Just y | x == y -> putChar '.'
| otherwise -> error $ "Not the same:\n" ++ show x ++ "\n" ++ show y
Nothing -> error $ show omobj
Left msg -> error $ show x ++ "\n" ++ msg
_see :: Int -> IO ()
_see n = printDerivation hypothesisExercise (examplesAsList hypothesisExercise !! n)
_testje :: IO ()
_testje = printDerivation hypothesisExercise opgave_5_4
_save :: IO ()
_save = do
let pilot = [("A", mayPilotA), ("B", mayPilotB), ("C", mayPilotC), ("D", mayPilotD)]
ex = hypothesisExercise
forM_ pilot $ \(n, cs) -> do
writeFile ("Task" ++ n ++ ".txt") $ showDerivation ex cs
writeFile ("Task" ++ n ++ "-OM.txt") $ showDerivationOM ex cs
showDerivationOM :: Exercise a -> a -> String
showDerivationOM ex a =
case defaultDerivation ex a of
Just d -> show $ biMap fst f d
Nothing -> "no derivation"
where
errorXML = makeXML "error" mempty
f ctx = fromMaybe errorXML $ do
x <- fromContext ctx
omobj <- toOpenMath ex x
return (toXML omobj)
------------------------------
hypothesisExercise :: Exercise ComponentSet
hypothesisExercise = emptyExercise
{ exerciseId = describe "Hypothesis testing" $ newId "hypothesis"
, prettyPrinter = show
, status = Experimental
, parser = parseComponentSet
, strategy = liftToContext hypothesisStrategy
, extraRules = fmap liftToContext buggyRules
, ruleOrdering = ruleOrderingWith highPriorityRules
, examples = examplesWithDifficulty [ (Medium, cs) | cs <- opgavenSW ++ opgavenEconomie ] -- hypothesisExamples
, equivalence = withoutContext eqComponentSet
, similarity = withoutContext similarComponentSet
, constraints = map liftToContext hypothesisConstraints
, hasTypeable = useTypeable
, ready = predicate (hasConclusionHypotheses <&&> checkConstraints)
, hasTermView = Just termView
}
highPriorityRules :: [Rule ComponentSet]
highPriorityRules =
[ addHypothesesRule
, lookupTValueRule, lookupZValueRule
, computePValueTTest, computePValueZTest
, addTestValueRule
, hypothesesConclusionCriticalRule, hypothesesConclusionPValueRule
-- buggy rules
, buggyTValueSided, buggyTValueTestValue -- Sietske: higher priority than corresponding buggy alpha rule
, buggyRValueSided, buggyRValueTestValue -- idem
, buggyZValueSided, buggyZValueTestValue
, buggyChiValueSided, buggyChiValueTestValue
]
----------------------------------------------------------
-- Equivalence
eqComponentSet :: ComponentSet -> ComponentSet -> Bool
eqComponentSet x y = compareIntials
&& checkConstraints x
&& checkConstraints y
where
compareIntials =
M.fromList (toList (initials x)) == M.fromList (toList (initials y))
checkConstraints :: ComponentSet -> Bool
checkConstraints cs =
all (`checkConstraint` cs) hypothesisConstraints
checkConstraint :: Constraint ComponentSet -> ComponentSet -> Bool
checkConstraint p cs
| not (isRelevant p cs) = True
| otherwise = isSatisfied p cs
----------------------------------------------------------
-- Similarity
-- To do: not all component ids compare doubles with the same precision
-- (e.g. pvalue uses 3 decimals, default is 2)
similarComponentSet :: ComponentSet -> ComponentSet -> Bool
similarComponentSet cs1 cs2 = sorted cs1 `eqList` sorted cs2
where
sorted = map f . sortOn fst . toList
where
f (n, CExpr e) = (n, CExpr (normalizeExpr e))
f (n, CRelation r) = (n, CRelation (fmap normalizeExpr r))
f (n, c) = (n, c)
eqList :: [(ComponentId, Component)] -> [(ComponentId, Component)] -> Bool
eqList xs ys = length xs == length ys && all (\((a, x), (b, y)) -> a == b && x `eqComponent` y) (zip xs ys)
eqComponent :: Component -> Component -> Bool
eqComponent (CExpr x) (CExpr y) = eqExpr x y
eqComponent (CRelation x) (CRelation y) =
eqExpr (leftHandSide x) (leftHandSide y) && eqExpr (rightHandSide x) (rightHandSide y)
&& relationType x == relationType y
eqComponent x y = x == y
eqExprs :: [Expr] -> [Expr] -> Bool
eqExprs [] [] = True
eqExprs (x:xs) (y:ys) = eqExpr x y && eqExprs xs ys
eqExprs _ _ = False
eqExpr :: Expr -> Expr -> Bool
eqExpr (Number x) (Number y) = equalDouble x y
eqExpr x y =
case (getFunction x, getFunction y) of
(Just (f, xs), Just (g, ys)) -> f == g && xs `eqExprs` ys
_ -> x == y
-- we vouwen hier de definities uit zodat we formules kunnen herkennen
-- afronden op 2 decimalen: beter is om expressies component-gewijs te
-- vergelijken en daarbij de hulpfunctie 'equal' te gebruiken
normalizeExpr :: Expr -> Expr
normalizeExpr (Var "sigmaM") = Var "sigma" / sqrt (Var "n")
normalizeExpr (Var "SEM") = Var "s" / sqrt (Var "n")
normalizeExpr (Nat n) = Number (fromInteger n)
normalizeExpr expr = descend normalizeExpr expr
-- | Test whether the conclusionhypothesis is present in the componentset. If
-- the predicate holds then he exercise is considered /done/.
hasConclusionHypotheses :: ComponentSet -> Bool
hasConclusionHypotheses cs = contains cs ConclusionHypotheses