{-# language FlexibleInstances, MultiParamTypeClasses, FlexibleContexts #-} module Satchmo.Relation.Data ( Relation , relation, symmetric_relation , build , identity , bounds, (!), indices, assocs, elems , table ) where import Satchmo.Code import Satchmo.Boolean import Satchmo.SAT import qualified Data.Array as A import Data.Array ( Array, Ix ) import Data.Functor ((<$>)) import Control.Monad ( guard, forM ) newtype Relation a b = Relation ( Array (a,b) Boolean ) relation :: ( Ix a, Ix b, MonadSAT m ) => ((a,b),(a,b)) -> m ( Relation a b ) {-# specialize inline relation :: ( Ix a, Ix b) => ((a,b),(a,b)) -> SAT ( Relation a b ) #-} relation :: forall a b (m :: * -> *). (Ix a, Ix b, MonadSAT m) => ((a, b), (a, b)) -> m (Relation a b) relation ((a, b), (a, b)) bnd = do [((a, b), Boolean)] pairs <- [m ((a, b), Boolean)] -> m [((a, b), Boolean)] forall (t :: * -> *) (m :: * -> *) a. (Traversable t, Monad m) => t (m a) -> m (t a) forall (m :: * -> *) a. Monad m => [m a] -> m [a] sequence ([m ((a, b), Boolean)] -> m [((a, b), Boolean)]) -> [m ((a, b), Boolean)] -> m [((a, b), Boolean)] forall a b. (a -> b) -> a -> b $ do (a, b) p <- ((a, b), (a, b)) -> [(a, b)] forall a. Ix a => (a, a) -> [a] A.range ((a, b), (a, b)) bnd m ((a, b), Boolean) -> [m ((a, b), Boolean)] forall a. a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return (m ((a, b), Boolean) -> [m ((a, b), Boolean)]) -> m ((a, b), Boolean) -> [m ((a, b), Boolean)] forall a b. (a -> b) -> a -> b $ do Boolean x <- m Boolean forall (m :: * -> *). MonadSAT m => m Boolean boolean ((a, b), Boolean) -> m ((a, b), Boolean) forall a. a -> m a forall (m :: * -> *) a. Monad m => a -> m a return ( (a, b) p, Boolean x ) Relation a b -> m (Relation a b) forall a. a -> m a forall (m :: * -> *) a. Monad m => a -> m a return (Relation a b -> m (Relation a b)) -> Relation a b -> m (Relation a b) forall a b. (a -> b) -> a -> b $ ((a, b), (a, b)) -> [((a, b), Boolean)] -> Relation a b forall a b. (Ix a, Ix b) => ((a, b), (a, b)) -> [((a, b), Boolean)] -> Relation a b build ((a, b), (a, b)) bnd [((a, b), Boolean)] pairs symmetric_relation :: ((b, b), (b, b)) -> m (Relation b b) symmetric_relation ((b, b), (b, b)) bnd = do [[((b, b), Boolean)]] pairs <- [m [((b, b), Boolean)]] -> m [[((b, b), Boolean)]] forall (t :: * -> *) (m :: * -> *) a. (Traversable t, Monad m) => t (m a) -> m (t a) forall (m :: * -> *) a. Monad m => [m a] -> m [a] sequence ([m [((b, b), Boolean)]] -> m [[((b, b), Boolean)]]) -> [m [((b, b), Boolean)]] -> m [[((b, b), Boolean)]] forall a b. (a -> b) -> a -> b $ do (b p,b q) <- ((b, b), (b, b)) -> [(b, b)] forall a. Ix a => (a, a) -> [a] A.range ((b, b), (b, b)) bnd Bool -> [()] forall (f :: * -> *). Alternative f => Bool -> f () guard (Bool -> [()]) -> Bool -> [()] forall a b. (a -> b) -> a -> b $ b p b -> b -> Bool forall a. Ord a => a -> a -> Bool <= b q m [((b, b), Boolean)] -> [m [((b, b), Boolean)]] forall a. a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return (m [((b, b), Boolean)] -> [m [((b, b), Boolean)]]) -> m [((b, b), Boolean)] -> [m [((b, b), Boolean)]] forall a b. (a -> b) -> a -> b $ do Boolean x <- m Boolean forall (m :: * -> *). MonadSAT m => m Boolean boolean [((b, b), Boolean)] -> m [((b, b), Boolean)] forall a. a -> m a forall (m :: * -> *) a. Monad m => a -> m a return ([((b, b), Boolean)] -> m [((b, b), Boolean)]) -> [((b, b), Boolean)] -> m [((b, b), Boolean)] forall a b. (a -> b) -> a -> b $ [ ((b p,b q), Boolean x ) ] [((b, b), Boolean)] -> [((b, b), Boolean)] -> [((b, b), Boolean)] forall a. [a] -> [a] -> [a] ++ [ ((b q,b p), Boolean x) | b p b -> b -> Bool forall a. Eq a => a -> a -> Bool /= b q ] Relation b b -> m (Relation b b) forall a. a -> m a forall (m :: * -> *) a. Monad m => a -> m a return (Relation b b -> m (Relation b b)) -> Relation b b -> m (Relation b b) forall a b. (a -> b) -> a -> b $ ((b, b), (b, b)) -> [((b, b), Boolean)] -> Relation b b forall a b. (Ix a, Ix b) => ((a, b), (a, b)) -> [((a, b), Boolean)] -> Relation a b build ((b, b), (b, b)) bnd ([((b, b), Boolean)] -> Relation b b) -> [((b, b), Boolean)] -> Relation b b forall a b. (a -> b) -> a -> b $ [[((b, b), Boolean)]] -> [((b, b), Boolean)] forall (t :: * -> *) a. Foldable t => t [a] -> [a] concat [[((b, b), Boolean)]] pairs identity :: ( Ix a, MonadSAT m) => ((a,a),(a,a)) -> m ( Relation a a ) identity :: forall a (m :: * -> *). (Ix a, MonadSAT m) => ((a, a), (a, a)) -> m (Relation a a) identity ((a, a), (a, a)) bnd = do Boolean f <- Bool -> m Boolean forall (m :: * -> *). MonadSAT m => Bool -> m Boolean constant Bool False Boolean t <- Bool -> m Boolean forall (m :: * -> *). MonadSAT m => Bool -> m Boolean constant Bool True Relation a a -> m (Relation a a) forall a. a -> m a forall (m :: * -> *) a. Monad m => a -> m a return (Relation a a -> m (Relation a a)) -> Relation a a -> m (Relation a a) forall a b. (a -> b) -> a -> b $ ((a, a), (a, a)) -> [((a, a), Boolean)] -> Relation a a forall a b. (Ix a, Ix b) => ((a, b), (a, b)) -> [((a, b), Boolean)] -> Relation a b build ((a, a), (a, a)) bnd ([((a, a), Boolean)] -> Relation a a) -> [((a, a), Boolean)] -> Relation a a forall a b. (a -> b) -> a -> b $ [(a, a)] -> ((a, a) -> ((a, a), Boolean)) -> [((a, a), Boolean)] forall {a} {b}. [a] -> (a -> b) -> [b] for ( ((a, a), (a, a)) -> [(a, a)] forall a. Ix a => (a, a) -> [a] A.range ((a, a), (a, a)) bnd ) (((a, a) -> ((a, a), Boolean)) -> [((a, a), Boolean)]) -> ((a, a) -> ((a, a), Boolean)) -> [((a, a), Boolean)] forall a b. (a -> b) -> a -> b $ \ (a i,a j) -> ((a i,a j), if a i a -> a -> Bool forall a. Eq a => a -> a -> Bool == a j then Boolean t else Boolean f ) for :: [a] -> (a -> b) -> [b] for = ((a -> b) -> [a] -> [b]) -> [a] -> (a -> b) -> [b] forall a b c. (a -> b -> c) -> b -> a -> c flip (a -> b) -> [a] -> [b] forall a b. (a -> b) -> [a] -> [b] map build :: ( Ix a, Ix b ) => ((a,b),(a,b)) -> [ ((a,b), Boolean ) ] -> Relation a b build :: forall a b. (Ix a, Ix b) => ((a, b), (a, b)) -> [((a, b), Boolean)] -> Relation a b build ((a, b), (a, b)) bnd [((a, b), Boolean)] pairs = Array (a, b) Boolean -> Relation a b forall a b. Array (a, b) Boolean -> Relation a b Relation (Array (a, b) Boolean -> Relation a b) -> Array (a, b) Boolean -> Relation a b forall a b. (a -> b) -> a -> b $ ((a, b), (a, b)) -> [((a, b), Boolean)] -> Array (a, b) Boolean forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e A.array ((a, b), (a, b)) bnd [((a, b), Boolean)] pairs bounds :: (Ix a, Ix b) => Relation a b -> ((a,b),(a,b)) bounds :: forall a b. (Ix a, Ix b) => Relation a b -> ((a, b), (a, b)) bounds ( Relation Array (a, b) Boolean r ) = Array (a, b) Boolean -> ((a, b), (a, b)) forall i e. Array i e -> (i, i) A.bounds Array (a, b) Boolean r indices :: Relation a b -> [(a, b)] indices ( Relation Array (a, b) Boolean r ) = Array (a, b) Boolean -> [(a, b)] forall i e. Ix i => Array i e -> [i] A.indices Array (a, b) Boolean r assocs :: Relation a b -> [((a, b), Boolean)] assocs ( Relation Array (a, b) Boolean r ) = Array (a, b) Boolean -> [((a, b), Boolean)] forall i e. Ix i => Array i e -> [(i, e)] A.assocs Array (a, b) Boolean r elems :: Relation a b -> [Boolean] elems ( Relation Array (a, b) Boolean r ) = Array (a, b) Boolean -> [Boolean] forall i e. Array i e -> [e] A.elems Array (a, b) Boolean r Relation Array (a, b) Boolean r ! :: Relation a b -> (a, b) -> Boolean ! (a, b) p = Array (a, b) Boolean r Array (a, b) Boolean -> (a, b) -> Boolean forall i e. Ix i => Array i e -> i -> e A.! (a, b) p instance (Ix a, Ix b, Decode m Boolean Bool) => Decode m ( Relation a b ) ( Array (a,b) Bool ) where decode :: Relation a b -> m (Array (a, b) Bool) decode ( Relation Array (a, b) Boolean r ) = do Array (a, b) Boolean -> m (Array (a, b) Bool) forall (m :: * -> *) c a. Decode m c a => c -> m a decode Array (a, b) Boolean r table :: (Enum a, Ix a, Enum b, Ix b) => Array (a,b) Bool -> String table :: forall a b. (Enum a, Ix a, Enum b, Ix b) => Array (a, b) Bool -> String table Array (a, b) Bool r = [String] -> String unlines ([String] -> String) -> [String] -> String forall a b. (a -> b) -> a -> b $ do let ((a a,b b),(a c,b d)) = Array (a, b) Bool -> ((a, b), (a, b)) forall i e. Array i e -> (i, i) A.bounds Array (a, b) Bool r a x <- [ a a .. a c ] String -> [String] forall a. a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return (String -> [String]) -> String -> [String] forall a b. (a -> b) -> a -> b $ [String] -> String unwords ([String] -> String) -> [String] -> String forall a b. (a -> b) -> a -> b $ do b y <- [ b b .. b d ] String -> [String] forall a. a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return (String -> [String]) -> String -> [String] forall a b. (a -> b) -> a -> b $ if Array (a, b) Bool r Array (a, b) Bool -> (a, b) -> Bool forall i e. Ix i => Array i e -> i -> e A.! (a x,b y) then String "*" else String "."