packages feed

satplus-0.1.0.0: SAT/Equal.hs

{-|
Module      : SAT.Equal
Description : Equality functions on things that live in the SAT-solver

This module provides a type class with functions for asserting the equality
or inequality of two objects, as well as functions that compute whether or
not two objects are equal or not.
-}
module SAT.Equal(
  -- * Constraints
    equal
  , notEqual

  -- * Type class Equal
  , Equal(..)
  )
 where

import SAT
import SAT.Bool
import SAT.Util( unconditionally )

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

-- | Type class for SAT-things that can be equal or not.
class Equal a where
  -- | Add constraints to the Solver that state that the arguments are equal,
  -- under the presence of a /disjunctive prefix/.
  -- (See 'SAT.Util.unconditionally' for what /prefix/ means. This function
  -- without prefix is called 'equal'.)
  equalOr :: Solver -> [Lit] {- ^ prefix -} -> a -> a -> IO ()

  -- | Add constraints to the Solver that state that the arguments are not
  -- equal, under the presence of a /disjunctive prefix/.
  -- (See 'SAT.Util.unconditionally' for what /prefix/ means.
  -- This function without prefix is called 'notEqual'.)
  notEqualOr :: Solver -> [Lit] {- ^ prefix -} -> a -> a -> IO ()

  -- | Return a literal that represents the arguments being equal or not.
  isEqual :: Solver -> a -> a -> IO Lit
  isEqual s x y =
    do q <- newLit s
       equalOr s [neg q] x y
       notEqualOr s [q] x y
       return q

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

-- | Add constraints to the Solver that state that the arguments are equal.
-- See also 'equalOr'.
equal :: Equal a => Solver -> a -> a -> IO ()
equal = unconditionally equalOr

-- | Add constraints to the Solver that state that the arguments are not equal.
-- See also 'notEqualOr'.
notEqual :: Equal a => Solver -> a -> a -> IO ()
notEqual = unconditionally notEqualOr

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

instance Equal () where
  equalOr    s pre _ _ = return ()
  notEqualOr s pre _ _ = addClause s pre
  isEqual    _     _ _ = return true

instance Equal Bool where
  equalOr    s pre x y = if x == y then return () else addClause s pre
  notEqualOr s pre x y = if x /= y then return () else addClause s pre
  isEqual    _     x y = return (bool (x==y))

instance Equal Lit where
  equalOr s pre x y =
    do addClause s (pre ++ [neg x, y])
       addClause s (pre ++ [x, neg y])

  notEqualOr s pre x y =
    do equalOr s pre x (neg y)

  isEqual s x y = xorl s [x, neg y]

instance (Equal a, Equal b) => Equal (a,b) where
  equalOr s pre (x1,x2) (y1,y2) =
    do equalOr s pre x1 y1
       equalOr s pre x2 y2

  notEqualOr s pre (x1,x2) (y1,y2) =
    do q <- newLit s
       notEqualOr s (q:pre) x1 y1
       notEqualOr s [neg q] x2 y2

instance (Equal a, Equal b) => Equal (Either a b) where
  equalOr s pre (Left x)  (Left y)  = equalOr s pre x y
  equalOr s pre (Right x) (Right y) = equalOr s pre x y
  equalOr s pre _         _         = addClause s pre

  notEqualOr s pre (Left x)  (Left y)  = notEqualOr s pre x y
  notEqualOr s pre (Right x) (Right y) = notEqualOr s pre x y
  notEqualOr s pre _         _         = return ()

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

instance (Equal a, Equal b, Equal c) => Equal (a,b,c) where
  equalOr    s pre x y = equalOr    s pre (encTriple x) (encTriple y)
  notEqualOr s pre x y = notEqualOr s pre (encTriple x) (encTriple y)

encTriple (x,y,z) = ((x,y),z)

instance Equal a => Equal (Maybe a) where
  equalOr    s pre mx my = equalOr    s pre (encMaybe mx) (encMaybe my)
  notEqualOr s pre mx my = notEqualOr s pre (encMaybe mx) (encMaybe my)

encMaybe Nothing  = Left ()
encMaybe (Just x) = Right x

instance Equal a => Equal [a] where
  equalOr    s pre xs ys = equalOr    s pre (encList xs) (encList ys)
  notEqualOr s pre xs ys = notEqualOr s pre (encList xs) (encList ys)

encList []     = Nothing
encList (x:xs) = Just (x,xs)

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