{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Documentation.SBV.Examples.Puzzles.Garden where
import Data.SBV
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. SMTDefinable 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 a. Num a => [a] -> a
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 :: ConstraintSet
puzzle :: ConstraintSet
puzzle = do n <- String -> Symbolic Flower
sInteger String
"N"
let valid = Flower -> Flower -> Flower -> Flower -> SBool
validPick Flower
n
constrain $ \(Exists Flower
ef1) (Exists Flower
ef2) (Exists Flower
ef3) ->
Flower -> Flower -> Flower -> SBool
valid Flower
ef1 Flower
ef2 Flower
ef3 SBool -> SBool -> SBool
.&& (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]
constrain $ \(Forall Flower
af1) (Forall Flower
af2) (Forall Flower
af3) ->
let atLeastOne :: Color -> SBool
atLeastOne Color
c = Color -> [Flower] -> Flower
count Color
c [Flower
af1, Flower
af2, Flower
af3] Flower -> Flower -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= Flower
1
in Flower -> Flower -> Flower -> SBool
valid Flower
af1 Flower
af2 Flower
af3 SBool -> SBool -> SBool
.=> Color -> SBool
atLeastOne Color
Red SBool -> SBool -> SBool
.&& Color -> SBool
atLeastOne Color
Yellow SBool -> SBool -> SBool
.&& Color -> SBool
atLeastOne Color
Blue
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 -> ConstraintSet -> IO AllSatResult
forall a. Satisfiable a => SMTConfig -> a -> IO AllSatResult
allSatWith SMTConfig
z3{allSatTrackUFs=False} ConstraintSet
puzzle