如何在haskell中生成随机命题公式(CNF)?

时间:2014-04-30 00:23:10

标签: haskell smt satisfiability

如何在haskell中获得随机命题公式?我最好需要CNF中的公式,但我会

我想使用也涉及SAT求解器的性能测试公式。请注意,我的目标不是测试SAT求解器的性能!我对非常困难的公式也不感兴趣,因此难度应该是随机的,否则只包括简单的公式。

我知道我的真实世界数据导致了SAT求解器并不困难的命题公式。

目前,我使用hattSBV库作为数据结构来处理命题公式。我还查看了hGen库,也许它可以用来生成随机公式。但是没有文档,我没有看到hGen的源代码。

我的目标是选择n并获取包含n布尔变量的公式。

2 个答案:

答案 0 :(得分:5)

如果你想随机生成一些东西,我建议使用一个非确定性monad,其中MonadRandom是一个受欢迎的选择。

我建议对此过程提出两个输入:vars,变量数和clauses子句数。当然,您也可以使用相同的想法随机生成子句数量。这是一个草图:

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)

我在where子句中包含了可选类型签名,以便更容易遵循该结构。

基本上,遵循你想要产生的“语法”;每个非终端关联者都有一个gen*函数。

我不知道如何判断CNF表达是容易还是困难。

答案 1 :(得分:3)

使用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)