{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Documentation.SBV.Examples.Puzzles.HexPuzzle where
import Data.SBV
import Data.SBV.Control
data Color = Black | Blue | Green | Red
mkSymbolicEnumeration ''Color
type Button = Word8
type SButton = SBV Button
type Grid = SArray Button Color
next :: SButton -> Grid -> Grid
next :: SButton -> Grid -> Grid
next SButton
b Grid
g = forall a. Mergeable a => SBool -> a -> a -> a
ite (forall (array :: * -> * -> *) a b.
SymArray array =>
array a b -> SBV a -> SBV b
readArray Grid
g SButton
b forall a. EqSymbolic a => a -> a -> SBool
.== SBV Color
sBlack) Grid
g
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite (SButton
b forall a. EqSymbolic a => a -> a -> SBool
.== SButton
5) ([Button] -> Grid
rot [ Button
1, Button
2, Button
6, Button
10, Button
9, Button
4])
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite (SButton
b forall a. EqSymbolic a => a -> a -> SBool
.== SButton
6) ([Button] -> Grid
rot [ Button
2, Button
3, Button
7, Button
11, Button
10, Button
5])
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite (SButton
b forall a. EqSymbolic a => a -> a -> SBool
.== SButton
9) ([Button] -> Grid
rot [ Button
4, Button
5, Button
10, Button
14, Button
13, Button
8])
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite (SButton
b forall a. EqSymbolic a => a -> a -> SBool
.== SButton
10) ([Button] -> Grid
rot [ Button
5, Button
6, Button
11, Button
15, Button
14, Button
9])
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite (SButton
b forall a. EqSymbolic a => a -> a -> SBool
.== SButton
11) ([Button] -> Grid
rot [ Button
6, Button
7, Button
12, Button
16, Button
15, Button
10])
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite (SButton
b forall a. EqSymbolic a => a -> a -> SBool
.== SButton
14) ([Button] -> Grid
rot [ Button
9, Button
10, Button
15, Button
18, Button
17, Button
13])
forall a b. (a -> b) -> a -> b
$ forall a. Mergeable a => SBool -> a -> a -> a
ite (SButton
b forall a. EqSymbolic a => a -> a -> SBool
.== SButton
15) ([Button] -> Grid
rot [Button
10, Button
11, Button
16, Button
19, Button
18, Button
14]) Grid
g
where rot :: [Button] -> Grid
rot [Button]
xs = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\(Button
i, SBV Color
c) Grid
a -> forall (array :: * -> * -> *) b a.
(SymArray array, SymVal b) =>
array a b -> SBV a -> SBV b -> array a b
writeArray Grid
a (forall a. SymVal a => a -> SBV a
literal Button
i) SBV Color
c) Grid
g (forall a b. [a] -> [b] -> [(a, b)]
zip [Button]
new [SBV Color]
cur)
where cur :: [SBV Color]
cur = forall a b. (a -> b) -> [a] -> [b]
map (forall (array :: * -> * -> *) a b.
SymArray array =>
array a b -> SBV a -> SBV b
readArray Grid
g forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. SymVal a => a -> SBV a
literal) [Button]
xs
new :: [Button]
new = forall a. [a] -> [a]
tail [Button]
xs forall a. [a] -> [a] -> [a]
++ [forall a. [a] -> a
head [Button]
xs]
search :: [Color] -> [Color] -> IO ()
search :: [Color] -> [Color] -> IO ()
search [Color]
initial [Color]
final = forall a. Symbolic a -> IO a
runSMT forall a b. (a -> b) -> a -> b
$ do Grid
emptyGrid :: Grid <- forall (array :: * -> * -> *) a b.
(SymArray array, HasKind a, HasKind b) =>
String -> Maybe (SBV b) -> Symbolic (array a b)
newArray String
"emptyGrid" (forall a. a -> Maybe a
Just SBV Color
sBlack)
let initGrid :: Grid
initGrid = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\(Button
i, Color
c) Grid
a -> forall (array :: * -> * -> *) b a.
(SymArray array, SymVal b) =>
array a b -> SBV a -> SBV b -> array a b
writeArray Grid
a (forall a. SymVal a => a -> SBV a
literal Button
i) (forall a. SymVal a => a -> SBV a
literal Color
c)) Grid
emptyGrid (forall a b. [a] -> [b] -> [(a, b)]
zip [Button
1..] [Color]
initial)
forall a. Query a -> Symbolic a
query forall a b. (a -> b) -> a -> b
$ forall {t}.
(Show t, Num t) =>
t -> Grid -> [SButton] -> QueryT IO ()
loop (Int
0 :: Int) Grid
initGrid []
where loop :: t -> Grid -> [SButton] -> QueryT IO ()
loop t
i Grid
g [SButton]
sofar = 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
"Searching at depth: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show t
i
Int -> QueryT IO ()
push Int
1
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall (array :: * -> * -> *) a b.
SymArray array =>
array a b -> SBV a -> SBV b
readArray Grid
g forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. SymVal a => a -> SBV a
literal) [Button
1..Button
19] forall a. EqSymbolic a => a -> a -> SBool
.== forall a b. (a -> b) -> [a] -> [b]
map forall a. SymVal a => a -> SBV a
literal [Color]
final
CheckSatResult
cs <- Query CheckSatResult
checkSat
case CheckSatResult
cs of
CheckSatResult
Unk -> forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"Solver said Unknown, depth: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show t
i
DSat{} -> forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"Solver returned a delta-satisfiable result, depth: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show t
i
CheckSatResult
Unsat -> do
Int -> QueryT IO ()
pop Int
1
SButton
b <- forall a. SymVal a => String -> Query (SBV a)
freshVar (String
"press_" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show t
i)
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain forall a b. (a -> b) -> a -> b
$ SButton
b forall a. EqSymbolic a => a -> [a] -> SBool
`sElem` forall a b. (a -> b) -> [a] -> [b]
map forall a. SymVal a => a -> SBV a
literal [Button
5, Button
6, Button
9, Button
10, Button
11, Button
14, Button
15]
t -> Grid -> [SButton] -> QueryT IO ()
loop (t
iforall a. Num a => a -> a -> a
+t
1) (SButton -> Grid -> Grid
next SButton
b Grid
g) ([SButton]
sofar forall a. [a] -> [a] -> [a]
++ [SButton
b])
CheckSatResult
Sat -> do [Button]
vs <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall a. SymVal a => SBV a -> Query a
getValue [SButton]
sofar
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
"Found: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show [Button]
vs
forall {b}. (SymVal b, Show b) => [SBV b] -> [b] -> QueryT IO ()
findOthers [SButton]
sofar [Button]
vs
findOthers :: [SBV b] -> [b] -> QueryT IO ()
findOthers [SBV b]
vs = [b] -> QueryT IO ()
go
where go :: [b] -> QueryT IO ()
go [b]
curVals = do forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain forall a b. (a -> b) -> a -> b
$ [SBool] -> SBool
sOr forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\SBV b
v b
c -> SBV b
v forall a. EqSymbolic a => a -> a -> SBool
./= forall a. SymVal a => a -> SBV a
literal b
c) [SBV b]
vs [b]
curVals
CheckSatResult
cs <- Query CheckSatResult
checkSat
case CheckSatResult
cs of
CheckSatResult
Unk -> forall a. HasCallStack => String -> a
error String
"Unknown!"
DSat{} -> forall a. HasCallStack => String -> a
error String
"Delta-sat!"
CheckSatResult
Unsat -> forall a. IO a -> Query a
io forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
"There are no more solutions."
CheckSatResult
Sat -> do [b]
newVals <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall a. SymVal a => SBV a -> Query a
getValue [SBV b]
vs
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
"Found: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show [b]
newVals
[b] -> QueryT IO ()
go [b]
newVals
example :: IO ()
example :: IO ()
example = [Color] -> [Color] -> IO ()
search [Color]
initBoard [Color]
finalBoard
where initBoard :: [Color]
initBoard = [Color
Black, Color
Black, Color
Black, Color
Red, Color
Blue, Color
Green, Color
Red, Color
Black, Color
Green, Color
Green, Color
Green, Color
Black, Color
Red, Color
Green, Color
Green, Color
Red, Color
Black, Color
Black, Color
Black]
finalBoard :: [Color]
finalBoard = [Color
Black, Color
Red, Color
Black, Color
Black, Color
Green, Color
Green, Color
Black, Color
Red, Color
Green, Color
Blue, Color
Green, Color
Red, Color
Black, Color
Green, Color
Green, Color
Black, Color
Black, Color
Red, Color
Black]