packages feed

satchmo-2.9.7: Satchmo/SAT/CNF.hs

-- | use this module to get the actual
-- conjunctive normal form (a list of clauses).
-- You can then send this to minisat,
-- and do your own statistics and preprocessing first

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DoAndIfThenElse #-}
{-# LANGUAGE PatternSignatures #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}


module Satchmo.SAT.CNF

( SAT
, fresh
, emit
, solve
)

where

import qualified MiniSat as API

import Satchmo.Data
import Satchmo.Boolean hiding ( not )
import Satchmo.Code
import Satchmo.MonadSAT
import Satchmo.Fourier_Motzkin ( fomo )

import Control.Monad
import Control.Monad.State.Strict
import Control.Monad.Reader

import Control.Applicative
import Control.Lens
import Data.Monoid
import Data.Foldable
import qualified Data.Map.Strict as M
import System.IO

data S = S { _next :: ! Variable
           , _output :: ! CNF
           -- , _assignment :: ! (M.Map Variable Bool)
           }

$(makeLenses ''S)

newtype SAT a = SAT { unSAT :: StateT S IO a }
  deriving ( Functor, Applicative, Monad, MonadIO, MonadState S )

instance MonadFix SAT -- dummy

instance MonadSAT SAT where
  fresh = do
      x <- get
      modify ( next %~ succ )
      return $ literal True $ x ^. next

  emit cl = do      
      modify ( output %~ ( singleton cl <> ) )

  note msg = liftIO $ hPutStrLn stderr msg

  type Decoder SAT = Reader (M.Map Variable Bool)
  decode_variable v = do m <- ask ; return $ m M.! v
      
instance Decode (Reader (M.Map Variable Bool)) Boolean Bool where
    decode b = case b of
        Constant c -> return c
        Boolean  l -> do 
            v <- -- decode_variable $ variable l
              do m <- ask ; return $ M.findWithDefault False ( variable l ) m
            return $ if positive l then v else not v

solve :: SAT (Decoder SAT a) -> IO (Maybe a)
solve action = do
  (a,s) <- runStateT (unSAT action)
           $ S { _next = 1, _output = cnf [] }
  mm <- fomo $ s^.output
  return $ case mm of
    Nothing -> Nothing
    Just m -> Just $ runReader a m