{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Documentation.SBV.Examples.Puzzles.Jugs where
import Data.SBV
import Data.SBV.Control
import GHC.Generics(Generic)
data Jug = Jug { Jug -> Integer
capacity :: Integer
, Jug -> SInteger
content :: SInteger
} deriving (forall x. Rep Jug x -> Jug
forall x. Jug -> Rep Jug x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Jug x -> Jug
$cfrom :: forall x. Jug -> Rep Jug x
Generic, Bool -> SBool -> Jug -> Jug -> Jug
forall b. (Ord b, SymVal b, Num b) => [Jug] -> Jug -> SBV b -> Jug
forall a.
(Bool -> SBool -> a -> a -> a)
-> (forall b. (Ord b, SymVal b, Num b) => [a] -> a -> SBV b -> a)
-> Mergeable a
select :: forall b. (Ord b, SymVal b, Num b) => [Jug] -> Jug -> SBV b -> Jug
$cselect :: forall b. (Ord b, SymVal b, Num b) => [Jug] -> Jug -> SBV b -> Jug
symbolicMerge :: Bool -> SBool -> Jug -> Jug -> Jug
$csymbolicMerge :: Bool -> SBool -> Jug -> Jug -> Jug
Mergeable)
transfer :: Jug -> Jug -> (Jug, Jug)
transfer :: Jug -> Jug -> (Jug, Jug)
transfer Jug
j1 Jug
j2 = (Jug
j1', Jug
j2')
where empty :: SInteger
empty = forall a. SymVal a => a -> SBV a
literal (Jug -> Integer
capacity Jug
j2) forall a. Num a => a -> a -> a
- Jug -> SInteger
content Jug
j2
transferrable :: SInteger
transferrable = SInteger
empty forall a. OrdSymbolic a => a -> a -> a
`smin` Jug -> SInteger
content Jug
j1
j1' :: Jug
j1' = Jug
j1 { content :: SInteger
content = Jug -> SInteger
content Jug
j1 forall a. Num a => a -> a -> a
- SInteger
transferrable }
j2' :: Jug
j2' = Jug
j2 { content :: SInteger
content = Jug -> SInteger
content Jug
j2 forall a. Num a => a -> a -> a
+ SInteger
transferrable }
initJugs :: (Jug, Jug, Jug)
initJugs :: (Jug, Jug, Jug)
initJugs = (Jug
j1, Jug
j2, Jug
j3)
where j1 :: Jug
j1 = Integer -> SInteger -> Jug
Jug Integer
8 SInteger
8
j2 :: Jug
j2 = Integer -> SInteger -> Jug
Jug Integer
5 SInteger
0
j3 :: Jug
j3 = Integer -> SInteger -> Jug
Jug Integer
3 SInteger
0
solved :: (Jug, Jug, Jug) -> SBool
solved :: (Jug, Jug, Jug) -> SBool
solved (Jug
j1, Jug
j2, Jug
j3) = Jug -> SInteger
content Jug
j1 forall a. EqSymbolic a => a -> a -> SBool
.== SInteger
4 SBool -> SBool -> SBool
.&& Jug -> SInteger
content Jug
j2 forall a. EqSymbolic a => a -> a -> SBool
.== SInteger
4 SBool -> SBool -> SBool
.&& Jug -> SInteger
content Jug
j3 forall a. EqSymbolic a => a -> a -> SBool
.== SInteger
0
moves :: [(SInteger, SInteger)] -> (Jug, Jug, Jug)
moves :: [(SInteger, SInteger)] -> (Jug, Jug, Jug)
moves = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (Jug, Jug, Jug) -> (SInteger, SInteger) -> (Jug, Jug, Jug)
move (Jug, Jug, Jug)
initJugs
where move :: (Jug, Jug, Jug) -> (SInteger, SInteger) -> (Jug, Jug, Jug)
move :: (Jug, Jug, Jug) -> (SInteger, SInteger) -> (Jug, Jug, Jug)
move (Jug
j0, Jug
j1, Jug
j2) (SInteger
from, SInteger
to) =
forall a. Mergeable a => SBool -> a -> a -> a
ite ((SInteger
from, SInteger
to) forall a. EqSymbolic a => a -> a -> SBool
.== (SInteger
1, SInteger
2)) (let (Jug
j0', Jug
j1') = Jug -> Jug -> (Jug, Jug)
transfer Jug
j0 Jug
j1 in (Jug
j0', Jug
j1', Jug
j2))
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite ((SInteger
from, SInteger
to) forall a. EqSymbolic a => a -> a -> SBool
.== (SInteger
2, SInteger
1)) (let (Jug
j1', Jug
j0') = Jug -> Jug -> (Jug, Jug)
transfer Jug
j1 Jug
j0 in (Jug
j0', Jug
j1', Jug
j2))
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite ((SInteger
from, SInteger
to) forall a. EqSymbolic a => a -> a -> SBool
.== (SInteger
1, SInteger
3)) (let (Jug
j0', Jug
j2') = Jug -> Jug -> (Jug, Jug)
transfer Jug
j0 Jug
j2 in (Jug
j0', Jug
j1, Jug
j2'))
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite ((SInteger
from, SInteger
to) forall a. EqSymbolic a => a -> a -> SBool
.== (SInteger
3, SInteger
1)) (let (Jug
j2', Jug
j0') = Jug -> Jug -> (Jug, Jug)
transfer Jug
j2 Jug
j0 in (Jug
j0', Jug
j1, Jug
j2'))
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite ((SInteger
from, SInteger
to) forall a. EqSymbolic a => a -> a -> SBool
.== (SInteger
2, SInteger
3)) (let (Jug
j1', Jug
j2') = Jug -> Jug -> (Jug, Jug)
transfer Jug
j1 Jug
j2 in (Jug
j0, Jug
j1', Jug
j2'))
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite ((SInteger
from, SInteger
to) forall a. EqSymbolic a => a -> a -> SBool
.== (SInteger
3, SInteger
2)) (let (Jug
j2', Jug
j1') = Jug -> Jug -> (Jug, Jug)
transfer Jug
j2 Jug
j1 in (Jug
j0, Jug
j1', Jug
j2'))
(Jug
j0, Jug
j1, Jug
j2)
puzzle :: IO ()
puzzle :: IO ()
puzzle = forall a. Symbolic a -> IO a
runSMT forall a b. (a -> b) -> a -> b
$ do
let run :: Int -> QueryT IO ()
run Int
i = do forall a. IO a -> Query a
io forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn forall a b. (a -> b) -> a -> b
$ String
"# of moves: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (Int
i :: Int)
Int -> QueryT IO ()
push Int
1
[(SInteger, SInteger)]
ms <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall a b. a -> b -> a
const QueryT IO (SInteger, SInteger)
genMove) [Int
1..Int
i]
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain forall a b. (a -> b) -> a -> b
$ (Jug, Jug, Jug) -> SBool
solved forall a b. (a -> b) -> a -> b
$ [(SInteger, SInteger)] -> (Jug, Jug, Jug)
moves [(SInteger, SInteger)]
ms
CheckSatResult
cs <- Query CheckSatResult
checkSat
case CheckSatResult
cs of
CheckSatResult
Unsat -> do Int -> QueryT IO ()
pop Int
1
Int -> QueryT IO ()
run (Int
iforall a. Num a => a -> a -> a
+Int
1)
CheckSatResult
Sat -> forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ forall {a} {a}.
(SymVal a, SymVal a, Show a, Show a) =>
(SBV a, SBV a) -> QueryT IO ()
sh [(SInteger, SInteger)]
ms
CheckSatResult
_ -> forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"Unexpected result: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show CheckSatResult
cs
forall a. Query a -> Symbolic a
query forall a b. (a -> b) -> a -> b
$ Int -> QueryT IO ()
run Int
0
where genMove :: QueryT IO (SInteger, SInteger)
genMove = (,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. SymVal a => Query (SBV a)
freshVar_ forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. SymVal a => Query (SBV a)
freshVar_
sh :: (SBV a, SBV a) -> QueryT IO ()
sh (SBV a
f, SBV a
t) = do a
from <- forall a. SymVal a => SBV a -> Query a
getValue SBV a
f
a
to <- forall a. SymVal a => SBV a -> Query a
getValue SBV a
t
forall a. IO a -> Query a
io forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show a
from forall a. [a] -> [a] -> [a]
++ String
" --> " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
to