packages feed

DCFL 0.1.5.0 → 0.1.6.0

raw patch · 2 files changed

+70/−19 lines, 2 filesdep +paralleldep ~deepseqPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: parallel

Dependency ranges changed: deepseq

API changes (from Hackage documentation)

- Data.DCFL: ConstraintEl :: [Int] -> ([Int] -> Bool) -> ConstraintEl
- Data.DCFL: Distribution :: [Double] -> Distribution
- Data.DCFL: Solved :: [Variable] -> Int -> Solved
- Data.DCFL: Values :: [Integer] -> Values
- Data.DCFL: Variable :: [Int] -> Int -> Distribution -> Variable
- Data.DCFL: applyAt :: (Num b1, Eq b1, Enum b1) => (b -> b) -> b1 -> [b] -> [b]
- Data.DCFL: b :: Double
- Data.DCFL: checkDistrSolved :: Distribution -> Bool
- Data.DCFL: constraint :: ConstraintEl -> ([Int] -> Bool)
- Data.DCFL: cummDistributionIter :: Distribution -> Int -> Double -> [Double]
- Data.DCFL: distr :: Variable -> Distribution
- Data.DCFL: evalConstraint :: ([Int] -> Bool) -> [Int] -> Bool
- Data.DCFL: evalConstraints :: [[Int] -> Bool] -> [Int] -> Bool
- Data.DCFL: failureCurrProb :: t -> Double -> Double
- Data.DCFL: failureOtherProb :: Double -> Double -> Double
- Data.DCFL: failureProb :: Eq a => Double -> a -> Double -> a -> Double
- Data.DCFL: getValueIndex :: Distribution -> Double -> Int
- Data.DCFL: getValues :: [Variable] -> [Int]
- Data.DCFL: iterationCount :: Solved -> Int
- Data.DCFL: oneIfEqual :: (Num a1, Eq a) => a -> a -> a1
- Data.DCFL: possible :: Variable -> [Int]
- Data.DCFL: probab :: Distribution -> [Double]
- Data.DCFL: randomNum :: IO Double
- Data.DCFL: randomizeVariable :: Variable -> IO Variable
- Data.DCFL: replicateDouble :: Int -> Double -> [Double]
- Data.DCFL: solveThreaded :: Int -> [Variable] -> [ConstraintEl] -> IO Solved
- Data.DCFL: updateEach' :: [Variable] -> [ConstraintEl] -> [Int] -> IO [Variable]
- Data.DCFL: updateEachThreaded :: Int -> [Variable] -> [ConstraintEl] -> IO [Variable]
- Data.DCFL: updateEachTimesThreaded :: Int -> [Variable] -> [ConstraintEl] -> Int -> IO [Variable]
- Data.DCFL: updateMapF :: [Variable] -> [ConstraintEl] -> Int -> IO Variable
- Data.DCFL: updateProb :: (Num a, Eq a, Enum a) => Distribution -> a -> Bool -> Distribution
- Data.DCFL: updateVariableProb :: Variable -> Bool -> Variable
- Data.DCFL: valueIndex :: Variable -> Int
- Data.DCFL: variableIndices :: ConstraintEl -> [Int]
- Data.DCFL: variables :: Solved -> [Variable]
- Data.DCFL: width :: Num b => Distribution -> b
+ Data.DCFL: solveParallel :: [Variable] -> [ConstraintEl] -> IO Solved
+ Data.DCFL: updateEachParallel :: [Variable] -> [ConstraintEl] -> IO [Variable]
+ Data.DCFL: updateEachTimesParallel :: [Variable] -> [ConstraintEl] -> Int -> IO [Variable]
- Data.DCFL: printVariables :: Show a => [a] -> [IO ()]
+ Data.DCFL: printVariables :: [Variable] -> [IO ()]

Files

