logict-state-0.1.0.0: src/Control/Monad/LogicState/Examples.hs
{-# LANGUAGE FlexibleInstances, UndecidableInstances, ExistentialQuantification, RankNTypes, ScopedTypeVariables #-}
module Control.Monad.LogicState.Examples
( main
)
where
import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.State.Strict as StStr
-- import qualified Control.Monad.State.Strict as StStr
import qualified Control.Monad.State.Lazy as StLaz
import Control.Monad.LogicState.Logic
import Control.Monad.LogicState
odds :: MonadPlus m => m Int
odds = (return 1) `mplus` (odds >>= \a -> return (2 + a))
{-
-------------------------------------------------------------------------------------------------
-- Basic queens
queens1 :: Int -> [[Int]]
queens1 n = filter test (generate n)
where generate 0 = [[]]
generate k = [q : qs | q <- [1..n], qs <- generate (k-1)]
test [] = True
test (q:qs) = isSafe q qs && test qs
isSafe try qs = not (try `elem` qs || sameDiag try qs)
sameDiag try qs = any (\(colDist,q) -> abs (try - q) == colDist) $ zip [1..] qs
-------------------------------------------------------------------------------------------------
-- Basic queens, optimized with pruning
queens2 :: Int -> [[Int]]
queens2 n = map reverse $ queens' n
where queens' 0 = [[]]
queens' k = [q:qs | qs <- queens' (k-1), q <- [1..n], isSafe q qs]
isSafe try qs = not (try `elem` qs || sameDiag try qs)
sameDiag try qs = any (\(colDist,q) -> abs (try - q) == colDist) $ zip [1..] qs
-------------------------------------------------------------------------------------------------
-- Logic queens
queens1L n = do
q <- generate1 n n
guard (test q)
return q
where
test [] = True
test (q:qs) = isSafe q qs && test qs
isSafe try qs = not (try `elem` qs || sameDiag try qs)
sameDiag try qs = any (\(colDist,q) -> abs (try - q) == colDist) $ zip [1..] qs
generate1 :: MonadPlus m => Int -> Int -> m [Int]
generate1 _ 0 = return []
generate1 n k = do
qs <- generate1 n (k-1)
msum $ map (return . (:qs)) [1..n]
-------------------------------------------------------------------------------------------------
-- Logic queens, with pruning
queens2L n = do
q <- generate2 n n
return q
generate2 :: MonadPlus m => Int -> Int -> m [Int]
generate2 _ 0 = return []
generate2 n k = do
qs <- generate2 n (k-1)
msum $ flip map [1..n] $ \i -> do
let q = i : qs
guard (test q)
return q
where
test [] = True
test (q:qs) = isSafe q qs && test qs
isSafe try qs = not (try `elem` qs || sameDiag try qs)
sameDiag try qs = any (\(colDist,q) -> abs (try - q) == colDist) $ zip [1..] qs
-}
-------------------------------------------------------------------------------------------------
-- Logic queens, with pruning, with state
queens3L n = do
q <- generate3 n n
return q
count3g :: Monad m => LogicStateT Int Int m Int
count3g = state (\(g::Int, b::Int) -> (g,(g+1,b)))
count3gb :: Monad m => LogicStateT Int Int m (Int,Int)
count3gb = state (\(g::Int, b::Int) -> ((g,b),(g+1,b+1)))
generate3 :: Monad m => Int -> Int -> LogicStateT Int Int m ((Int,Int),[Int])
generate3 _ 0 = count3gb >>= \c -> return (c,[])
generate3 n k = do
(_,qs) <- generate3 n (k-1)
qss <- forM [1..n] $ \i -> backtrack $ do
let q = i : qs
guard (test q)
cnt <- count3gb
return (cnt,q)
foldr1 mplus qss
{-
foldr1 mplus $ flip map [1..n] $ \i -> do
let q = i : qs
guard (test q)
cnt <- count3gb
return (cnt,q)
-}
where
test [] = True
test (q:qs) = isSafe q qs && test qs
isSafe try qs = not (try `elem` qs || sameDiag try qs)
sameDiag try qs = any (\(colDist,q) -> abs (try - q) == colDist) $ zip [1..] qs
main = do
-- forM_ (queens1 8) print
-- forM_ (queens2 8) print
-- forM_ (observeAll () $ queens1L 8) print
-- forM_ (observeAll () $ (queens2L 8 :: Logic [Int])) print
-- forM_ (observeAll (0::Int,0::Int) $ (queens3L 8 :: LogicVar Int Int ((Int,Int),[Int]))) print
forM_ (observeMany (0::Int,0::Int) 500 $ (queens3L 10 :: LogicState Int Int ((Int,Int),[Int]))) print
-- forM_ (observe (0::Int,0::Int) $ (queens3L 8 :: LogicVar Int Int ((Int,Int),[Int]))) print