如何在haskell中获得随机命题公式?我最好需要CNF中的公式,但我会
我想使用也涉及SAT求解器的性能测试公式。请注意,我的目标不是测试SAT求解器的性能!我对非常困难的公式也不感兴趣,因此难度应该是随机的,否则只包括简单的公式。
我知道我的真实世界数据导致了SAT求解器并不困难的命题公式。
目前,我使用hatt和SBV库作为数据结构来处理命题公式。我还查看了hGen库,也许它可以用来生成随机公式。但是没有文档,我没有看到hGen的源代码。
我的目标是选择n
并获取包含n
布尔变量的公式。
答案 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)