module Goal.Core
( -- * Module Exports
module Goal.Core.Plot
, module Data.Function
, module Data.Ord
, module Data.Monoid
, module Data.List
, module Data.Maybe
, module Data.Either
, module Data.Default.Class
, module Control.Applicative
, module Control.Monad
, module Control.Monad.ST
, module Control.Arrow
, module Control.Lens.Type
, module Control.Lens.Getter
, module Control.Lens.Setter
, module Control.Lens.TH
, module Control.Concurrent
, module Numeric
, module Debug.Trace
-- * Lists
, takeEvery
, breakEvery
-- * Low-Level
, traceGiven
-- * Numeric
, roundSD
, toPi
-- ** Functions
, logistic
, logit
-- ** Lists
, mean
, range
, discretizeFunction
) where
--- Imports ---
-- Re-exports --
import Goal.Core.Plot hiding (empty,over)
import Data.Ord
import Data.Function
import Data.Monoid hiding (Dual)
import Data.List hiding (sum)
import Data.Maybe
import Data.Either
import Control.Applicative
import Control.Arrow hiding ((<+>))
import Control.Monad
import Control.Monad.ST
import Control.Lens.Type
import Control.Lens.Getter
import Control.Lens.Setter hiding (Identity)
import Control.Lens.TH
import Control.Concurrent
import Debug.Trace
import Data.Default.Class
import Numeric
--- General Functions ---
takeEvery :: Int -> [x] -> [x]
-- | Takes every nth element, starting with the head of the list.
takeEvery m = map snd . filter (\(x,_) -> mod x m == 0) . zip [0..]
breakEvery :: Int -> [x] -> [[x]]
-- | Break the list up into lists of length n.
breakEvery _ [] = []
breakEvery n xs = take n xs : breakEvery n (drop n xs)
traceGiven :: Show a => a -> a
-- | Runs traceShow on the given element.
traceGiven a = traceShow a a
--- Numeric ---
roundSD :: (Floating x, RealFrac x) => Int -> x -> x
-- | Roundest the number to the specified significant digit.
roundSD n x = (/10^n) . fromIntegral . round $ 10^n * x
toPi :: (Floating x, RealFrac x) => x -> x
-- | Modulo pi thingy.
toPi x =
let xpi = x / pi
n = floor xpi
f = xpi - fromIntegral n
in if even n then pi * f else -(pi * (1 - f))
logistic :: Floating x => x -> x
-- | A standard sigmoid function.
logistic x = 1 / (1 + exp(negate x))
logit :: Floating x => x -> x
-- | The inverse of the logistic.
logit x = log $ x / (1 - x)
-- Lists --
mean :: Fractional x => [x] -> x
-- | Average value of a list of numbers.
mean = uncurry (/) . foldr (\e (s,c) -> (e+s,c+1)) (0,0)
range :: Double -> Double -> Int -> [Double]
-- | Returns n numbers from mn to mx.
range _ _ 0 = []
range mn mx 1 = [(mn + mx) / 2]
range mn mx n =
[ x * mx + (1 - x) * mn | x <- (/ (fromIntegral n - 1)) . fromIntegral <$> [0 .. n-1] ]
discretizeFunction :: Double -> Double -> Int -> (Double -> Double) -> [(Double,Double)]
-- | Takes range information in the form of a minimum, maximum, and sample count,
-- a function to sample, and returns a list of pairs (x,f(x)) over the specified
-- range.
discretizeFunction mn mx n f =
let rng = range mn mx n
in zip rng $ f <$> rng
-- Graveyard --
{-
parMapWH :: (a -> b) -> [a] -> [b]
-- | ParMap using rseq. WH stands for Weak Head (normal form).
parMapWH = parMap rseq
parMapDS :: NFData b => (a -> b) -> [a] -> [b]
parMapDS = parMap rdeepseq
gridSearch
:: (a -> Double) -- ^ The error function on the model
-> (x -> a) -- ^ A constructor from the parameter being tested to the model
-> [x] -- ^ The list of parameter values to test
-> (x,[(x,Double)]) -- ^ The best parameter and model, and accompanying statistics
-- | A general implementation of a grid search. Returns a triple where the first
-- element is the best parameter, the second is the best model, and the third is a list
-- of the errors calculated at each parameter value.
gridSearch errorfun constructor xs =
let as = constructor <$> xs
errs = parMapDS errorfun as
x = fst . minimumBy (comparing snd) $ zip xs errs
in (x,zip xs errs)
iterativeOptimization
:: (a -> a -> Double) -- ^ Difference measure
-> Double -- ^ Differential error threshold
-> Int -- ^ Maximum number of iterations (< 1 is interpreted as infinity)
-> (a -> a) -- ^ Iterator
-> a -- ^ Initial Value
-> (a,[(a,Double)]) -- ^ The final value and associated descent
-- | Iterates a value, stopping when a stopping criterion is satisfied, or the maximum
-- number of iterations is reached. The algorithm returns the resulting value as well as
-- the descent preceding it.
--
-- The error accompanying each element of the descent corresponds to the error between
-- that element and the following element. The last error in the descent will therefore
-- correspond to the measured difference between the last element of the descent, and the
-- returned singleton in the pair.
--
-- If the last error in the returned descent is less then the given threshold, then the
-- threshold was reached. Otherwise, n will have been reached as the terminal condition.
iterativeOptimization difference thrsh n iterator a =
let itrs = iterate iterator a
itrs' = if n > 0 then take (n+1) itrs else itrs
zps = zip itrs' $ tail itrs'
zps' = case break ((< thrsh) . snd) . zip zps $ uncurry difference <$> zps of
(zps0,[]) -> zps0
(zps0,rst) -> zps0 ++ [head rst]
in (snd . fst . last $ zps', first fst <$> zps')
-}