如果你想随机生成一些东西,我建议使用非确定性 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 表达式是简单还是困难。