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