packages feed

puresat-0.1: exe/puresat.hs

module Main (main) where

import Control.Monad
import System.Environment

import qualified PureSAT.Main as PureSAT
import PureSAT.Base
import PureSAT.Prim
import qualified PureSAT.DIMACS

main :: IO ()
main = do
    args <- getArgs
    forM_ args $ \arg -> do
        print arg
        dimacs <- PureSAT.DIMACS.parseDimacsFile arg
        let solution = solvePureSAT dimacs
        if null solution
        then do
            putStrLn "p unsat"
        else do
            putStrLn "p sat"
            putStrLn $ unwords $ map show solution

solvePureSAT :: [[Int]] -> [Int]
solvePureSAT clauses = runST $ do
    s <- PureSAT.newSolver

    -- create literal
    literals <- newPrimArray maxLiteral
    forM_ [1..maxLiteral] $ \i -> do
        l <- PureSAT.newLit s
        writePrimArray literals (i - 1) l

    -- addClauses
    forM_ clauses $ \clause -> do
        clause' <- forM clause $ \i -> do
            l <- readPrimArray literals (abs i - 1)
            return $ if i < 0 then PureSAT.neg l else l

        PureSAT.addClause s clause'

    -- solve
    res <- PureSAT.solve s

    -- read back the solution
    if res
    then do
        forM [1..maxLiteral] $ \i -> do
            l <- readPrimArray literals (i - 1)
            x <- PureSAT.modelValue s l
            return $ if x then i else negate i

    else return []
  where
    maxLiteral = foldl' (\acc clause -> foldl' (\x y -> max x (abs y)) acc clause) 0 clauses