maxent (empty) → 0.1.0.0
raw patch · 5 files changed
+224/−0 lines, 5 filesdep +addep +basedep +nonlinear-optimizationsetup-changed
Dependencies added: ad, base, nonlinear-optimization, vector
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- maxent.cabal +78/−0
- src/MaxEnt.hs +27/−0
- src/MaxEnt/Internal.hs +87/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, Jonathan Fischoff++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Jonathan Fischoff nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ maxent.cabal view
@@ -0,0 +1,78 @@+-- Initial maxent.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/++-- The name of the package.+name: maxent++-- The package version. See the Haskell package versioning policy (PVP) +-- for standards guiding when and how versions should be incremented.+-- http://www.haskell.org/haskellwiki/Package_versioning_policy+-- PVP summary: +-+------- breaking API changes+-- | | +----- non-breaking API additions+-- | | | +--- code changes with no API change+version: 0.1.0.0++-- A short (one-line) description of the package.+synopsis: Compute Maximum Entropy Distrubtions++-- A longer description of the package.+description: Use this package to compute maximum entropy distributions given a list of values and+ list of constraints.+ .+ Here is a the example from Probability the Logic of Science + .+  > maxent ([1,2,3], [average 1.5])+ .+ Right [0.61, 0.26, 0.11]+ .+ The classic dice example+ .+  > maxent ([1,2,3,4,5,6], [average 4.5])+ .+ Right [.05, .07, 0.11, 0.16, 0.23, 0.34]+ + I will document this more ... soonish+ +-- URL for the project homepage or repository.+homepage: https://github.com/jfischoff/maxent++-- The license under which the package is released.+license: BSD3++-- The file containing the license text.+license-file: LICENSE++-- The package author(s).+author: Jonathan Fischoff++-- An email address to which users can send suggestions, bug reports, and +-- patches.+maintainer: jonathangfischoff@gmail.com++-- A copyright notice.+-- copyright: ++category: Math++build-type: Simple++-- Constraint on the version of Cabal needed to build this package.+cabal-version: >=1.8+++library+ -- Modules exported by the library.+ exposed-modules: MaxEnt+ + -- Modules included in this library but not exported.+ other-modules: MaxEnt.Internal+ + -- Other library packages from which modules are imported.+ build-depends: base ==4.6.*,+ nonlinear-optimization ==0.3.*,+ vector ==0.9.*, + ad ==3.2.*+ + -- Directories containing source files.+ hs-source-dirs: src+
+ src/MaxEnt.hs view
@@ -0,0 +1,27 @@+-- |+-- Use this package to compute maximum entropy distributions given a list of values and+-- list of constraints.+-- +-- Here is a the example from Probability the Logic of Science+-- +-- > maxent ([1,2,3], [average 1.5])+-- +-- Right [0.61, 0.26, 0.11]+-- +-- The classic dice example+-- +-- > maxent ([1,2,3,4,5,6], [average 4.5])+-- +-- Right [.05, .07, 0.11, 0.16, 0.23, 0.34]+module MaxEnt (+ Constraint,+ constraint,+ average,+ variance,+ maxent+) where+import MaxEnt.Internal (Constraint,+ constraint,+ average,+ variance,+ maxent)
+ src/MaxEnt/Internal.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE TupleSections, Rank2Types #-}+module MaxEnt.Internal where+import Numeric.Optimization.Algorithms.HagerZhang05+import qualified Data.Vector.Unboxed as U+import qualified Data.Vector.Storable as S+import Numeric.AD+import GHC.IO (unsafePerformIO)++sumWith :: Num c => (a -> b -> c) -> [a] -> [b] -> c +sumWith f xs = sum . zipWith f xs++pOfK :: Floating a => [a] -> [a -> a] -> [a] -> Int -> a+pOfK values fs ls k = exp (negate . sumWith (\l f -> l * f (values !! k)) ls $ fs) / + partitionFunc values fs ls ++probs :: Floating b => [b] -> [b -> b] -> [b] -> [b] +probs values fs ls = map (pOfK values fs ls) [0..length values - 1] ++partitionFunc :: Floating a => [a] -> [a -> a] -> [a] -> a+partitionFunc values fs ls = sum $ [ exp ((-l) * f x) | x <- values, (f, l) <- zip fs ls]++objectiveFunc :: Floating a => [a] -> [a -> a] -> [a] -> [a] -> a+objectiveFunc values fs moments ls = log (partitionFunc values fs ls) + sumWith (*) ls moments++toFunction :: (forall a. Floating a => [a] -> a) -> Function Simple+toFunction f = VFunction (f . U.toList)++toGradient :: (forall a. Floating a => [a] -> a) -> Gradient Simple+toGradient f = VGradient (U.fromList . grad f . U.toList)++toDoubleF :: (forall a. Floating a => [a] -> a) -> [Double] -> Double+toDoubleF f x = f x ++-- | Constraint type. Think of this as f and c in sum pi (f x) = c+type Constraint a = (a -> a, a)++-- make a constraint from function and constant+constraint :: Floating a => (a -> a) -> a -> Constraint a+constraint = (,)++-- The average constraint+average :: Floating a => a -> Constraint a+average m = constraint id m++-- The variance constraint+variance :: Floating a => a -> Constraint a+variance sigma = constraint (^(2 :: Int)) sigma++-- | The main entry point for computing discrete maximum entropy distributions.+-- +maxent :: (forall a. Floating a => ([a], [Constraint a])) -- ^ A pair of values that the distributions is over and the constraints+ -> Either (Result, Statistics) [Double] -- ^ Either the a discription of what wrong or the probability distribution +maxent params = result where+ obj :: Floating a => [a] -> a+ obj = uncurry (objectiveFunc values) fsmoments+ + values :: Floating a => [a]+ values = fst params+ + constraints :: Floating a => [(a -> a, a)]+ constraints = snd params+ + fsmoments :: Floating a => ([a -> a], [a])+ fsmoments = unzip constraints + + fs :: [Double -> Double]+ fs = fst fsmoments+ + -- hmm maybe there is a better way to get rid of the defaulting+ guess = U.fromList $ replicate + (length (constraints :: [(Double -> Double, Double)])) (1.0 :: Double) + + result = case unsafePerformIO (optimize defaultParameters 0.00001 guess + (toFunction obj)+ (toGradient obj)+ Nothing) of+ (vs, ToleranceStatisfied, _) -> Right $ probs values fs (S.toList vs)+ (_, x, y) -> Left (x, y)++--test = maxent ([1.0,2.0,3.0], [average 1.5])+++ + +++