DCFL.cabal view
@@ -10,7 +10,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.1.5.0+version:             0.1.6.0  -- A short (one-line) description of the package. synopsis:           Communication Free Learning-based constraint solver@@ -57,5 +57,5 @@   -- other-modules:             -- Other library packages from which modules are imported.-  build-depends:       base >=4.6 && <= 5.0, random >=1.0, HUnit >=1.2, deepseq ==1.4+  build-depends:       base >=4.6 && <= 5.0, random >=1.0, HUnit >=1.2, deepseq >=1.2, parallel >=3.0   ghc-options:         -Wall
src/Data/DCFL.hs view
@@ -5,7 +5,39 @@ -- Each process runs in parallel for every variable. -- Maintain a probability distribution for the variable -- Update it based on whether or not constraints are satisfied-module Data.DCFL where+module Data.DCFL (+  Distribution,+  Values,+  Variable,+  ConstraintEl,+  Solved,++  -- * Distributions+  initDistribution,+  cummDistribution,+  checkSolved,++  -- * Variables+  randomizeSingle,+  randomize,+  printVariables,++  -- * Constraints+  getConstraintsFor,+  justConstraints,++  -- * Solving+  -- ** Serial/Single Threaded+  solve,+  update,+  updateEach,+  updateEachTimes,++  -- ** Parallelized+  solveParallel,+  updateEachTimesParallel,+  updateEachParallel+) where import System.Random import Control.Parallel.Strategies import Control.DeepSeq@@ -19,8 +51,8 @@ -- |The integer values a 'Variable' can take on. data Values = Values [Integer] deriving Show --- |Each variable has a finite set of possible values, a value it holds--- at a given point and a probability distribution over the set of possible values.+-- |Each 'Variable' has a finite set of possible values, a value it holds+-- and a probability distribution over the set of possible values. data Variable = Variable {possible::[Int], valueIndex::Int,    distr::Distribution} deriving (Show) @@ -28,7 +60,7 @@   rnf (Variable possible valueIndex distr) = rnf (possible, valueIndex, distr)  -- |Each constraint function ([Int] -> Bool) is associated with a certain set of--- variables. 'ConstraintEl' represents this relationship for a constraint+-- variables. 'ConstraintEl' represents this relationship for a given constraint -- function. data ConstraintEl = ConstraintEl {variableIndices :: [Int],   constraint :: ([Int] -> Bool)}@@ -41,6 +73,7 @@     "Constraint " ++ (show variableIndices)  -- |Returns the number of finite values that a `Distribution` is over.+width :: Distribution -> Int width (Distribution p) = fromIntegral $ length p  -- |Constant, as defined in the research paper "Decentralized Constraint Satisfaction"@@ -48,6 +81,7 @@ b = 0.1 :: Double  -- |Internally called function.+oneIfEqual :: (Eq a) => a -> a -> Int oneIfEqual x val   | val == x = 1   | otherwise = 0@@ -62,17 +96,21 @@ -- @ --  'Distribution' [0.2, 0.2, 0.2, 0.2, 0.2]. -- @+initDistribution :: Int -> Distribution initDistribution width = Distribution $    replicateDouble width (1.0/(fromIntegral width))  -- |Adjust probability for the value which has just failed a constraint.-failureCurrProb width currValue = (1.0-b)*currValue+failureCurrProb :: Int -> Double -> Double+failureCurrProb _ currValue = (1.0-b)*currValue  -- |Adjust probability for values other than the one that just failed a constraint.-failureOtherProb width currValue = ((1.0-b)*currValue) + (b/(width-1.0))+failureOtherProb :: Int -> Double -> Double +failureOtherProb width currValue = ((1.0-b)*currValue) + (b/((fromIntegral $ width)-1.0))  -- |Adjust probability of taking on a value for a certain 'Variable' given that -- a constraint was just failed.+failureProb :: Int -> Int -> Double -> Int -> Double failureProb width valueIndex currValue currIndex   | valueIndex == currIndex = failureCurrProb width currValue   | otherwise = failureOtherProb width currValue@@ -81,28 +119,34 @@ -- If successful, then set the probability of the current value to 1.0 and the -- probability for every other value to 0.0.  -- Otherwise, update it with failureProb.+updateProb :: Distribution -> Int -> Bool -> Distribution updateProb dist@(Distribution p) valueIndex success   -- if successful, we update the distribution-  | success = Distribution $ map (\x -> oneIfEqual (snd x) valueIndex) $ zip p [0..]+  | success = Distribution $ +    map (\x -> fromIntegral $ oneIfEqual (snd x) valueIndex) $ zip p [0..]   | otherwise = Distribution $ map (\x ->      failureProb (width dist) valueIndex (fst x) (snd x)) $ zip p [0..]  -- |Same as 'updateProb', but rather than returning a 'Distribution', this function -- returns a 'Variable'.+updateVariableProb :: Variable -> Bool -> Variable updateVariableProb (Variable possib valIndex dist) success =    Variable possib valIndex $ updateProb dist valIndex success  -- |Internal iteration function used by 'cummDistribution'.+cummDistributionIter :: Distribution -> Int -> Double -> [Double] cummDistributionIter dist@(Distribution p) ind curr   | ind == length p = []   | otherwise = newCurr : (cummDistributionIter dist (ind + 1) (newCurr)) where     newCurr = curr + (p !! ind)  -- |Creates a cummulative 'Distribution' out of a given 'Distribution'.+cummDistribution :: Distribution -> Distribution cummDistribution dist@(Distribution p) = Distribution $ cummDistributionIter dist 0 0  -- |Given a cummulative 'Distribution', this function returns the where a random -- value should be "placed" within the 'Distribution'.+getValueIndex :: Distribution -> Double -> Int getValueIndex (Distribution p) randValue =    length $ takeWhile (\x -> randValue > (fst x)) $ zip p [0..] @@ -113,6 +157,7 @@   return x  -- |Randomize the value of a 'Variable'.+randomizeVariable :: Variable -> IO Variable randomizeVariable var@(Variable p v dist) = do   randVal <- randomNum   let newValIndex = getValueIndex (cummDistribution dist) randVal in@@ -128,6 +173,7 @@   foldr (&&) True $ map (\c -> evalConstraint c values) constraints  -- |Apply a function at only one index of a list. Internal function.+applyAt :: (a -> a) -> Int -> [a] -> [a] applyAt f index list =    map (\x -> if (snd x) == index then f (fst x)                                  else (fst x)) $ zip list [0..]@@ -139,6 +185,7 @@   [constraint | ConstraintEl [a, b] constraint <- constraintSet, ((a == n) || (b == n))]  -- |Get the constraint functions out of a list of 'ConstraintEl's.+justConstraints :: [ConstraintEl] -> [[Int] -> Bool] justConstraints = map constraint  -- |Get a list of values from a list of 'Variable's.@@ -151,9 +198,11 @@                                          else return $ (fst x)) $ zip variables [0..]  -- | Randomize all the variables in a list.+randomize :: [Variable] -> [IO Variable] randomize variables = map randomizeVariable variables  -- |Print variables.+printVariables :: [Variable] -> [IO ()] printVariables variables = do   map (putStrLn . show) variables @@ -197,10 +246,12 @@  -- |Checks if every probability in the distribution is either 0 or 1. If it is, -- then, all constraints have been satisfied.+checkDistrSolved :: Distribution -> Bool checkDistrSolved (Distribution probab) = all (\x -> x == 0.0 || x == 1.0) probab  -- |Check if the constraints have been solved by looking at the distributions -- of each 'Variable'.+checkSolved :: [Variable] -> Bool checkSolved [] = True checkSolved (var:vars)   | checkDistrSolved $ distr var = checkSolved vars@@ -208,7 +259,7 @@  -- |This is the moost important function within this library. Given a list of -- 'Variable' and a list of 'ConstraintEl', the library uses the Communcation Free Learning--- Algorithm to return a 'Solved' value. Note that the implementation is not parallelized./+-- Algorithm to return a 'Solved' value. See 'solveThreaded' for a parallelized implementation. solve :: [Variable] -> [ConstraintEl] -> IO Solved solve vars constraints = do   rvars <- updateEachTimes vars constraints 10@@ -226,25 +277,25 @@  -- |Updates each variable in the variable set a number of times and does each -- variable's update in a separate thread.-updateEachThreaded :: Int -> [Variable] -> [ConstraintEl] -> IO [Variable]-updateEachThreaded numThreads variables constraints = do+updateEachParallel :: [Variable] -> [ConstraintEl] -> IO [Variable]+updateEachParallel variables constraints = do   m <- sequence $ map (updateMapF variables constraints) [0..(length variables)]   -- evaluate the map in parallel   let mp = m `using` parList rdeepseq in return mp -updateEachTimesThreaded :: Int -> [Variable] -> [ConstraintEl] -> Int -> IO [Variable]-updateEachTimesThreaded numThreads variables constraints times+updateEachTimesParallel :: [Variable] -> [ConstraintEl] -> Int -> IO [Variable]+updateEachTimesParallel variables constraints times   | times == 0 = return variables   | otherwise = do-    rvars <- updateEachThreaded numThreads variables constraints-    updateEachTimesThreaded numThreads variables constraints (times - 1)+    rvars <- updateEachParallel variables constraints+    updateEachTimesParallel variables constraints (times - 1)  -- |Solve the constraint set in parallel using Haskell threads. In order for -- the solution to be parallelized, the program using DCFL must be compiled -- with GHC's '-threaded' option.-solveThreaded :: Int -> [Variable] -> [ConstraintEl] -> IO Solved-solveThreaded numThreads vars constraints = do-  rvars <- updateEachTimesThreaded numThreads vars constraints 10+solveParallel :: [Variable] -> [ConstraintEl] -> IO Solved+solveParallel vars constraints = do+  rvars <- updateEachTimesParallel vars constraints 10   if checkSolved rvars     then return $ Solved rvars 0     else do