packages feed

AERN-Real-2011.1: src/Numeric/AERN/RealArithmetic/Measures.hs

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ImplicitParams #-}
{-|
    Module      :  Numeric.AERN.RealArithmetic.Measures
    Description :  measures of quality for approximations
    Copyright   :  (c) Michal Konecny
    License     :  BSD3

    Maintainer  :  mikkonecny@gmail.com
    Stability   :  experimental
    Portability :  portable
    
    Measures of quality for approximations.
-}
module Numeric.AERN.RealArithmetic.Measures where

import {-# Source #-} Numeric.AERN.RealArithmetic.RefinementOrderRounding.FieldOps

import qualified Numeric.AERN.Basics.NumericOrder as NumOrd
import Numeric.AERN.Basics.NumericOrder.OpsImplicitEffort

import qualified Numeric.AERN.Basics.RefinementOrder as RefOrd

import Test.QuickCheck
import Test.Framework (testGroup, Test)
import Test.Framework.Providers.QuickCheck2 (testProperty)

{-|
   Ability to measure a distance.  Distance
   should be a numeric type approximating the
   positive real numbers with Partial comparison.
-}
class HasDistance t where
    type Distance t
    type DistanceEffortIndicator t
    distanceDefaultEffort :: t -> (DistanceEffortIndicator t)
    {-| distance measure -}
    distanceBetweenEff :: 
        DistanceEffortIndicator t -> t -> t -> Distance t

propDistanceTriangular :: 
    (HasDistance t, 
     NumOrd.PartialComparison (Distance t),
     RoundedAdd (Distance t)
    ) =>
    t ->
    (DistanceEffortIndicator t) ->     
    (NumOrd.PartialCompareEffortIndicator (Distance t)) -> 
    (AddEffortIndicator (Distance t)) ->     
    t -> t -> t -> Bool
propDistanceTriangular _ effortDist effortComp effortAdd e1 e2 e3 =
    let ?pCompareEffort = effortComp in 
    let (<+>) = addOutEff effortAdd in 
        let
        d12 = distanceBetweenEff effortDist e1 e2
        d23 = distanceBetweenEff effortDist e2 e3
        d13 = distanceBetweenEff effortDist e1 e3
        in
        case (d12 <+> d23) >=? d13 of
            Nothing -> True
            Just b -> b

testsDistance ::
    (HasDistance t, 
     NumOrd.PartialComparison (Distance t),
     RoundedAdd (Distance t),
     Arbitrary (NumOrd.PartialCompareEffortIndicator (Distance t)), 
     Show (NumOrd.PartialCompareEffortIndicator (Distance t)),
     Arbitrary (AddEffortIndicator (Distance t)), 
     Show (AddEffortIndicator (Distance t)),
     Arbitrary (DistanceEffortIndicator t), 
     Show (DistanceEffortIndicator t), 
     Arbitrary t, Show t) =>
    (String, t) -> Test
testsDistance (name, sample) =
    testGroup (name ++ " distance measure") $ 
        [
         testProperty "triangle inequality" (propDistanceTriangular sample)
        ]

{-|
   A numeric measure of imprecision of approximations.
   A zero imprecision means the approximation is exact.
   The imprecision type should support Partial comparison.
-}
class HasImprecision t where
    type Imprecision t
    type ImprecisionEffortIndicator t
    imprecisionDefaultEffort :: t -> ImprecisionEffortIndicator t
    imprecisionOfEff :: ImprecisionEffortIndicator t -> t -> Imprecision t

propImprecisionDecreasesWithRefinement ::
    (HasImprecision t, NumOrd.PartialComparison (Imprecision t)) =>
    t -> 
    (ImprecisionEffortIndicator t) -> 
    (NumOrd.PartialCompareEffortIndicator (Imprecision t)) -> 
    RefOrd.LEPair t -> Bool
propImprecisionDecreasesWithRefinement _ effortImpr effortComp (RefOrd.LEPair (e1,e2)) =
    let 
    ?pCompareEffort = effortComp 
    in
    case (imprecisionOfEff effortImpr e1) >=? (imprecisionOfEff effortImpr e2) of
        Nothing -> True
        Just b -> b

testsImprecision (name, sample) =
    testGroup (name ++ " imprecision measure") $ 
        [
         testProperty "decreases with refinement" (propImprecisionDecreasesWithRefinement sample)
        ]