working code
This commit is contained in:
commit
32cdc46325
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.stack-work/
|
||||||
|
*~
|
12
README.md
Normal file
12
README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# mud
|
||||||
|
|
||||||
|
|
||||||
|
Run the demo:
|
||||||
|
```sh
|
||||||
|
stack run
|
||||||
|
```
|
||||||
|
|
||||||
|
## tests
|
||||||
|
```
|
||||||
|
stack test
|
||||||
|
```
|
29
app/Main.hs
Normal file
29
app/Main.hs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
-- app/Main.hs
|
||||||
|
import Text.Printf (printf)
|
||||||
|
import MUD (updated, getPF, wme)
|
||||||
|
import RandomUtils (generateUniformPoints, generateNormalPoints)
|
||||||
|
import Data.List (elemIndex)
|
||||||
|
import Data.Maybe (fromJust)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
let f = id
|
||||||
|
let numData = 100
|
||||||
|
let mesh = [-1, -0.995 .. 1]
|
||||||
|
lam_lg <- generateUniformPoints 1000 (-1.0, 1.0)
|
||||||
|
let trueValue = 0.1
|
||||||
|
let noiseLevel = 0.121
|
||||||
|
noise <- generateNormalPoints numData 0 noiseLevel
|
||||||
|
let d = replicate numData trueValue
|
||||||
|
let noisyData = zipWith (+) d noise
|
||||||
|
let g x = wme (f x) noisyData noiseLevel
|
||||||
|
let q = getPF g lam_lg
|
||||||
|
let v = updated g q mesh
|
||||||
|
|
||||||
|
-- print $ v
|
||||||
|
|
||||||
|
let maxIndex = fromJust $ elemIndex (maximum v) v
|
||||||
|
let mudPoint = mesh !! maxIndex
|
||||||
|
|
||||||
|
putStrLn $ printf "For (true = %f with sigma = %f and N = %d), the MUD point from mesh is: %f" trueValue noiseLevel numData mudPoint
|
||||||
|
|
73
mud.cabal
Normal file
73
mud.cabal
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
cabal-version: 2.2
|
||||||
|
|
||||||
|
-- This file has been generated from package.yaml by hpack version 0.36.0.
|
||||||
|
--
|
||||||
|
-- see: https://github.com/sol/hpack
|
||||||
|
|
||||||
|
name: mud
|
||||||
|
version: 0.1.0.0
|
||||||
|
description: Please see the README on GitHub at <https://github.com/mathematicalmichael/mud#readme>
|
||||||
|
homepage: https://github.com/mathematicalmichael/mud#readme
|
||||||
|
bug-reports: https://github.com/mathematicalmichael/mud/issues
|
||||||
|
author: Michael Pilosov
|
||||||
|
maintainer: consistentbayes@gmail.com
|
||||||
|
copyright: 2024 Michael Pilosov
|
||||||
|
license: BSD-3-Clause
|
||||||
|
build-type: Simple
|
||||||
|
extra-source-files:
|
||||||
|
README.md
|
||||||
|
|
||||||
|
source-repository head
|
||||||
|
type: git
|
||||||
|
location: https://github.com/mathematicalmichael/mud
|
||||||
|
|
||||||
|
library
|
||||||
|
exposed-modules:
|
||||||
|
MUD
|
||||||
|
RandomUtils
|
||||||
|
other-modules:
|
||||||
|
AcceptReject
|
||||||
|
Paths_mud
|
||||||
|
autogen-modules:
|
||||||
|
Paths_mud
|
||||||
|
hs-source-dirs:
|
||||||
|
src
|
||||||
|
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
|
||||||
|
build-depends:
|
||||||
|
base >=4.7 && <5
|
||||||
|
, random
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable mud-exe
|
||||||
|
main-is: Main.hs
|
||||||
|
other-modules:
|
||||||
|
Paths_mud
|
||||||
|
autogen-modules:
|
||||||
|
Paths_mud
|
||||||
|
hs-source-dirs:
|
||||||
|
app
|
||||||
|
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends:
|
||||||
|
base >=4.7 && <5
|
||||||
|
, mud
|
||||||
|
, random
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
test-suite test-suite
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
main-is: Main.hs
|
||||||
|
other-modules:
|
||||||
|
TestKDE
|
||||||
|
TestMUD
|
||||||
|
TestRandomUtils
|
||||||
|
Paths_mud
|
||||||
|
autogen-modules:
|
||||||
|
Paths_mud
|
||||||
|
hs-source-dirs:
|
||||||
|
test
|
||||||
|
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends:
|
||||||
|
base >=4.7 && <5
|
||||||
|
, mud
|
||||||
|
, random
|
||||||
|
default-language: Haskell2010
|
64
package.yaml
Normal file
64
package.yaml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
name: mud
|
||||||
|
version: 0.1.0.0
|
||||||
|
github: "mathematicalmichael/mud"
|
||||||
|
license: BSD-3-Clause
|
||||||
|
author: "Michael Pilosov"
|
||||||
|
maintainer: "consistentbayes@gmail.com"
|
||||||
|
copyright: "2024 Michael Pilosov"
|
||||||
|
|
||||||
|
extra-source-files:
|
||||||
|
- README.md
|
||||||
|
|
||||||
|
# Metadata used when publishing your package
|
||||||
|
# synopsis: Short description of your package
|
||||||
|
# category: Uncategorized
|
||||||
|
|
||||||
|
# To avoid duplicated efforts in documentation and dealing with the
|
||||||
|
# complications of embedding Haddock markup inside cabal files, it is
|
||||||
|
# common to point users to the README.md file.
|
||||||
|
description: Please see the README on GitHub at <https://github.com/mathematicalmichael/mud#readme>
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- base >= 4.7 && < 5
|
||||||
|
- random
|
||||||
|
|
||||||
|
ghc-options:
|
||||||
|
- -Wall
|
||||||
|
- -Wcompat
|
||||||
|
- -Widentities
|
||||||
|
- -Wincomplete-record-updates
|
||||||
|
- -Wincomplete-uni-patterns
|
||||||
|
- -Wmissing-export-lists
|
||||||
|
- -Wmissing-home-modules
|
||||||
|
- -Wpartial-fields
|
||||||
|
- -Wredundant-constraints
|
||||||
|
|
||||||
|
library:
|
||||||
|
source-dirs: src
|
||||||
|
exposed-modules:
|
||||||
|
- MUD
|
||||||
|
- RandomUtils
|
||||||
|
|
||||||
|
executables:
|
||||||
|
mud-exe:
|
||||||
|
main: Main.hs
|
||||||
|
source-dirs: app
|
||||||
|
ghc-options:
|
||||||
|
- -threaded
|
||||||
|
- -rtsopts
|
||||||
|
- -with-rtsopts=-N
|
||||||
|
dependencies:
|
||||||
|
- mud
|
||||||
|
|
||||||
|
tests:
|
||||||
|
test-suite:
|
||||||
|
main: Main.hs
|
||||||
|
source-dirs: test
|
||||||
|
ghc-options:
|
||||||
|
- -threaded
|
||||||
|
- -rtsopts
|
||||||
|
- -with-rtsopts=-N
|
||||||
|
dependencies:
|
||||||
|
- mud
|
||||||
|
- random
|
||||||
|
|
33
src/AcceptReject.hs
Normal file
33
src/AcceptReject.hs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
module AcceptReject (main) where
|
||||||
|
|
||||||
|
import System.Random
|
||||||
|
import Control.Monad (replicateM)
|
||||||
|
|
||||||
|
-- Acceptance-Rejection sampling for normal distribution
|
||||||
|
generateNormalPointsAR :: Int -> Double -> Double -> IO [Double]
|
||||||
|
generateNormalPointsAR n mu sigma = do
|
||||||
|
gen <- newStdGen
|
||||||
|
let samples = take n $ filter acceptCandidate $ randomPairs gen
|
||||||
|
return $ map ((\x -> mu + sigma * x) . fst) samples
|
||||||
|
where
|
||||||
|
acceptCandidate (u1, u2) =
|
||||||
|
let x = sqrt (-2 * log u1) * cos (2 * pi * u2)
|
||||||
|
in u2 < exp (-0.5 * x * x)
|
||||||
|
randomPairs g = zip (randoms g) (randoms g)
|
||||||
|
|
||||||
|
-- Generate random points from a uniform distribution in the range [a, b]
|
||||||
|
generateUniformPoints :: Int -> Double -> Double -> IO [Double]
|
||||||
|
generateUniformPoints n a b = replicateM n (randomRIO (a, b))
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
-- Generate 10 random points from a uniform distribution in the range [-1, 1]
|
||||||
|
uniformPoints <- generateUniformPoints 10 (-1) 1
|
||||||
|
putStrLn "Uniform distribution points:"
|
||||||
|
print uniformPoints
|
||||||
|
|
||||||
|
-- Generate 10 random points from a normal distribution using acceptance-rejection sampling
|
||||||
|
normalPointsAR <- generateNormalPointsAR 10 0 1
|
||||||
|
putStrLn "Normal distribution points (Acceptance-Rejection):"
|
||||||
|
print normalPointsAR
|
||||||
|
|
51
src/MUD.hs
Normal file
51
src/MUD.hs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
module MUD (uniformPDF, gaussianPDF, kde, wme, getPF, updated) where
|
||||||
|
|
||||||
|
-- Function to evaluate Uniform PDF at a point x with range [a, b]
|
||||||
|
uniformPDF :: Double -> Double -> Double -> Double
|
||||||
|
uniformPDF a b x
|
||||||
|
| x >= a && x <= b = 1 / (b - a)
|
||||||
|
| otherwise = 0
|
||||||
|
|
||||||
|
-- Function to evaluate Gaussian PDF at a point x with mean mu and standard deviation sigma
|
||||||
|
gaussianPDF :: Double -> Double -> Double -> Double
|
||||||
|
gaussianPDF x mu sigma = (1 / sqrt (2 * pi * sigma**2)) * exp (-(x - mu)**2 / (2 * sigma**2))
|
||||||
|
|
||||||
|
-- Kernel Density Estimation function
|
||||||
|
kde :: [Double] -> Double -> (Double -> Double)
|
||||||
|
kde ctlpoints bandwidth = \x -> (1 / (n * actualBandwidth)) * sum [gaussianPDF x xi actualBandwidth | xi <- ctlpoints]
|
||||||
|
where
|
||||||
|
n = fromIntegral (length ctlpoints)
|
||||||
|
actualBandwidth
|
||||||
|
| bandwidth == 0 = 1.06 * stdDev ctlpoints * n ** (-1/5)
|
||||||
|
| otherwise = bandwidth
|
||||||
|
|
||||||
|
-- Calculate standard deviation
|
||||||
|
stdDev :: [Double] -> Double
|
||||||
|
stdDev xs = sqrt $ sum [(x - mean) ** 2 | x <- xs] / n
|
||||||
|
where
|
||||||
|
n = fromIntegral (length xs)
|
||||||
|
mean = sum xs / n
|
||||||
|
|
||||||
|
-- Estimate the push-forward distribution
|
||||||
|
getPF :: (Double -> Double) -> [Double] -> (Double -> Double)
|
||||||
|
getPF f x = kde y 0
|
||||||
|
where
|
||||||
|
y = map f x
|
||||||
|
|
||||||
|
-- Weighted Mean Error Functional
|
||||||
|
wme :: Double -> [Double] -> Double -> Double
|
||||||
|
wme y d s = (1 / sqrt n) * sum [ (y - di) / std | di <- d ]
|
||||||
|
where
|
||||||
|
n = fromIntegral (length d)
|
||||||
|
std
|
||||||
|
| s == 0 = stdDev d
|
||||||
|
| otherwise = s
|
||||||
|
|
||||||
|
-- Updated density computation.
|
||||||
|
updated :: (Double -> Double) -> (Double -> Double) -> [Double] -> [Double]
|
||||||
|
updated f d x = [ i * (o / p) | (i, o, p) <- zip3 a b c]
|
||||||
|
where
|
||||||
|
y = map f x
|
||||||
|
a = map (\xi -> gaussianPDF xi 0 1) x
|
||||||
|
b = map (\yi -> gaussianPDF yi 0 1) y
|
||||||
|
c = map d y
|
25
src/RandomUtils.hs
Normal file
25
src/RandomUtils.hs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
-- src/RandomUtils.hs
|
||||||
|
module RandomUtils (generateUniformPoints, generateNormalPoints) where
|
||||||
|
|
||||||
|
import System.Random
|
||||||
|
import Control.Monad (replicateM)
|
||||||
|
|
||||||
|
-- Generate random points from a uniform distribution in the range [a, b]
|
||||||
|
generateUniformPoints :: Int -> (Double, Double) -> IO [Double]
|
||||||
|
generateUniformPoints n (a, b) = replicateM n (randomRIO (a, b))
|
||||||
|
|
||||||
|
-- Generate random points from a normal distribution using the Box-Muller transform
|
||||||
|
generateNormalPoints :: Int -> Double -> Double -> IO [Double]
|
||||||
|
generateNormalPoints n mu sigma = do
|
||||||
|
gen <- newStdGen
|
||||||
|
let randomFloats = take (2 * n) $ randomRs (0, 1) gen
|
||||||
|
return $ boxMullerTransform mu sigma randomFloats
|
||||||
|
|
||||||
|
-- Box-Muller transform to generate normally distributed random values
|
||||||
|
boxMullerTransform :: Double -> Double -> [Double] -> [Double]
|
||||||
|
boxMullerTransform mu sigma (u1:u2:us) =
|
||||||
|
let z0 = sqrt (-2 * log u1) * cos (2 * pi * u2)
|
||||||
|
z1 = sqrt (-2 * log u1) * sin (2 * pi * u2)
|
||||||
|
in (mu + z0 * sigma) : (mu + z1 * sigma) : boxMullerTransform mu sigma us
|
||||||
|
boxMullerTransform _ _ _ = [] -- If input list is not in pairs, return empty list
|
||||||
|
|
67
stack.yaml
Normal file
67
stack.yaml
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# This file was automatically generated by 'stack init'
|
||||||
|
#
|
||||||
|
# Some commonly used options have been documented as comments in this file.
|
||||||
|
# For advanced use and comprehensive documentation of the format, please see:
|
||||||
|
# https://docs.haskellstack.org/en/stable/yaml_configuration/
|
||||||
|
|
||||||
|
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
|
||||||
|
# A snapshot resolver dictates the compiler version and the set of packages
|
||||||
|
# to be used for project dependencies. For example:
|
||||||
|
#
|
||||||
|
# resolver: lts-22.21
|
||||||
|
# resolver: nightly-2024-05-06
|
||||||
|
# resolver: ghc-9.6.5
|
||||||
|
#
|
||||||
|
# The location of a snapshot can be provided as a file or url. Stack assumes
|
||||||
|
# a snapshot provided as a file might change, whereas a url resource does not.
|
||||||
|
#
|
||||||
|
# resolver: ./custom-snapshot.yaml
|
||||||
|
# resolver: https://example.com/snapshots/2023-01-01.yaml
|
||||||
|
resolver:
|
||||||
|
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/22.yaml
|
||||||
|
|
||||||
|
# User packages to be built.
|
||||||
|
# Various formats can be used as shown in the example below.
|
||||||
|
#
|
||||||
|
# packages:
|
||||||
|
# - some-directory
|
||||||
|
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
|
||||||
|
# subdirs:
|
||||||
|
# - auto-update
|
||||||
|
# - wai
|
||||||
|
packages:
|
||||||
|
- .
|
||||||
|
# Dependency packages to be pulled from upstream that are not in the resolver.
|
||||||
|
# These entries can reference officially published versions as well as
|
||||||
|
# forks / in-progress versions pinned to a git hash. For example:
|
||||||
|
#
|
||||||
|
# extra-deps:
|
||||||
|
# - acme-missiles-0.3
|
||||||
|
# - git: https://github.com/commercialhaskell/stack.git
|
||||||
|
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||||
|
#
|
||||||
|
# extra-deps: []
|
||||||
|
|
||||||
|
# Override default flag values for local packages and extra-deps
|
||||||
|
# flags: {}
|
||||||
|
|
||||||
|
# Extra package databases containing global packages
|
||||||
|
# extra-package-dbs: []
|
||||||
|
|
||||||
|
# Control whether we use the GHC we find on the path
|
||||||
|
# system-ghc: true
|
||||||
|
#
|
||||||
|
# Require a specific version of Stack, using version ranges
|
||||||
|
# require-stack-version: -any # Default
|
||||||
|
# require-stack-version: ">=2.15"
|
||||||
|
#
|
||||||
|
# Override the architecture used by Stack, especially useful on Windows
|
||||||
|
# arch: i386
|
||||||
|
# arch: x86_64
|
||||||
|
#
|
||||||
|
# Extra directories used by Stack for building
|
||||||
|
# extra-include-dirs: [/path/to/dir]
|
||||||
|
# extra-lib-dirs: [/path/to/dir]
|
||||||
|
#
|
||||||
|
# Allow a newer minor version of GHC than the snapshot specifies
|
||||||
|
# compiler-check: newer-minor
|
13
stack.yaml.lock
Normal file
13
stack.yaml.lock
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# This file was autogenerated by Stack.
|
||||||
|
# You should not edit this file by hand.
|
||||||
|
# For more information, please see the documentation at:
|
||||||
|
# https://docs.haskellstack.org/en/stable/lock_files
|
||||||
|
|
||||||
|
packages: []
|
||||||
|
snapshots:
|
||||||
|
- completed:
|
||||||
|
sha256: 4be1ca5d31689b524a7f0f17a439bbe9136465213edc498e9a395899a670f2aa
|
||||||
|
size: 718486
|
||||||
|
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/22.yaml
|
||||||
|
original:
|
||||||
|
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/22.yaml
|
12
test/Main.hs
Normal file
12
test/Main.hs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
module Main (main) where
|
||||||
|
|
||||||
|
import TestKDE (tests)
|
||||||
|
import TestMUD (tests)
|
||||||
|
import TestRandomUtils (tests)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
TestKDE.tests
|
||||||
|
TestRandomUtils.tests
|
||||||
|
TestMUD.tests
|
||||||
|
|
26
test/TestKDE.hs
Normal file
26
test/TestKDE.hs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
-- TestKDE.hs
|
||||||
|
module TestKDE (tests) where
|
||||||
|
|
||||||
|
import MUD (kde)
|
||||||
|
import RandomUtils (generateUniformPoints)
|
||||||
|
import Data.List (intercalate)
|
||||||
|
|
||||||
|
tests :: IO ()
|
||||||
|
tests = do
|
||||||
|
-- List of 21 equispaced points from -5 to 5
|
||||||
|
let grdpoints :: [Double]
|
||||||
|
grdpoints = [-5, -4.5 .. 5]
|
||||||
|
|
||||||
|
-- Generate 10 random points from a normal distribution
|
||||||
|
controlPoints <- generateUniformPoints 10 (-1.0, 1.0)
|
||||||
|
|
||||||
|
-- Fit the KDE to the random points with a specified bandwidth
|
||||||
|
let bandwidth = 0.5
|
||||||
|
let kdeEstimator = kde controlPoints bandwidth
|
||||||
|
|
||||||
|
-- Evaluate the KDE on the grid from -5 to 5
|
||||||
|
let evaluations = map kdeEstimator grdpoints
|
||||||
|
|
||||||
|
putStrLn "KDE evaluations at points from -5 to 5:"
|
||||||
|
putStrLn $ intercalate "\n" $ zipWith (\x y -> "x = " ++ show x ++ ", KDE = " ++ show y) grdpoints evaluations
|
||||||
|
|
17
test/TestMUD.hs
Normal file
17
test/TestMUD.hs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
-- TestMUD.hs
|
||||||
|
module TestMUD (tests) where
|
||||||
|
|
||||||
|
import MUD (updated, getPF)
|
||||||
|
import RandomUtils (generateUniformPoints)
|
||||||
|
|
||||||
|
tests :: IO ()
|
||||||
|
tests = do
|
||||||
|
-- Example of Updated density
|
||||||
|
let grdpoints = [-5, -4.5 .. 5]
|
||||||
|
-- let f = (\x -> x)
|
||||||
|
let f = id
|
||||||
|
lam_sm <- generateUniformPoints 100 (-1.0, 1.0)
|
||||||
|
let p = getPF f lam_sm
|
||||||
|
let u = updated f p grdpoints
|
||||||
|
print u
|
||||||
|
|
18
test/TestRandomUtils.hs
Normal file
18
test/TestRandomUtils.hs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
-- TestRandomUtils.hs
|
||||||
|
module TestRandomUtils (tests) where
|
||||||
|
|
||||||
|
import RandomUtils (generateUniformPoints, generateNormalPoints)
|
||||||
|
|
||||||
|
-- Define your tests here
|
||||||
|
tests :: IO ()
|
||||||
|
tests = do
|
||||||
|
-- Generate 10 random points from a uniform distribution in the range [-1, 1]
|
||||||
|
uniformPoints <- generateUniformPoints 10 (-1, 1)
|
||||||
|
putStrLn "Uniform distribution points:"
|
||||||
|
print uniformPoints
|
||||||
|
|
||||||
|
-- Generate 10 random points from a normal distribution using the Box-Muller transform
|
||||||
|
normalPoints <- generateNormalPoints 10 0 1
|
||||||
|
putStrLn "Normal distribution points (Box-Muller):"
|
||||||
|
print normalPoints
|
||||||
|
|
Loading…
Reference in New Issue
Block a user