Advertisement
Guest User

Untitled

a guest
Jul 20th, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- module to parse CNF (Dimacs) format of problems and solutions
  2.  
  3. module Cnf
  4.   ( parseProblem
  5.   , parseSolution
  6.   , myParse
  7.   , CNFProblem(..)
  8.   , Solution(..)
  9.   , Trail
  10.   , Clause
  11.   , Clauses
  12.   ) where
  13.  
  14. import Control.Applicative ((<*), (*>))
  15. import Text.ParserCombinators.Parsec hiding (spaces)
  16. import Data.Set (Set, fromList)
  17.  
  18. -- data structures
  19.  
  20. data Solution =
  21.   Sat | Unsat | Unknown
  22.   deriving (Show, Eq)
  23.  
  24. data CNFProblem = CNFProblem
  25.   { numClauses :: Int
  26.   , numVars    :: Int
  27.   , clauses    :: [Clause]
  28.   } deriving (Show, Eq)
  29.  
  30. type Trail = Set Int
  31. type Clause = Set Int
  32. type Clauses = [Clause]
  33.  
  34. -- parse function
  35. myParse :: Parser a -> String -> a
  36. myParse parser input = either (error . show) id $ parse parser "" input
  37.  
  38. -- parse problem
  39.  
  40. parseProblem :: Parser CNFProblem
  41. parseProblem = do
  42.   problem <- skipMany commentLine *> problemLine
  43.   clauses <- skipMany commentLine *> (clause `endBy` nspaces) <* eof
  44.   return $ problem { clauses = map fromList clauses }
  45.  
  46. commentLine :: Parser Char
  47. commentLine = char 'c' >> skipMany (noneOf "\n") >> newline
  48.  
  49. problemLine :: Parser CNFProblem
  50. problemLine = do
  51.   numVars <- (char 'p' >> spaces >> string "cnf" >> spaces) *> int
  52.   numClauses <- spaces *> int <* nspaces
  53.   return $ CNFProblem numClauses numVars []
  54.  
  55. clause :: Parser [Int]
  56. clause = do
  57.   literal <- int
  58.   if literal == 0
  59.     then return []
  60.     else do -- recurse (read the rest of clause)
  61.       c <- nspaces *> clause
  62.       return $ literal : c
  63.  
  64. int :: Parser Int
  65. int = do
  66.   neg <- optionMaybe (char '-')
  67.   digits <- many1 digit
  68.   return $ (if neg == Nothing then 1 else (-1)) * read digits
  69.  
  70. spaces = skipMany (oneOf " \t")
  71. nspaces = skipMany (oneOf " \t\n")
  72.  
  73. -- parse solution
  74. parseSolution :: Parser (Solution, Trail)
  75. parseSolution = do
  76.   skipMany commentLine >> char 's' >> spaces
  77.   sol <- (string "SATISFIABLE" <|> string "UNSATISFIABLE" <|> string "UNKNOWN")
  78.   skipMany (oneOf " \t\n")
  79.   trail <- readTrail <|> return []
  80.   return (readSolution sol, fromList trail)
  81.  
  82. readTrail :: Parser [Int]
  83. readTrail = do
  84.   i <- skipMany (oneOf "v \t\n") *> int
  85.   if i == 0
  86.     then return []
  87.     else do
  88.       trail <- readTrail
  89.       return $ i : trail
  90.  
  91. -- read a solution
  92. readSolution :: String -> Solution
  93. readSolution "SATISFIABLE"    = Sat
  94. readSolution "UNSATISFIABLE"  = Unsat
  95. readSolution "UNKNOWN"        = Unknown
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement