{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Documentation.SBV.Examples.Puzzles.Garden where
import Data.SBV
import Data.List(isSuffixOf)
data Color = Red | Yellow | Blue
mkSymbolicEnumeration ''Color
type Flower = SInteger
col :: Flower -> SBV Color
col :: Flower -> SBV Color
col = String -> Flower -> SBV Color
forall a. Uninterpreted a => String -> a
uninterpret String
"col"
validPick :: SInteger -> Flower -> Flower -> Flower -> SBool
validPick :: Flower -> Flower -> Flower -> Flower -> SBool
validPick Flower
n Flower
i Flower
j Flower
k = [Flower] -> SBool
forall a. EqSymbolic a => [a] -> SBool
distinct [Flower
i, Flower
j, Flower
k] SBool -> SBool -> SBool
.&& (Flower -> SBool) -> [Flower] -> SBool
forall a. (a -> SBool) -> [a] -> SBool
sAll Flower -> SBool
ok [Flower
i, Flower
j, Flower
k]
where ok :: Flower -> SBool
ok Flower
x = Flower -> (Flower, Flower) -> SBool
forall a. OrdSymbolic a => a -> (a, a) -> SBool
inRange Flower
x (Flower
1, Flower
n)
count :: Color -> [Flower] -> SInteger
count :: Color -> [Flower] -> Flower
count Color
c [Flower]
fs = [Flower] -> Flower
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [SBool -> Flower -> Flower -> Flower
forall a. Mergeable a => SBool -> a -> a -> a
ite (Flower -> SBV Color
col Flower
f SBV Color -> SBV Color -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== Color -> SBV Color
forall a. SymVal a => a -> SBV a
literal Color
c) Flower
1 Flower
0 | Flower
f <- [Flower]
fs]
puzzle :: Goal
puzzle :: Goal
puzzle = do Flower
n <- String -> Symbolic Flower
sInteger String
"N"
let valid :: Flower -> Flower -> Flower -> SBool
valid = Flower -> Flower -> Flower -> Flower -> SBool
validPick Flower
n
Flower
ef1 <- String -> Symbolic Flower
forall a. SymVal a => String -> Symbolic (SBV a)
sbvExists String
"ef1_modelIgnore"
Flower
ef2 <- String -> Symbolic Flower
forall a. SymVal a => String -> Symbolic (SBV a)
sbvExists String
"ef2_modelIgnore"
Flower
ef3 <- String -> Symbolic Flower
forall a. SymVal a => String -> Symbolic (SBV a)
sbvExists String
"ef3_modelIgnore"
Flower
af1 <- String -> Symbolic Flower
forall a. SymVal a => String -> Symbolic (SBV a)
sbvForall String
"af1"
Flower
af2 <- String -> Symbolic Flower
forall a. SymVal a => String -> Symbolic (SBV a)
sbvForall String
"af2"
Flower
af3 <- String -> Symbolic Flower
forall a. SymVal a => String -> Symbolic (SBV a)
sbvForall String
"af3"
SBool -> Goal
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain (SBool -> Goal) -> SBool -> Goal
forall a b. (a -> b) -> a -> b
$ Flower -> Flower -> Flower -> SBool
valid Flower
ef1 Flower
ef2 Flower
ef3
SBool -> Goal
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain (SBool -> Goal) -> SBool -> Goal
forall a b. (a -> b) -> a -> b
$ (Flower -> SBV Color) -> [Flower] -> [SBV Color]
forall a b. (a -> b) -> [a] -> [b]
map Flower -> SBV Color
col [Flower
ef1, Flower
ef2, Flower
ef3] [SBV Color] -> [SBV Color] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== [SBV Color
sRed, SBV Color
sYellow, SBV Color
sBlue]
SBool -> Goal
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain (SBool -> Goal) -> SBool -> Goal
forall a b. (a -> b) -> a -> b
$ Flower -> Flower -> Flower -> SBool
valid Flower
af1 Flower
af2 Flower
af3 SBool -> SBool -> SBool
.=> Color -> [Flower] -> Flower
count Color
Red [Flower
af1, Flower
af2, Flower
af3] Flower -> Flower -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= Flower
1
SBool -> Goal
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain (SBool -> Goal) -> SBool -> Goal
forall a b. (a -> b) -> a -> b
$ Flower -> Flower -> Flower -> SBool
valid Flower
af1 Flower
af2 Flower
af3 SBool -> SBool -> SBool
.=> Color -> [Flower] -> Flower
count Color
Yellow [Flower
af1, Flower
af2, Flower
af3] Flower -> Flower -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= Flower
1
SBool -> Goal
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain (SBool -> Goal) -> SBool -> Goal
forall a b. (a -> b) -> a -> b
$ Flower -> Flower -> Flower -> SBool
valid Flower
af1 Flower
af2 Flower
af3 SBool -> SBool -> SBool
.=> Color -> [Flower] -> Flower
count Color
Blue [Flower
af1, Flower
af2, Flower
af3] Flower -> Flower -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= Flower
1
flowerCount :: IO ()
flowerCount :: IO ()
flowerCount = AllSatResult -> IO ()
forall a. Show a => a -> IO ()
print (AllSatResult -> IO ()) -> IO AllSatResult -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< SMTConfig -> Goal -> IO AllSatResult
forall a. Provable a => SMTConfig -> a -> IO AllSatResult
allSatWith SMTConfig
z3{satTrackUFs :: Bool
satTrackUFs = Bool
False, isNonModelVar :: String -> Bool
isNonModelVar = (String
"_modelIgnore" String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf`)} Goal
puzzle