packages feed

toysolver-0.9.0: src/ToySolver/Converter/Tseitin.hs

{-# OPTIONS_GHC -Wall #-}
{-# OPTIONS_HADDOCK show-extensions #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  ToySolver.Converter.Tseitin
-- Copyright   :  (c) Masahiro Sakai 2018
-- License     :  BSD-style
--
-- Maintainer  :  masahiro.sakai@gmail.com
-- Stability   :  experimental
-- Portability :  non-portable
--
-----------------------------------------------------------------------------
module ToySolver.Converter.Tseitin
  ( TseitinInfo (..)
  ) where

import qualified Data.Aeson as J
import qualified Data.Aeson.Types as J
import Data.Aeson ((.=), (.:))
import Data.Array.IArray
import qualified Data.IntMap.Strict as IntMap
import qualified Data.Map.Lazy as Map
import qualified Data.Text as T
import ToySolver.Converter.Base
import ToySolver.Internal.JSON
import qualified ToySolver.SAT.Formula as SAT
import ToySolver.SAT.Internal.JSON
import qualified ToySolver.SAT.Types as SAT
import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin

data TseitinInfo = TseitinInfo !Int !Int (SAT.VarMap Tseitin.Formula)
  deriving (Show, Read, Eq)

instance Transformer TseitinInfo where
  type Source TseitinInfo = SAT.Model
  type Target TseitinInfo = SAT.Model

instance ForwardTransformer TseitinInfo where
  transformForward (TseitinInfo _nv1 nv2 defs) m = array (1, nv2) (assocs a)
    where
      -- Use BOXED array to tie the knot
      a :: Array SAT.Var Bool
      a = array (1, nv2) $
            assocs m ++ [(v, Tseitin.evalFormula a phi) | (v, phi) <- IntMap.toList defs]

instance BackwardTransformer TseitinInfo where
  transformBackward (TseitinInfo nv1 _nv2 _defs) = SAT.restrictModel nv1

instance J.ToJSON TseitinInfo where
  toJSON (TseitinInfo nv1 nv2 defs) =
    J.object
    [ "type" .= ("TseitinInfo" :: J.Value)
    , "num_original_variables" .= nv1
    , "num_transformed_variables" .= nv2
    , "definitions" .= J.object
        [ jVarName v .= formula
        | (v, formula) <- IntMap.toList defs
        ]
    ]

instance J.FromJSON TseitinInfo where
  parseJSON = withTypedObject "TseitinInfo" $ \obj -> do
    defs <- obj .: "definitions"
    TseitinInfo
      <$> obj .: "num_original_variables"
      <*> obj .: "num_transformed_variables"
      <*> (IntMap.fromList <$> mapM f (Map.toList defs))
    where
      f :: (T.Text, SAT.Formula) -> J.Parser (SAT.Var, SAT.Formula)
      f (name, formula) = do
        x <- parseVarNameText name
        pure (x, formula)

-- -----------------------------------------------------------------------------