How can I get a random propositional formula in haskell? Preferably I need the formula in CNF, but I would
I want to use the formulas for performance testing that also involves SAT solvers. Please note that my goal is not to test the performance of SAT solvers! I am also not interested in very difficult formulas, so the difficulty should be random or otherwise only include easy formulas.
I know that my real world data leads to propositional formulas that are not difficult for SAT solvers.
At the moment I use the hatt and SBV libraries as data structures to work with propositional formulas. I also looked at the hGen library, perhaps it can be used to generate the random formulas. However there is no documentation and I didn’t get far by looking at the source code of hGen.
My goal is to chose n and get back a formula that includes n boolean variables.
If you want to generate something randomly, I suggest a nondeterminism monad, of which MonadRandom is a popular choice.
I would suggest two inputs to this procedure: vars, the number of variables, and clauses the number of clauses. Of course you could always generate the number of clauses at random as well, using this same idea. Here's a sketch:
import Control.Monad.Random (Rand, StdGen, uniform)
import Control.Applicative ((<$>))
import Control.Monad (replicateM)
type Cloud = Rand StdGen -- for "probability cloud"
newtype Var = Var Int
data Atom = Positive Var -- X
| Negative Var -- not X
type CNF = [[Atom]] -- conjunction of disjunctions
genCNF :: Int -> Int -> Cloud CNF
genCNF vars clauses = replicateM clauses genClause
where
genClause :: Could [Atom]
genClause = replicateM 3 genAtom -- for CNF-3
genAtom :: Cloud Atom
genAtom = do
f <- uniform [Positive, Negative]
v <- Var <$> uniform [0..vars-1]
return (f v)
I included the optional type signatures in the where clause to make it easier to follow the structure.
Essentially, follow the "grammar" of what you are trying to generate; with each nonterminal associate with a gen* function.
I don't know how to judge whether a CNF expression is easy or hard.
Using the types in hatt:
import Data.Logic.Propositional
import System.Random
import Control.Monad.State
import Data.Maybe
import Data.SBV
type Rand = State StdGen
rand :: Random a => (a, a) -> Rand a
rand = state . randomR
runRand :: Rand a -> IO a
runRand r = randomIO >>= return . fst . runState r . mkStdGen
randFormula :: Rand Expr
randFormula = rand (3, 10) >>= randFormulaN 50
randFormulaN :: Int -> Int -> Rand Expr
randFormulaN negC n = replicateM n clause >>= return . foldl1 Conjunction
where vars = take n (map (Variable . Var) ['a'..])
clause = rand (1, n) >>= mapM f . flip take vars >>= return . foldl1 Disjunction
f v = rand (0,100) >>= \neg -> return (if neg <= negC then Negation v else v)
Related
I beg for your help, speeding up the following program:
main = do
jobsToProcess <- fmap read getLine
forM_ [1..jobsToProcess] $ \_ -> do
[r, k] <- fmap (map read . words) getLine :: IO [Int]
putStrLn $ doSomeReallyLongWorkingJob r k
There could(!) be a lot of identical jobs to do, but it's not up to me modifying the inputs, so I tried to use Data.HashMap for backing up already processed jobs. I already optimized the algorithms in the doSomeReallyLongWorkingJob function, but now it seems, it's quite as fast as C.
But unfortunately it seems, I'm not able to implement a simple cache without producing a lot of errors. I need a simple cache of Type HashMap (Int, Int) Int, but everytime I have too much or too few brackets. And IF I manage to define the cache, I'm stuck in putting data into or retrieving data from the cache cause of lots of errors.
I already Googled for some hours but it seems I'm stuck. BTW: The result of the longrunner is an Int as well.
It's pretty simple to make a stateful action that caches operations. First some boilerplate:
{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.State
import Data.Map (Map)
import qualified Data.Map as M
import Debug.Trace
I'll use Data.Map, but of course you can substitute in a hash map or any similar data structure without much trouble. My long-running computation will just add up its arguments. I'll use trace to show when this computation is executed; we'll hope not to see the output of the trace when we enter a duplicate input.
reallyLongRunningComputation :: [Int] -> Int
reallyLongRunningComputation args = traceShow args $ sum args
Now the caching operation will just look up whether we've seen a given input before. If we have, we'll return the precomputed answer; otherwise we'll compute the answer now and store it.
cache :: (MonadState (Map a b) m, Ord a) => (a -> b) -> a -> m b
cache f x = do
mCached <- gets (M.lookup x)
case mCached of
-- depending on your goals, you may wish to force `result` here
Nothing -> modify (M.insert x result) >> return result
Just cached -> return cached
where
result = f x
The main function now just consists of calling cache reallyLongRunningComputation on appropriate inputs.
main = do
iterations <- readLn
flip evalStateT M.empty . replicateM_ iterations
$ liftIO getLine
>>= liftIO . mapM readIO . words
>>= cache reallyLongRunningComputation
>>= liftIO . print
Let's try it in ghci!
> main
5
1 2 3
[1,2,3]
6
4 5
[4,5]
9
1 2
[1,2]
3
1 2
3
1 2 3
6
As you can see by the bracketed outputs, reallyLongRunningComputation was called the first time we entered 1 2 3 and the first time we entered 1 2, but not the second time we entered these inputs.
I hope i'm not too far off base, but first you need a way to carry around the past jobs with you. Easiest would be to use a foldM instead of a forM.
import Control.Monad
import Data.Maybe
main = do
jobsToProcess <- fmap read getLine
foldM doJobAcc acc0 [1..jobsToProcess]
where
acc0 = --initial value of some type of accumulator, i.e. hash map
doJobAcc acc _ = do
[r, k] <- fmap (map read . words) getLine :: IO [Int]
case getFromHash acc (r,k) of
Nothing -> do
i <- doSomeReallyLongWorkingJob r k
return $ insertNew acc (r,k) i
Just i -> do
return acc
Note, I don't actually use the interface for putting and getting the hash table key. It doesn't actually have to be a hash table, Data.Map from containers could work. Or even a list if its going to be a small one.
Another way to carry around the hash table would be to use a State transformer monad.
I am just adding this answer since I feel like the other answers are diverging a bit from the original question, namely using hashtable constructs in Main function (inside IO monad).
Here is a minimal hashtable example using hashtables module. To install the module with cabal, simply use
cabal install hashtables
In this example, we simply put some values in a hashtable and use lookup to print a value retrieved from the table.
import qualified Data.HashTable.IO as H
main :: IO ()
main = do
t <- H.new :: IO (H.CuckooHashTable Int String)
H.insert t 22 "Hello world"
H.insert t 5 "No problem"
msg <- H.lookup t 5
print msg
Notice that we need to use explicit type annotation to specify which implementation of the hashtable we wish to use.
I am trying to generate a sample of random numbers in Haskell
import System.Random
getSample n = take n $ randoms g where
g = newStdGen
but it seems I am not quite using newStdGen the right way. What am I missing?
First off, you probably don't want to use newStdGen. The biggest problem is that you'll get a different seed every time you run your program, so no results will be reproducible. In my opinion, mkStdGen is a better choice as it requires you to give it a seed. This means you will get the same sequence of (pseudo)random numbers every time. If you want a different sequence, just change the seed.
The second problem with newStdGen is that since it's impure, you'll end up in the IO monad which can be a bit inconvenient.
sample :: Int -> IO [Int]
sample n = do
gen <- newStdGen
return $ take n $ randoms gen
You can use do-notation to 'extract' the values and then sum them:
main :: IO ()
main = do
xs <- sample 10
s = sum xs
print s
Or you could 'fmap' the function over the result (but notice that at some point you will probably need to extract the value):
main :: IO ()
main = do
s <- fmap sum $ sample 10
print s
The fmap function is a generalized version of map. Just like map applies a function to the values inside a list, fmap can apply a function to values inside IO.
Another problem with this sample function is that if we call it again, it starts with a fresh seed instead of continuing the previous (pseudo)random sequence. Again, this make reproducing results impossible. In order to fix this problem, we need to pass in the seed and return a new seed. Unfortunately, randoms does not return the next seed for us, so we'll have to write this from scratch using random.
sample :: Int -> StdGen -> ([Int],StdGen)
sample n seed1 = case n of
0 -> ([],seed1)
k -> let (rs,seed2) = sample (k-1) seed1
(r, seed3) = random seed2
in ((r:rs),seed3)
Our main function is now
main :: IO ()
main = do
let seed1 = mkStdGen 123456
(xs,seed2) = sample 10 seed1
s = sum xs
(ys,seed3) = sample 10 seed2
t = sum ys
print s
print t
I know this seems like an awful lot of work just to to use random numbers, but the advantages are worth it. We can generate all of our randomness with a single seed which guarantees that the results can be reproduced.
Of course, this being Haskell, we can take advantage of Monads to get rid of all the manual threading of the seed values. This is a slightly more advanced method, but well worth learning since monads are ubiquitous in Haskell code.
We need these imports:
import System.Random
import Control.Monad
import Control.Applicative
Then we'll create a newtype which represents the action of turning a seed into a value and the next seed.
newtype Rand a = Rand { runRand :: StdGen -> (a,StdGen) }
We need Functor and Applicative instances or GHC will complain, but we can avoid implementing them for this example.
instance Functor Rand
instance Applicative Rand
And now for the Monad instance. This is where the magic happens. The >>= function (called bind) is the one place where we specify how to thread the seed value through the computation.
instance Monad Rand where
return x = Rand ( \seed -> (x,seed) )
ra >>= f = Rand ( \s1 -> let (a,s2) = runRand ra s1
in runRand (f a) s2 )
newRand :: Rand Int
newRand = Rand ( \seed -> random seed )
Now our sample function is extremely simple! We can take advantage of replicateM from Control.Monad which repeats a given action and accumulates the results in a list. All that funny business with the seed values is taken care of behind the scenes
sample :: Int -> Rand [Int]
sample n = replicateM n newRand
main :: IO ()
main = do
let seed1 = mkStdGen 124567
(xs,seed2) = runRand (sample 10) seed1
s = sum xs
print s
We can even stay inside the Rand monad if we need to generate random values multiple times.
main :: IO ()
main = do
let seed1 = mkStdGen 124567
(xs,seed2) = flip runRand seed1 $ do
x <- newRand
bs <- sample 5
cs <- sample 10
return $ x : (bs ++ cs)
s = sum xs
print s
I hope this helps!
This question already has answers here:
Random number in Haskell [duplicate]
(5 answers)
Closed 8 years ago.
I am in the process of learning Haskell and to learn I want to generate a random Int type. I am confused because the following code works. Basically, I want an Int not an IO Int.
In ghci this works:
Prelude> import System.Random
Prelude System.Random> foo <- getStdRandom (randomR (1,1000000))
Prelude System.Random> fromIntegral foo :: Int
734077
Prelude System.Random> let bar = fromIntegral foo :: Int
Prelude System.Random> bar
734077
Prelude System.Random> :t bar
bar :: Int
So when I try to wrap this up with do it fails and I don't understand why.
randomInt = do
tmp <- getStdRandom (randomR (1,1000000))
fromIntegral tmp :: Int
The compiler produces the following:
Couldn't match expected type `IO b0' with actual type `Int'
In a stmt of a 'do' block: fromIntegral tmp :: Int
In the expression:
do { tmp <- getStdRandom (randomR (1, 1000000));
fromIntegral tmp :: Int }
In an equation for `randomInt':
randomInt
= do { tmp <- getStdRandom (randomR (1, 1000000));
fromIntegral tmp :: Int }
Failed, modules loaded: none.
I am new to Haskell, so if there is a better way to generate a random Int without do that would be preferred.
So my question is, why does my function not work and is there a better way to get a random Int.
The simple answer is that you can't generate random numbers without invoking some amount of IO. Whenever you get the standard generator, you have to interact with the host operating system and it makes a new seed. Because of this, there is non-determinism with any function that generates random numbers (the function returns different values for the same inputs). It would be like wanting to be able to get input from STDIN from the user without it being in the IO monad.
Instead, you have a few options. You can write all your code that depends on a randomly generated value as pure functions and only perform the IO to get the standard generator in main or some similar function, or you can use the MonadRandom package that gives you a pre-built monad for managing random values. Since most every pure function in System.Random takes a generator and returns a tuple containing the random value and a new generator, the Rand monad abstracts this pattern out so that you don't have to worry about it. You can end up writing code like
import Control.Monad.Random hiding (Random)
type Random a = Rand StdGen a
rollDie :: Int -> Random Int
rollDie n = getRandomR (1, n)
d6 :: Random Int
d6 = rollDie 6
d20 :: Random Int
d20 = rollDie 20
magicMissile :: Random (Maybe Int)
magicMissile = do
roll <- d20
if roll > 15
then do
damage1 <- d6
damage2 <- d6
return $ Just (damage1 + damage2)
else return Nothing
main :: IO ()
main = do
putStrLn "I'm going to cast Magic Missile!"
result <- evalRandIO magicMissile
case result of
Nothing -> putStrLn "Spell fizzled"
Just d -> putStrLn $ "You did " ++ show d ++ " damage!"
There's also an accompanying monad transformer, but I'd hold off on that until you have a good grasp on monads themselves. Compare this code to using System.Random:
rollDie :: Int -> StdGen -> (Int, StdGen)
rollDie n g = randomR (1, n) g
d6 :: StdGen -> (Int, StdGen)
d6 = rollDie 6
d20 :: StdGen -> (Int, StdGen)
d20 = rollDie 20
magicMissile :: StdGen -> (Maybe Int, StdGen)
magicMissile g =
let (roll, g1) = d20 g
(damage1, g2) = d6 g1
(damage2, g3) = d6 g2
in if roll > 15
then (Just $ damage1 + damage2, g3)
else Nothing
main :: IO ()
main = do
putStrLn "I'm going to case Magic Missile!"
g <- getStdGen
let (result, g1) = magicMissile g
case result of
Nothing -> putStrLn "Spell fizzled"
Just d -> putStrLn $ "You did " ++ show d ++ " damage!"
Here we have to manually have to manage the state of the generator and we don't get the handy do-notation that makes our order of execution more clear (laziness helps in the second case, but it makes it more confusing). Manually managing this state is boring, tedious, and error prone. The Rand monad makes everything much easier, more clear, and reduces the chance for bugs. This is usually the preferred way to do random number generation in Haskell.
It is worth mentioning that you can actually "unwrap" an IO a value to just an a value, but you should not use this unless you are 100% sure you know what you're doing. There is a function called unsafePerformIO, and as the name suggests it is not safe to use. It exists in Haskell mainly for when you are interfacing with the FFI, such as with a C DLL. Any foreign function is presumed to perform IO by default, but if you know with absolute certainty that the function you're calling has no side effects, then it's safe to use unsafePerformIO. Any other time is just a bad idea, it can lead to some really strange behaviors in your code that are virtually impossible to track down.
I think the above is slightly misleading. If you use the state monad then you can do something like this:
acceptOrRejects :: Int -> Int -> [Double]
acceptOrRejects seed nIters =
evalState (replicateM nIters (sample stdUniform))
(pureMT $ fromIntegral seed)
See here for an extended example of usage:Markov Chain Monte Carlo
I am building some moderately large DIMACS files, however with the method used below the memory usage is rather large compared to the size of the files generated, and on some of the larger files I need to generate I run in to out of memory problems.
import Control.Monad.State.Strict
import Control.Monad.Writer.Strict
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Monad
import qualified Text.Show.ByteString as BS
import Data.List
main = printDIMACS "test.cnf" test
test = do
xs <- freshs 100000
forM_ (zip xs (tail xs))
(\(x,y) -> addAll [[negate x, negate y],[x,y]])
type Var = Int
type Clause = [Var]
data DIMACSS = DS{
nextFresh :: Int,
numClauses :: Int
} deriving (Show)
type DIMACSM a = StateT DIMACSS (Writer B.ByteString) a
freshs :: Int -> DIMACSM [Var]
freshs i = do
next <- gets nextFresh
let toRet = [next..next+i-1]
modify (\s -> s{nextFresh = next+i})
return toRet
fresh :: DIMACSM Int
fresh = do
i <- gets nextFresh
modify (\s -> s{nextFresh = i+1})
return i
addAll :: [Clause] -> DIMACSM ()
addAll c = do
tell
(B.concat .
intersperse (B.pack " 0\n") .
map (B.unwords . map BS.show) $ c)
tell (B.pack " 0\n")
modify (\s -> s{numClauses = numClauses s + length c})
add h = addAll [h]
printDIMACS :: FilePath -> DIMACSM a -> IO ()
printDIMACS file f = do
writeFile file ""
appendFile file (concat ["p cnf ", show i, " ", show j, "\n"])
B.appendFile file b
where
(s,b) = runWriter (execStateT f (DS 1 0))
i = nextFresh s - 1
j = numClauses s
I would like to keep the monadic building of clauses since it is very handy, but I need to overcome the memory problem. How do I optimize the above program so that it doesn't use too much memory?
If you want good memory behavior, you need to make sure that you write out the clauses as you generate them, instead of collecting them in memory and dumping them as such, either using lazyness or a more explicit approach such as conduits, enumerators, pipes or the like.
The main obstacle to that approach is that the DIMACS format expects the number of clauses and variables in the header. This prevents the naive implementation from being sufficiently lazy. There are two possibilities:
The pragmatic one is to write the clauses first to a temporary location. After that the numbers are known, so you write them to the real file and append the contents of the temporary file.
The prettier approach is possible if the generation of clauses has no side effects (besides the effects offered by your DIMACSM monad) and is sufficiently fast: Run it twice, first throwing away the clauses and just calculating the numbers, print the header line, run the generator again; now printing the clauses.
(This is from my experience with implementing SAT-Britney, where I took the second approach, because it fitted better with other requirements in that context.)
Also, in your code, addAll is not lazy enough: The list c needs to be retained even after writing (in the MonadWriter sense) the clauses. This is another space leak. I suggest you implement add as the primitive operation and then addAll = mapM_ add.
As explained in Joachim Breitner's answer the problem was that DIMACSM was not lazy enough, both because the strict versions of the monads was used and because the number of variables and clauses are needed before the ByteString can be written to the file. The solution is to use the lazy versions of the Monads and execute them twice. It turns out that it is also necessary to have WriterT be the outer monad:
import Control.Monad.State
import Control.Monad.Writer
...
type DIMACSM a = WriterT B.ByteString (State DIMACSS) a
...
printDIMACS :: FilePath -> DIMACSM a -> IO ()
printDIMACS file f = do
writeFile file ""
appendFile file (concat ["p cnf ", show i, " ", show j, "\n"])
B.appendFile file b
where
s = execState (execWriterT f) (DS 1 0)
b = evalState (execWriterT f) (DS 1 0)
i = nextFresh s - 1
j = numClauses s
What are the recommended Haskell packages for pure pseudo-random generators (uniform Doubles)?
I'm interested in a convenient API in the first place, speed would be nice too.
Maybe mwc-random?
I like the mersenne-random-pure64 package. For example you can use it like this to generate an infinite lazy stream of random doubles from a seed value:
import Data.Word (Word64)
import Data.List (unfoldr)
import System.Random.Mersenne.Pure64
randomStream :: (PureMT -> (a, PureMT)) -> PureMT -> [a]
randomStream rndstep g = unfoldr (Just . rndstep) g
toStream :: Word64 -> [Double]
toStream seed = randomStream randomDouble $ pureMT seed
main = print . take 10 $ toStream 42
using System.Random (randoms)
You can get a similar output with the builtin randoms function, which is shorter and more general (Thanks to ehird for pointing that out):
import System.Random (randoms)
import System.Random.Mersenne.Pure64 (pureMT)
main = print . take 10 $ randomdoubles where
randomdoubles :: [Double]
randomdoubles = randoms $ pureMT 42
making it an instance of MonadRandom
After reading about MonadRandom i got curious how to get PureMT working as an instance of it. Out of the box it doesn't work, because PureMT doesn't instantiate RandomGen's split function. One way to make it work is to wrap PureMT in a newtype and write a custom split instance for the RandomGen typeclass, for which there exists a default MonadRandom instance.
import Control.Monad.Random
import System.Random.Mersenne.Pure64
getTenRandomDoubles :: Rand MyPureMT [Double]
getTenRandomDoubles = getRandoms >>= return . take 10
main = print $ evalRand getTenRandomDoubles g
where g = MyPureMT $ pureMT 42
newtype MyPureMT = MyPureMT { unMyPureMT :: PureMT }
myPureMT = MyPureMT . pureMT
instance RandomGen MyPureMT where
next = nextMyPureMT
split = splitMyPureMT
splitMyPureMT :: MyPureMT -> (MyPureMT, MyPureMT)
splitMyPureMT (MyPureMT g) = (myPureMT s, myPureMT s') where
(s',g'') = randomWord64 g'
(s ,g' ) = randomWord64 g
nextMyPureMT (MyPureMT g) = (s, MyPureMT g') where
(s, g') = randomInt g
The standard System.Random has a pure interface. I would recommend wrapping it in a State g (for whatever generator g you're using) to avoid threading the state; the state function makes turning functions like next into stateful actions easy:
next :: (RandomGen g) => g -> (Int, g)
state :: (s -> (a, s)) -> State s a
state next :: (RandomGen g) => State g Int
The MonadRandom package is based on the State g interface with pre-written wrappers for the generator functions; I think it's fairly popular.
Note that you can still run actions using this pure interface on the global RNG. MonadRandom has evalRandIO for the purpose.
I think you could write an (orphan) RandomGen instance to use mwc-random with these.
A particularly nice package with a pure interface that is also suitable for cryptographic applications and yet maintains a high performance is the cprng-aes package.
It provides two interfaces: A deterministic pure one using the type classes from System.Random as well as a strong IO interface using the type classes from the Crypto-API package.
As a side note: I would generally prefer the mersenne-random packages over mwc-random. They use the original Mersenne Twister algorithm and in my benchmarks outperformed mwc-random by a large factor.