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

    Maintainer  :  <EMAIL>
    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.NumericOrder as NumOrd
import Numeric.AERN.NumericOrder.OpsImplicitEffort

import qualified Numeric.AERN.RefinementOrder as RefOrd

import Numeric.AERN.Basics.Effort

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
    (EffortIndicator (DistanceEffortIndicator t))
    => 
    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
    isExactEff :: ImprecisionEffortIndicator t -> t -> Maybe Bool

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)
        ]

        <commit_msg>make list instance of HasImprecision using the max norm<commit_after>{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ImplicitParams #-}
{-|
    Module      :  Numeric.AERN.RealArithmetic.Measures
    Description :  measures of quality for approximations
    Copyright   :  (c) <NAME>
    License     :  BSD3

    Maintainer  :  <EMAIL>
    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.NumericOrder as NumOrd
import Numeric.AERN.NumericOrder.OpsImplicitEffort

import qualified Numeric.AERN.RefinementOrder as RefOrd

import Numeric.AERN.Basics.Effort

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
    (EffortIndicator (DistanceEffortIndicator t))
    => 
    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
    isExactEff :: ImprecisionEffortIndicator t -> t -> Maybe Bool

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)
        ]

instance 
    (HasImprecision t,
     NumOrd.RefinementRoundedLattice (Imprecision t)) 
    => 
    HasImprecision [t]
    where
    type Imprecision [t] = Imprecision t
    type ImprecisionEffortIndicator [t] = 
        (ImprecisionEffortIndicator t, NumOrd.MinmaxInOutEffortIndicator (Imprecision t))
    imprecisionDefaultEffort (h : _) =
        (effImpr, NumOrd.minmaxInOutDefaultEffort (imprecisionOfEff effImpr h))
        where
        effImpr = imprecisionDefaultEffort h
    imprecisionOfEff (effImpr, effMax) list@(_:_) =
        foldl1 (NumOrd.maxOutEff effMax) $ map (imprecisionOfEff effImpr) list
    isExactEff (eff, _) list =
        fmap and $ sequence $ map (isExactEff eff) list
         
{'fraction_non_alphanumeric': 0.0814463955637708, 'fraction_numerical': 0.006353974121996303, 'mean_word_length': 3.1341929321872017, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 74, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1212155', 'n_tokens_mistral': 2732, 'n_tokens_neox': 2660, 'n_words': 698}