-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Manipulating numbers with inherent experimental/measurement uncertainty -- -- See README.md. -- -- Documentation maintained at https://mstksg.github.io/uncertain @package uncertain @version 0.3.0.0 module Numeric.Uncertain -- | Represents an independent experimental value centered around a mean -- value with "inherent" and independent uncertainty. -- -- Mostly useful due to its instances of numeric typeclasses like -- Num, Fractional, etc., which allows you to add and -- multiply and apply arbitrary numerical functions to them and have the -- uncertainty propagate appropriately. You can also lift arbitrary -- (sufficiently polymorphic) functions with liftU, liftUF, -- liftU2 and family. -- --
-- ghci> let x = 1.52 +/- 0.07 -- ghci> let y = 781.4 +/- 0.3 -- ghci> let z = 1.53e-1 `withPrecision' 3 -- ghci> cosh x -- 2.4 +/- 0.2 -- ghci> exp x / z * sin (y ** z) -- 10.9 +/- 0.9 -- ghci> pi + 3 * logBase x y -- 52 +/- 5 ---- -- Uncertaintly is properly propagated according to the second-degree -- taylor series approximations of the applied functions. However, if the -- higher-degree terms are large with respect to to the means and -- variances of the uncertain values, these approximations may be -- inaccurate. -- -- Can be created with exact to represent an "exact" measurement -- with no uncertainty, +/- and :+/- to specify a standard -- deviation as a range, withPrecision to specify through decimal -- precision, and withVar to specify with a variance. Can also be -- inferred from a list of samples with fromSamples -- --
-- 7.13 +/- 0.05 -- 91800 +/- 100 -- 12.5 `withVar' 0.36 -- exact 7.9512 -- 81.42 `withPrecision' 4 -- 7 :: Uncertain Double -- 9.18 :: Uncertain Double -- fromSamples [12.5, 12.7, 12.6, 12.6, 12.5] ---- -- Can be deconstructed with :+/-, the pattern -- synonym/pseudo-constructor which matches on the mean and a standard -- deviation (supported on GHC 7.8+, with bidirectional constructor -- functionality supported on GHC 7.10+). You can also access properties -- with uMean, uStd, uVar, uMeanStd, -- uMeanVar, uRange, etc. -- -- It's important to remember that each "occurrence" represents a unique -- independent sample, so: -- --
-- ghci> let x = 15 +/- 2 in x + x -- 30 +/- 3 -- -- ghci> let x = 15 +/- 2 in x*2 -- 30 +/- 4 ---- -- x + x does not represent adding the same sample to itself -- twice, it represents independently sampling two values within -- the range 15 +/- 2 and adding them together. In general, -- errors and deviations will cancel each-other out, leading to a smaller -- uncertainty. -- -- However, x*2 represents taking one sample and -- multiplying it by two. This yields a greater uncertainty, because -- errors and deviations are amplified. -- -- Also be aware that the Show instance "normalizes" the result, -- and won't show any mean/central point to a decimal precision smaller -- than the uncertainty, rounding off the excess. data Uncert a -- | Pattern match on an Uncert with its central value and its -- standard deviation (see uStd for clarification). -- -- Can also be used to construct an Uncert, identically as -- +/-. -- -- Note: Only supported on GHC 7.8 and above. Bidirectional -- functionality (to allow use as a constructor) only supported on GHC -- 7.10 and above. -- | Create an Uncert around a central value and a given "range" of -- uncertainty. The range is interpreted as the standard deviation of the -- underlying random variable. Might be preferrable over :+/- -- because it is more general (doesn't require a Floating -- constraint) and looks a bit nicer. -- -- See uStd for more details. (+/-) :: Num a => a -> a -> Uncert a -- | Create an Uncert with an exact value and 0 uncertainty. exact :: Num a => a -> Uncert a -- | Create an Uncert about a given approximate central value, with -- the given number of digits of precision (in decimal notation). -- --
-- 5.21 withPrecision 3 ≡ 5.21 +/- 0.01 --withPrecision :: (Floating a, RealFrac a) => a -> Int -> Uncert a -- | Like withPrecision, except takes a number of "digits" of -- precision in the desired numeric base. For example, in base 2, takes -- the number of bits of precision. -- --
-- withPrecision ≡ withPrecisionAtBase 10 --withPrecisionAtBase :: (Floating a, RealFrac a) => Int -> a -> Int -> Uncert a -- | Create an Uncert around a central value, specifying its -- uncertainty with a given variance. The variance is taken to be -- proportional to the square of the range of uncertainty. See -- uStd for more details. -- -- "Negative variances" are treated as positive. withVar :: Num a => a -> a -> Uncert a -- | Infer an Uncert from a given list of independent samples -- of an underlying uncertain or random distribution. fromSamples :: Fractional a => [a] -> Uncert a -- | Get the meancentral valueexpected value of an Uncert. uMean :: Uncert a -> a -- | Get the variance of the uncertainty of an Uncert, -- proportional to the square of "how uncertain" a value is. Is the -- square of uStd. uVar :: Uncert a -> a -- | Get the standard deviation of the uncertainty of an -- Uncert, proportional to "how uncertain" a value is. -- -- Very informally, it can be thought of as the interval above and below -- the mean that about 68% of sampled values will fall under after -- repeated sampling, or as the range that one is 68% sure the true value -- is within. -- -- Is the square root of uVar. uStd :: Floating a => Uncert a -> a -- | Retrieve both the mean (central) value and the underlying variance of -- an Uncert together. -- --
-- uMeanVar ≡ uMean &&& uVar --uMeanVar :: Uncert a -> (a, a) -- | Retreve both the mean (central) value and the underlying standard -- deviation of an Uncert together. (See uStd for more -- details) -- --
-- uMeanStd ≡ uMean &&& uStd --uMeanStd :: Floating a => Uncert a -> (a, a) -- | Retrieve the "range" of the underlying distribution of an -- Uncert, derived from the standard deviation, where which -- approximly 68% of sampled values are expected to occur (or within -- which you are 68% certain the true value is). -- --
-- uRange (x +/- dx) ≡ (x - dx, x + dx) --uRange :: Floating a => Uncert a -> (a, a) -- | Lifts a numeric function over an Uncert. Correctly propagates -- the uncertainty according to the second-order taylor expansion -- expansion of the function. Note that if the higher-degree taylor -- series terms are large with respect to the mean and variance, this -- approximation may be inaccurate. -- -- Should take any function sufficiently polymorphic over numeric types, -- so you can use things like sqrt, sin, negate, -- etc. -- --
-- ghci> liftU (x -> log x ^ 2) (12.2 +/- 0.5) -- 6.3 +/- 0.2 --liftU :: Fractional a => (forall s. AD s (Tower a) -> AD s (Tower a)) -> Uncert a -> Uncert a -- | Lifts a two-argument (curried) function over two Uncerts. -- Correctly propagates the uncertainty according to the second-order -- (multivariate) taylor expansion expansion of the function. Note that -- if the higher-degree taylor series terms are large with respect to the -- mean and variance, this approximation may be inaccurate. -- -- Should take any function sufficiently polymorphic over numeric types, -- so you can use things like *, atan2, **, etc. -- --
-- ghci> liftU2 (x y -> x**y) (13.5 +- 0.1) (1.64 +- 0.08) -- 70 +/- 10 --liftU2 :: Fractional a => (forall s. AD s (Sparse a) -> AD s (Sparse a) -> AD s (Sparse a)) -> Uncert a -> Uncert a -> Uncert a -- | Lifts a three-argument (curried) function over three Uncerts. -- See liftU2 and liftUF for more details. liftU3 :: Fractional a => (forall s. AD s (Sparse a) -> AD s (Sparse a) -> AD s (Sparse a) -> AD s (Sparse a)) -> Uncert a -> Uncert a -> Uncert a -> Uncert a -- | Lifts a four-argument (curried) function over four Uncerts. See -- liftU2 and liftUF for more details. liftU4 :: Fractional a => (forall s. AD s (Sparse a) -> AD s (Sparse a) -> AD s (Sparse a) -> AD s (Sparse a) -> AD s (Sparse a)) -> Uncert a -> Uncert a -> Uncert a -> Uncert a -> Uncert a -- | Lifts a five-argument (curried) function over five Uncerts. See -- liftU2 and liftUF for more details. liftU5 :: Fractional a => (forall s. AD s (Sparse a) -> AD s (Sparse a) -> AD s (Sparse a) -> AD s (Sparse a) -> AD s (Sparse a) -> AD s (Sparse a)) -> Uncert a -> Uncert a -> Uncert a -> Uncert a -> Uncert a -> Uncert a -- | Lifts a multivariate numeric function on a container (given as an -- f a -> a) to work on a container of Uncerts. -- Correctly propagates the uncertainty according to the second-order -- (multivariate) taylor expansion of the function. Note that if the -- higher-degree taylor series terms are large with respect to the means -- and variances, this approximation may be inaccurate. -- -- Should take any function sufficiently polymorphic over numeric types, -- so you can use things like *, sqrt, atan2, etc. -- --
-- ghci> liftUF ([x,y,z] -> x*y+z) [12.2 +- 0.5, 56 +- 2, 0.12 +/- 0.08] -- 680 +/- 40 --liftUF :: (Traversable f, Fractional a) => (forall s. f (AD s (Sparse a)) -> AD s (Sparse a)) -> f (Uncert a) -> Uncert a -- | Attempts to "normalize" an Uncert. Rounds the uncertainty (the -- standard deviation) to one digit of precision, and rounds the central -- moment up to the implied precision. -- -- For example, it makes no real sense to have 542.185433 +/- -- 83.584, because the extra digits of 542.185433 past the -- tens place has no meaning because of the overpowering uncertainty. -- Normalizing this results in 540 +/- 80. -- -- Note that the Show instance for Uncert normalizes values -- before showing them. uNormalize :: (Floating a, RealFrac a) => Uncert a -> Uncert a -- | Like uNormalize, but takes a numerical base to round with -- respect to. -- --
-- uNormalize ≡ uNormalizeAtBase 10 --uNormalizeAtBase :: (Floating a, RealFrac a) => Int -> Uncert a -> Uncert a -- | Like show for Uncert, but does not normalize the value -- (see uNormalize) before showing. -- --
-- show ≡ uShow . uNormalize --uShow :: (Show a, Floating a) => Uncert a -> String -- | Like showsPrec for Uncert, but does not normalize the -- value (see uNormalize) before showing. See documentation for -- showsPrec for more information on how this is meant to be used. uShowsPrec :: (Show a, Floating a) => Int -> Uncert a -> ShowS instance GHC.Generics.Selector Numeric.Uncertain.S1_0_1Uncert instance GHC.Generics.Selector Numeric.Uncertain.S1_0_0Uncert instance GHC.Generics.Constructor Numeric.Uncertain.C1_0Uncert instance GHC.Generics.Datatype Numeric.Uncertain.D1Uncert instance GHC.Generics.Generic1 Numeric.Uncertain.Uncert instance GHC.Generics.Generic (Numeric.Uncertain.Uncert a) instance Data.Data.Data a => Data.Data.Data (Numeric.Uncertain.Uncert a) instance (GHC.Show.Show a, GHC.Float.Floating a, GHC.Real.RealFrac a) => GHC.Show.Show (Numeric.Uncertain.Uncert a) instance GHC.Real.Fractional a => GHC.Num.Num (Numeric.Uncertain.Uncert a) instance GHC.Real.Fractional a => GHC.Real.Fractional (Numeric.Uncertain.Uncert a) instance GHC.Float.Floating a => GHC.Float.Floating (Numeric.Uncertain.Uncert a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Numeric.Uncertain.Uncert a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Numeric.Uncertain.Uncert a) instance (GHC.Real.Fractional a, GHC.Real.Real a) => GHC.Real.Real (Numeric.Uncertain.Uncert a) instance GHC.Real.RealFrac a => GHC.Real.RealFrac (Numeric.Uncertain.Uncert a) instance GHC.Float.RealFloat a => GHC.Float.RealFloat (Numeric.Uncertain.Uncert a) -- | Provides the Corr monad, which allows one to describe complex -- relationships between random variables and evaluate their propagated -- uncertainties respecting their inter-correlations. -- -- See the Numeric.Uncertain.Correlated.Interactive module for an -- "interactive" and exploratory interface for this module's -- functionality. module Numeric.Uncertain.Correlated -- | The Corr monad allows us to keep track of correlated and -- non-independent samples. It fixes a basic "failure" of the -- Uncert type, which can't describe correlated samples. -- -- For example, consider the difference between: -- --
-- ghci> sum $ replicate 10 (12.5 +/- 0.8) -- 125 +/- 3 -- ghci> 10 * (12.5 +/- 0.8) -- 125 +/- 8 ---- -- The first one represents the addition of ten independent samples, -- whose errors will in general cancel eachother out. The second one -- represents sampling once and multiplying it by ten, which will amplify -- any error by a full factor of 10. -- -- See how the Corr monad expresses the above computations: -- --
-- ghci> evalCorr $ do -- x <- sampleUncert $ 12.5 +/- 0.8 -- y1 <- resolveUncert $ sum (replicate 10 x) -- y2 <- resolveUncert $ 10 * x -- return (y1, y2) -- (125 +- 8, 125 +- 8) -- -- ghci> evalCorr $ do -- xs <- replicateM 10 (sampleUncert (12.5 +/- 0.8)) -- resolveUncert $ sum xs -- 125 +/- 3 ---- -- The first example samples once and describes operations on the single -- sample; the second example samples 10 times with replicateM -- and sums all of the results. -- -- Things are more interesting when you sample multiple variables: -- --
-- ghci> evalCorr $ do -- x <- sampleUncert $ 12.5 +/- 0.8 -- y <- sampleUncert $ 15.9 +/- 0.5 -- z <- sampleUncert $ 1.52 +/- 0.07 -- let k = y ** x -- resolveUncert $ (x+z) * logBase z k -- 1200 +/- 200 ---- -- The first parameter is a dummy phantom parameter used to prevent -- CVars from leaking out of the computation (see -- evalCorr). The second parameter is the numeric type of all -- samples within the description (for example, if you ever sample an -- 'Uncert Double', the second parameter wil be Double). The third -- parameter is the result type of the computation -- the value the -- Corr is describing. data Corr s a b -- | Evaluates the value described by a Corr monad, taking into -- account inter-correlations between samples. -- -- Takes a universally qualified Corr, which should not affect -- usage. See the examples in the documentation for Corr. The -- univeral qualification is mostly a type system trick to ensure that -- you aren't allowed to ever use evalCorr to evaluate a -- CVar. evalCorr :: Fractional a => (forall s. Corr s a b) -> b -- | Represents a single sample (or a value calculated from samples) within -- the Corr monad. These can be created with -- sampleUncert, sampleExact, and constC, or -- made by combinining others with its numeric typeclass instances (like -- Num) or its functions lifting arbitrary numeric functions (like -- liftC2). These keep track of inter-correlations between -- sources, and if you add together two CVars that are correlated, -- their results will reflect this. -- -- Can be "resolved" into the uncertain value they represent using -- resolveUncert. -- -- Note that these are parameterized by a dummy phantom parameter -- s so that they can't be "evaluated" out of the Corr -- they live in with evalCorr. -- -- Note that a CVar s a can only ever meaningfully -- "exist" in a Corr s a, meaning that the all samples -- within that Corr are of the same type. data CVar s a -- | Generate a sample in Corr from an Uncert value, -- independently from all other samples. -- -- Note that you can only sample Uncert as within a -- Corr s a, meaning that all other "sampled" values are -- also as. sampleUncert :: Uncert a -> Corr s a (CVar s a) -- | Generate an exact sample in Corr with zero uncertainty, -- independently from all other samples. -- -- Not super useful, since you can do something equivalent with -- constC or the numeric instances: -- --
-- sampleExact x ≡ return (constC x) -- sampleExact 10 ≡ return 10 ---- -- But is provided for completeness alongside sampleUncert. -- -- Note that you can exactly sample an a within a -- Corr s a, meaning that all other "sampled" values are -- also as. sampleExact :: a -> Corr s a (CVar s a) -- | Creates a CVar representing a completely independent sample -- from all other CVars containing the exact value given. constC :: a -> CVar s a -- | Resolve an Uncert from a CVar using its potential -- multiple samples and sample sources, taking into account -- inter-correlations between CVars and samples. -- -- Note that if you use sampleUncert on the result, the new sample -- will be treated as something completely independent. Usually this -- should only be used as the "exit point" of a Corr description. resolveUncert :: CVar s a -> Corr s a (Uncert a) -- | Lifts a numeric function over the sample represented by a CVar. -- Correctly propagates the uncertainty according to the second-order -- taylor expansion expansion of the function. Note that if the -- higher-degree taylor series terms are large with respect to the mean -- and variance, this approximation may be inaccurate. -- -- Should take any function sufficiently polymorphic over numeric types, -- so you can use things like sqrt, sin, negate, -- etc. -- --
-- ghci> evalCorr $ do -- x <- sampleUncert $ 12.5 +/- 0.8 -- y <- sampleUncert $ 15.9 +/- 0.5 -- resolveUncert $ liftC (z -> log z ^ 2) (x + y) -- 11.2 +/- 0.2 --liftC :: Fractional a => (forall t. AD t (Sparse a) -> AD t (Sparse a)) -> CVar s a -> CVar s a -- | Lifts a two-argument (curried) function over the samples represented -- by two CVars. Correctly propagates the uncertainty according to -- the second-order (multivariate) taylor expansion expansion of the -- function, and properly takes into account and keeps track of all -- inter-correlations between the CVar samples. Note that if the -- higher-degree taylor series terms are large with respect to the mean -- and variance, this approximation may be inaccurate. -- -- Should take any function sufficiently polymorphic over numeric types, -- so you can use things like *, atan2, **, etc. -- --
-- ghci> evalCorr $ do -- x <- sampleUncert $ 12.5 +/- 0.8 -- y <- sampleUncert $ 15.9 +/- 0.5 -- resolveUncert $ liftC2 (a b -> log (a + b) ^ 2) x y -- 11.2 +/- 0.2 --liftC2 :: Fractional a => (forall t. AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a)) -> CVar s a -> CVar s a -> CVar s a -- | Lifts a three-argument (curried) function over the samples represented -- by three CVars. See liftC2 and liftCF for more -- details. liftC3 :: Fractional a => (forall t. AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a)) -> CVar s a -> CVar s a -> CVar s a -> CVar s a -- | Lifts a four-argument (curried) function over the samples represented -- by four CVars. See liftC2 and liftCF for more -- details. liftC4 :: Fractional a => (forall t. AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a)) -> CVar s a -> CVar s a -> CVar s a -> CVar s a -> CVar s a -- | Lifts a five-argument (curried) function over the samples represented -- by five CVars. See liftC2 and liftCF for more -- details. liftC5 :: Fractional a => (forall t. AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a)) -> CVar s a -> CVar s a -> CVar s a -> CVar s a -> CVar s a -> CVar s a -- | Lifts a multivariate numeric function on a container (given as an -- f a -> a) to work on a container of CVars. -- Correctly propagates the uncertainty according to the second-order -- (multivariate) taylor expansion of the function, and properly takes -- into account and keeps track of all inter-correlations between the -- CVar samples. Note that if the higher-degree taylor series -- terms are large with respect to the means and variances, this -- approximation may be inaccurate. -- -- Should take any function sufficiently polymorphic over numeric types, -- so you can use things like *, sqrt, atan2, etc. -- --
-- ghci> evalCorr $ do -- x <- sampleUncert $ 12.5 +/- 0.8 -- y <- sampleUncert $ 15.9 +/- 0.5 -- z <- sampleUncert $ 1.52 +/- 0.07 -- resolveUncert $ liftCF ([a,b,c] -> (a+c) * logBase c (b**a)) x y z -- 1200 +/- 200 --liftCF :: (Functor f, Fractional a) => (forall t. f (AD t (Sparse a)) -> AD t (Sparse a)) -> f (CVar s a) -> CVar s a -- | Exports all of the interface of Numeric.Uncertain.Correlated, -- except meant to be run in a ghci session "interactively" for -- exploratory purposes, or in a plain IO action (instead of -- inside a Corr monad). -- -- For example, with the Numeric.Uncertain.Correlated interface: -- --
-- ghci> evalCorr $ do -- x <- sampleUncert $ 12.5 +/- 0.8 -- y <- sampleUncert $ 15.9 +/- 0.5 -- z <- sampleUncert $ 1.52 +/- 0.07 -- let k = y**x -- resolveUncert $ (x+z) * logBase z k -- 1200 +/- 200 ---- -- And with the interface from this "interactive" module: -- --
-- ghci> x <- sampleUncert $ 12.5 +/- 0.8 -- ghci> y <- sampleUncert $ 15.9 +/- 0.5 -- ghci> z <- sampleUncert $ 1.52 +/- 0.07 -- ghci> let k = y**x -- ghci> resolveUncert $ (x+z) * logBase z k -- 1200 +/- 200 ---- -- The main purpose of this module is to allow one to use ghci as -- a fancy "calculator" for computing and exploring propagated -- uncertainties of complex and potentially correlated samples with -- uncertainty. -- -- Because many of the names overlap with the names from the -- Numeric.Uncertain.Correlated module, it is recommended that you -- never have both imported at the same time in ghci or in a file, -- or import them qualified if you must. -- -- Also note that all of these methods only work with -- Uncertain Doubles, and are not polymorphic -- over different numeric types. -- -- Be aware that this module is not robustly tested in heavily concurrent -- situations/applications. module Numeric.Uncertain.Correlated.Interactive -- | Represents a single sample (or a value calculated from samples) within -- the Corr monad. These can be created with -- sampleUncert, sampleExact, and constC, or -- made by combinining others with its numeric typeclass instances (like -- Num) or its functions lifting arbitrary numeric functions (like -- liftC2). These keep track of inter-correlations between -- sources, and if you add together two CVars that are correlated, -- their results will reflect this. -- -- Can be "resolved" into the uncertain value they represent using -- resolveUncert. -- -- Note that these are parameterized by a dummy phantom parameter -- s so that they can't be "evaluated" out of the Corr -- they live in with evalCorr. -- -- Note that a CVar s a can only ever meaningfully -- "exist" in a Corr s a, meaning that the all samples -- within that Corr are of the same type. data CVar s a -- | A CVar specialized to work in an "interactive" context, in -- ghci or IO. type CVarIO = CVar RealWorld Double -- | Generate a sample in IO from an Uncert -- Double value, independently from all other samples. sampleUncert :: Uncert Double -> IO CVarIO -- | Generate an exact sample in IO with zero uncertainty, -- independently from all other samples. -- -- Not super useful, since you can do something equivalent with -- constC or the numeric instances: -- --
-- sampleExact x ≡ return (constC x) -- sampleExact 10 ≡ return 10 ---- -- But is provided for completeness alongside sampleUncert. sampleExact :: Double -> IO CVarIO -- | Creates a CVar representing a completely independent sample -- from all other CVars containing the exact value given. constC :: a -> CVar s a -- | Resolve an Uncert from a CVarIO using its -- potential multiple samples and sample sources, taking into account -- inter-correlations between CVarIOs and samples. -- -- Note that if you use sampleUncert on the result, the new sample -- will be treated as something completely independent. Usually this -- should only be used as the "final value" of your computation or -- exploration. resolveUncert :: CVarIO -> IO (Uncert Double) -- | Lifts a numeric function over the sample represented by a CVar. -- Correctly propagates the uncertainty according to the second-order -- taylor expansion expansion of the function. Note that if the -- higher-degree taylor series terms are large with respect to the mean -- and variance, this approximation may be inaccurate. -- -- Should take any function sufficiently polymorphic over numeric types, -- so you can use things like sqrt, sin, negate, -- etc. -- --
-- ghci> evalCorr $ do -- x <- sampleUncert $ 12.5 +/- 0.8 -- y <- sampleUncert $ 15.9 +/- 0.5 -- resolveUncert $ liftC (z -> log z ^ 2) (x + y) -- 11.2 +/- 0.2 --liftC :: Fractional a => (forall t. AD t (Sparse a) -> AD t (Sparse a)) -> CVar s a -> CVar s a -- | Lifts a two-argument (curried) function over the samples represented -- by two CVars. Correctly propagates the uncertainty according to -- the second-order (multivariate) taylor expansion expansion of the -- function, and properly takes into account and keeps track of all -- inter-correlations between the CVar samples. Note that if the -- higher-degree taylor series terms are large with respect to the mean -- and variance, this approximation may be inaccurate. -- -- Should take any function sufficiently polymorphic over numeric types, -- so you can use things like *, atan2, **, etc. -- --
-- ghci> evalCorr $ do -- x <- sampleUncert $ 12.5 +/- 0.8 -- y <- sampleUncert $ 15.9 +/- 0.5 -- resolveUncert $ liftC2 (a b -> log (a + b) ^ 2) x y -- 11.2 +/- 0.2 --liftC2 :: Fractional a => (forall t. AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a)) -> CVar s a -> CVar s a -> CVar s a -- | Lifts a three-argument (curried) function over the samples represented -- by three CVars. See liftC2 and liftCF for more -- details. liftC3 :: Fractional a => (forall t. AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a)) -> CVar s a -> CVar s a -> CVar s a -> CVar s a -- | Lifts a four-argument (curried) function over the samples represented -- by four CVars. See liftC2 and liftCF for more -- details. liftC4 :: Fractional a => (forall t. AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a)) -> CVar s a -> CVar s a -> CVar s a -> CVar s a -> CVar s a -- | Lifts a five-argument (curried) function over the samples represented -- by five CVars. See liftC2 and liftCF for more -- details. liftC5 :: Fractional a => (forall t. AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a) -> AD t (Sparse a)) -> CVar s a -> CVar s a -> CVar s a -> CVar s a -> CVar s a -> CVar s a -- | Lifts a multivariate numeric function on a container (given as an -- f a -> a) to work on a container of CVars. -- Correctly propagates the uncertainty according to the second-order -- (multivariate) taylor expansion of the function, and properly takes -- into account and keeps track of all inter-correlations between the -- CVar samples. Note that if the higher-degree taylor series -- terms are large with respect to the means and variances, this -- approximation may be inaccurate. -- -- Should take any function sufficiently polymorphic over numeric types, -- so you can use things like *, sqrt, atan2, etc. -- --
-- ghci> evalCorr $ do -- x <- sampleUncert $ 12.5 +/- 0.8 -- y <- sampleUncert $ 15.9 +/- 0.5 -- z <- sampleUncert $ 1.52 +/- 0.07 -- resolveUncert $ liftCF ([a,b,c] -> (a+c) * logBase c (b**a)) x y z -- 1200 +/- 200 --liftCF :: (Functor f, Fractional a) => (forall t. f (AD t (Sparse a)) -> AD t (Sparse a)) -> f (CVar s a) -> CVar s a -- | Provides an interface for computing and propagating uncertainty by -- using Monte Carlo simulations. -- -- Basically simulates sampling from the distribution represented by the -- given Uncerts, applying the function of interest, and -- aggregating the mean and standard deviation of the results. x -- +/- dx is treated as a random variable whose probability -- density is the normal distribution with mean x and standard -- deviation dx. -- -- This module attempts to duplicate the API offered by -- Numeric.Uncertain and is meant to be imported qualified -- alongside Numeric.Uncertain -- --
-- import Numeric.Uncertain -- import qualified Numeric.Uncertain.MonteCarlo as MC ---- -- Actions are parameterized over all PrimMonad instances, so can -- be run under both ST and IO, making it suitable for -- exploratory purposes. All functions require a Gen from -- System.Random.MWC for random value generation purposes. -- --
-- ghci> import qualified Numeric.Uncertain.MonteCarlo as MC -- ghci> import System.Random.MWC -- ghci> let x = 1.52 +/- 0.07 -- ghci> let y = 781.4 +/- 0.3 -- ghci> let z = 1.53e-1 `withPrecision' 3 -- ghci> g <- create -- ghci> cosh x -- 2.4 +/- 0.2 -- ghci> MC.liftU cosh x g -- 2.4 +/- 0.2 -- ghci> exp x / z * sin (y ** z) -- 10.9 +/- 0.9 -- ghci> MC.liftU3 (a b c -> exp a / c * sin (b**c)) x y z g -- 10.8 +/- 1.0 -- ghci> pi + 3 * logBase x y -- 52 +/- 5 -- ghci> MC.liftU2 (a b -> pi + 3 * logBase a b) x y g -- 51 +/- 5 --module Numeric.Uncertain.MonteCarlo -- | Sample a random Double from the distribution specified by an -- Uncert Double. x +/- dx is -- treated as a random variable whose probability density is the normal -- distribution with mean x and standard deviation dx. sampleUncert :: (PrimMonad m, Functor m) => Uncert Double -> Gen (PrimState m) -> m Double -- | Lifts a numeric function over an Uncert using a Monte Carlo -- simulation with 1000 samples. -- --
-- ghci> g <- create -- ghci> MC.liftU (x -> log x ^ 2) (12.2 +/- 0.5) g -- 6.3 +/- 0.2 --liftU :: PrimMonad m => (Double -> Double) -> Uncert Double -> Gen (PrimState m) -> m (Uncert Double) -- | Lifts a two-argument (curried) function over two Uncerts using -- a Monte Carlo simulation with 1000 samples. -- --
-- ghci> g <- create -- ghci> MC.liftU2 (x y -> x**y) (13.5 +- 0.1) (1.64 +- 0.08) -- 70 +/- 20 --liftU2 :: PrimMonad m => (Double -> Double -> Double) -> Uncert Double -> Uncert Double -> Gen (PrimState m) -> m (Uncert Double) -- | Lifts a three-argument (curried) function over three Uncerts. -- See liftU2 and liftUF for more details. liftU3 :: PrimMonad m => (Double -> Double -> Double -> Double) -> Uncert Double -> Uncert Double -> Uncert Double -> Gen (PrimState m) -> m (Uncert Double) -- | Lifts a four-argument (curried) function over four Uncerts. See -- liftU2 and liftUF for more details. liftU4 :: PrimMonad m => (Double -> Double -> Double -> Double -> Double) -> Uncert Double -> Uncert Double -> Uncert Double -> Uncert Double -> Gen (PrimState m) -> m (Uncert Double) -- | Lifts a five-argument (curried) function over five Uncerts. See -- liftU2 and liftUF for more details. liftU5 :: PrimMonad m => (Double -> Double -> Double -> Double -> Double -> Double) -> Uncert Double -> Uncert Double -> Uncert Double -> Uncert Double -> Uncert Double -> Gen (PrimState m) -> m (Uncert Double) -- | Lifts a multivariate numeric function on a container (given as an -- f a -> a) to work on a container of Uncerts using a -- Monte Carlo simulation with 1000 samples. -- --
-- ghci> g <- create -- ghci> M.liftUF ([x,y,z] -> x*y+z) [12.2 +- 0.5, 56 +- 2, 0.12 +/- 0.08] g -- 680 +/- 40 --liftUF :: (Traversable f, PrimMonad m) => (f Double -> Double) -> f (Uncert Double) -> Gen (PrimState m) -> m (Uncert Double) -- | Like liftU, but allows you to specify the number of samples to -- run the Monte Carlo simulation with. liftU' :: PrimMonad m => Int -> (Double -> Double) -> Uncert Double -> Gen (PrimState m) -> m (Uncert Double) -- | Like liftU2, but allows you to specify the number of samples to -- run the Monte Carlo simulation with. liftU2' :: PrimMonad m => Int -> (Double -> Double -> Double) -> Uncert Double -> Uncert Double -> Gen (PrimState m) -> m (Uncert Double) -- | Like liftU3, but allows you to specify the number of samples to -- run the Monte Carlo simulation with. liftU3' :: PrimMonad m => Int -> (Double -> Double -> Double -> Double) -> Uncert Double -> Uncert Double -> Uncert Double -> Gen (PrimState m) -> m (Uncert Double) -- | Like liftU4, but allows you to specify the number of samples to -- run the Monte Carlo simulation with. liftU4' :: PrimMonad m => Int -> (Double -> Double -> Double -> Double -> Double) -> Uncert Double -> Uncert Double -> Uncert Double -> Uncert Double -> Gen (PrimState m) -> m (Uncert Double) -- | Like liftU5, but allows you to specify the number of samples to -- run the Monte Carlo simulation with. liftU5' :: PrimMonad m => Int -> (Double -> Double -> Double -> Double -> Double -> Double) -> Uncert Double -> Uncert Double -> Uncert Double -> Uncert Double -> Uncert Double -> Gen (PrimState m) -> m (Uncert Double) -- | Like liftUF, but allows you to specify the number of samples to -- run the Monte Carlo simulation with. liftUF' :: (Traversable f, PrimMonad m) => Int -> (f Double -> Double) -> f (Uncert Double) -> Gen (PrimState m) -> m (Uncert Double)