toysolver-0.5.0: app/toyfmf.hs
{-# LANGUAGE CPP, TypeFamilies, OverloadedStrings #-}
-----------------------------------------------------------------------------
-- |
-- Module : toyfmf
-- Copyright : (c) Masahiro Sakai 2012
-- License : BSD-style
--
-- Maintainer : masahiro.sakai@gmail.com
-- Stability : experimental
-- Portability : non-portable (CPP, TypeFamilies, OverloadedStrings)
--
-- A toy-level model finder
--
-----------------------------------------------------------------------------
module Main where
import Control.Monad
import Data.Interned (intern, unintern)
import Data.IORef
import qualified Data.Map as Map
import Data.Monoid
import Data.Ratio
import Data.String
import qualified Data.Text as Text
import System.Environment
import System.IO
import qualified Codec.TPTP as TPTP
import ToySolver.Data.Boolean
import qualified ToySolver.EUF.FiniteModelFinder as MF
import ToySolver.Internal.Util (setEncodingChar8)
main :: IO ()
main = do
#ifdef FORCE_CHAR8
setEncodingChar8
#endif
args <- getArgs
case args of
[fpath, size] -> solve fpath (read size)
_ -> hPutStrLn stderr "Usage: toyfmf <file.tptp> <size>"
solve :: FilePath -> Int -> IO ()
solve _ size | size <= 0 = error "<size> should be >=1"
solve fpath size = do
inputs <- TPTP.parseFile fpath
let fs = translateProblem inputs
ref <- newIORef 0
let skolem name _ = do
n <- readIORef ref
let fsym = intern $ unintern name <> "#" <> fromString (show n)
writeIORef ref (n+1)
return fsym
cs <- liftM concat $ mapM (MF.toSkolemNF skolem) fs
ret <- MF.findModel size cs
case ret of
Nothing -> do
putStrLn "s NO MODEL FOUND"
Just m -> do
putStrLn "s SATISFIABLE"
let isSkolem k = Text.any ('#'==) (unintern k)
let m' = m{ MF.mFunctions = Map.filterWithKey (\k _ -> not (isSkolem k)) (MF.mFunctions m) }
forM_ (MF.showModel m') $ \s ->
putStrLn $ "v " ++ s
return ()
-- ---------------------------------------------------------------------------
translateProblem :: [TPTP.TPTP_Input] -> [MF.Formula]
translateProblem inputs = do
i <- inputs
case i of
TPTP.Comment _ -> []
TPTP.Include _ _ -> error "\"include\" is not supported yet "
TPTP.AFormula{ TPTP.name = _, TPTP.role = role, TPTP.formula = formula, TPTP.annotations = _ } ->
return $ translateFormula formula
translateFormula :: TPTP.Formula -> MF.Formula
translateFormula = TPTP.foldF neg quant binop eq rel
where
neg phi = notB $ translateFormula phi
quant q vs phi = foldr q' (translateFormula phi) [fromString v | TPTP.V v <- vs]
where
q' =
case q of
TPTP.All -> MF.Forall
TPTP.Exists -> MF.Exists
binop phi op psi = op' phi' psi'
where
phi' = translateFormula phi
psi' = translateFormula psi
op' =
case op of
(TPTP.:<=>:) -> (.<=>.)
(TPTP.:=>:) -> (.=>.)
(TPTP.:<=:) -> flip (.=>.)
(TPTP.:&:) -> (.&&.)
(TPTP.:|:) -> (.||.)
(TPTP.:~&:) -> \a b -> notB (a .&&. b)
(TPTP.:~|:) -> \a b -> notB (a .||. b)
(TPTP.:<~>:) -> \a b -> notB (a .<=>. b)
eq lhs op rhs =
case op of
(TPTP.:=:) -> MF.Atom $ MF.PApp "=" [lhs', rhs']
(TPTP.:!=:) -> MF.Not $ MF.Atom $ MF.PApp "=" [lhs', rhs']
where
lhs' = translateTerm lhs
rhs' = translateTerm rhs
rel (TPTP.AtomicWord p) ts = MF.Atom $ MF.PApp (fromString p) ts'
where
ts' = map translateTerm ts
translateTerm :: TPTP.Term -> MF.Term
translateTerm = TPTP.foldT str num var app
where
str s = MF.TmApp (fromString (show s)) []
num r = MF.TmApp (fromString (showRational r)) []
var (TPTP.V v) = MF.TmVar (fromString v)
app (TPTP.AtomicWord f) ts = MF.TmApp (fromString f) ts'
where
ts' = map translateTerm ts
showRational r =
if denominator r == 1
then show (numerator r)
else show (numerator r) ++ "/" ++ show (denominator r)
-- ---------------------------------------------------------------------------