{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Documentation.SBV.Examples.Existentials.Diophantine where
import Data.List (intercalate, transpose)
import Data.SBV
import Data.Proxy
import GHC.TypeLits
data Solution = Homogeneous [[Integer]]
| NonHomogeneous [[Integer]] [[Integer]]
instance Show Solution where
show :: Solution -> String
show Solution
s = case Solution
s of
Homogeneous [[Integer]]
xss -> [String] -> [(Bool, [Integer])] -> String
forall {a}.
(Eq a, Num a, Show a) =>
[String] -> [(Bool, [a])] -> String
comb [String]
supplyH (([Integer] -> (Bool, [Integer]))
-> [[Integer]] -> [(Bool, [Integer])]
forall a b. (a -> b) -> [a] -> [b]
map (Bool
False,) [[Integer]]
xss)
NonHomogeneous [[Integer]]
css [[Integer]]
xss -> String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" [[String] -> [(Bool, [Integer])] -> String
forall {a}.
(Eq a, Num a, Show a) =>
[String] -> [(Bool, [a])] -> String
comb [String]
supplyNH ((Bool
True, [Integer]
cs) (Bool, [Integer]) -> [(Bool, [Integer])] -> [(Bool, [Integer])]
forall a. a -> [a] -> [a]
: ([Integer] -> (Bool, [Integer]))
-> [[Integer]] -> [(Bool, [Integer])]
forall a b. (a -> b) -> [a] -> [b]
map (Bool
False,) [[Integer]]
xss) | [Integer]
cs <- [[Integer]]
css]
where supplyH :: [String]
supplyH = [Char
'k' Char -> ShowS
forall a. a -> [a] -> [a]
: Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
i Char
'\'' | Int
i <- [Int
0 ..]]
supplyNH :: [String]
supplyNH = String
"" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
supplyH
comb :: [String] -> [(Bool, [a])] -> String
comb [String]
supply [(Bool, [a])]
xss = [String] -> String
vec ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ ([String] -> String) -> [[String]] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map [String] -> String
add ([[String]] -> [[String]]
forall a. [[a]] -> [[a]]
transpose ((String -> (Bool, [a]) -> [String])
-> [String] -> [(Bool, [a])] -> [[String]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith String -> (Bool, [a]) -> [String]
forall {a}.
(Eq a, Num a, Show a) =>
String -> (Bool, [a]) -> [String]
muls [String]
supply [(Bool, [a])]
xss))
where muls :: String -> (Bool, [a]) -> [String]
muls String
x (Bool
isConst, [a]
cs) = (a -> String) -> [a] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map a -> String
forall {a}. (Eq a, Num a, Show a) => a -> String
mul [a]
cs
where mul :: a -> String
mul a
0 = String
"0"
mul a
1 | Bool
isConst = String
"1"
| Bool
True = String
x
mul a
k | Bool
isConst = a -> String
forall a. Show a => a -> String
show a
k
| Bool
True = a -> String
forall a. Show a => a -> String
show a
k String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
x
add :: [String] -> String
add [] = String
"0"
add [String]
xs = (String -> ShowS) -> [String] -> String
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 String -> ShowS
plus [String]
xs
plus :: String -> ShowS
plus String
"0" String
y = String
y
plus String
x String
"0" = String
x
plus String
x String
y = String
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"+" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
y
vec :: [String] -> String
vec [String]
xs = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String]
xs String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
ldn :: forall proxy n. KnownNat n => proxy n -> Maybe Int -> [([Integer], Integer)] -> IO Solution
ldn :: forall (proxy :: Nat -> *) (n :: Nat).
KnownNat n =>
proxy n -> Maybe Int -> [([Integer], Integer)] -> IO Solution
ldn proxy n
pn Maybe Int
mbLim [([Integer], Integer)]
problem = do solution <- proxy n -> Maybe Int -> [[SInteger]] -> IO [[Integer]]
forall (proxy :: Nat -> *) (n :: Nat).
KnownNat n =>
proxy n -> Maybe Int -> [[SInteger]] -> IO [[Integer]]
basis proxy n
pn Maybe Int
mbLim (([Integer] -> [SInteger]) -> [[Integer]] -> [[SInteger]]
forall a b. (a -> b) -> [a] -> [b]
map ((Integer -> SInteger) -> [Integer] -> [SInteger]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> SInteger
forall a. SymVal a => a -> SBV a
literal) [[Integer]]
m)
if homogeneous
then return $ Homogeneous solution
else do let ones = [[Integer]
xs | (Integer
1:[Integer]
xs) <- [[Integer]]
solution]
zeros = [[Integer]
xs | (Integer
0:[Integer]
xs) <- [[Integer]]
solution]
return $ NonHomogeneous ones zeros
where rhs :: [Integer]
rhs = (([Integer], Integer) -> Integer)
-> [([Integer], Integer)] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map ([Integer], Integer) -> Integer
forall a b. (a, b) -> b
snd [([Integer], Integer)]
problem
lhs :: [[Integer]]
lhs = (([Integer], Integer) -> [Integer])
-> [([Integer], Integer)] -> [[Integer]]
forall a b. (a -> b) -> [a] -> [b]
map ([Integer], Integer) -> [Integer]
forall a b. (a, b) -> a
fst [([Integer], Integer)]
problem
homogeneous :: Bool
homogeneous = (Integer -> Bool) -> [Integer] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0) [Integer]
rhs
m :: [[Integer]]
m | Bool
homogeneous = [[Integer]]
lhs
| Bool
True = (Integer -> [Integer] -> [Integer])
-> [Integer] -> [[Integer]] -> [[Integer]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Integer
x [Integer]
y -> -Integer
x Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
: [Integer]
y) [Integer]
rhs [[Integer]]
lhs
basis :: forall proxy n. KnownNat n => proxy n -> Maybe Int -> [[SInteger]] -> IO [[Integer]]
basis :: forall (proxy :: Nat -> *) (n :: Nat).
KnownNat n =>
proxy n -> Maybe Int -> [[SInteger]] -> IO [[Integer]]
basis proxy n
_ Maybe Int
mbLim [[SInteger]]
m = AllSatResult -> [[Integer]]
forall a. SatModel a => AllSatResult -> [a]
extractModels (AllSatResult -> [[Integer]]) -> IO AllSatResult -> IO [[Integer]]
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` SMTConfig -> SymbolicT IO () -> IO AllSatResult
forall a. Satisfiable a => SMTConfig -> a -> IO AllSatResult
allSatWith SMTConfig
z3{allSatMaxModelCount = mbLim} SymbolicT IO ()
cond
where cond :: SymbolicT IO ()
cond = do as <- Int -> Symbolic [SInteger]
forall a. SymVal a => Int -> Symbolic [SBV a]
mkFreeVars Int
n
constrain $ \(ForallN [SInteger]
bs :: ForallN n nm Integer) ->
[SInteger] -> SBool
ok [SInteger]
as SBool -> SBool -> SBool
.&& ([SInteger] -> SBool
ok [SInteger]
bs SBool -> SBool -> SBool
.=> [SInteger]
as [SInteger] -> [SInteger] -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== [SInteger]
bs SBool -> SBool -> SBool
.|| SBool -> SBool
sNot ([SInteger]
bs [SInteger] -> [SInteger] -> SBool
forall {b}. OrdSymbolic b => [b] -> [b] -> SBool
`less` [SInteger]
as))
n :: Int
n = case [[SInteger]]
m of
[] -> Int
0
[SInteger]
f:[[SInteger]]
_ -> [SInteger] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SInteger]
f
ok :: [SInteger] -> SBool
ok [SInteger]
xs = (SInteger -> SBool) -> [SInteger] -> SBool
forall a. (a -> SBool) -> [a] -> SBool
sAny (SInteger -> SInteger -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.> SInteger
0) [SInteger]
xs SBool -> SBool -> SBool
.&& (SInteger -> SBool) -> [SInteger] -> SBool
forall a. (a -> SBool) -> [a] -> SBool
sAll (SInteger -> SInteger -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SInteger
0) [SInteger]
xs SBool -> SBool -> SBool
.&& [SBool] -> SBool
sAnd [[SInteger] -> SInteger
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((SInteger -> SInteger -> SInteger)
-> [SInteger] -> [SInteger] -> [SInteger]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith SInteger -> SInteger -> SInteger
forall a. Num a => a -> a -> a
(*) [SInteger]
r [SInteger]
xs) SInteger -> SInteger -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SInteger
0 | [SInteger]
r <- [[SInteger]]
m]
[b]
as less :: [b] -> [b] -> SBool
`less` [b]
bs = [SBool] -> SBool
sAnd ((b -> b -> SBool) -> [b] -> [b] -> [SBool]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith b -> b -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
(.<=) [b]
as [b]
bs) SBool -> SBool -> SBool
.&& [SBool] -> SBool
sOr ((b -> b -> SBool) -> [b] -> [b] -> [SBool]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith b -> b -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
(.<) [b]
as [b]
bs)
test :: IO Solution
test :: IO Solution
test = Proxy 4 -> Maybe Int -> [([Integer], Integer)] -> IO Solution
forall (proxy :: Nat -> *) (n :: Nat).
KnownNat n =>
proxy n -> Maybe Int -> [([Integer], Integer)] -> IO Solution
ldn (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @4) Maybe Int
forall a. Maybe a
Nothing [([Integer
2,Integer
1,-Integer
1], Integer
2)]
sailors :: IO [Integer]
sailors :: IO [Integer]
sailors = Int -> IO [Integer]
search Int
1
where search :: Int -> IO [Integer]
search Int
i = do soln <- Proxy 8 -> Maybe Int -> [([Integer], Integer)] -> IO Solution
forall (proxy :: Nat -> *) (n :: Nat).
KnownNat n =>
proxy n -> Maybe Int -> [([Integer], Integer)] -> IO Solution
ldn (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @8)
(Int -> Maybe Int
forall a. a -> Maybe a
Just Int
i)
[ ([Integer
1, -Integer
5, Integer
0, Integer
0, Integer
0, Integer
0, Integer
0], Integer
1)
, ([Integer
0, Integer
4, -Integer
5 , Integer
0, Integer
0, Integer
0, Integer
0], Integer
1)
, ([Integer
0, Integer
0, Integer
4, -Integer
5 , Integer
0, Integer
0, Integer
0], Integer
1)
, ([Integer
0, Integer
0, Integer
0, Integer
4, -Integer
5, Integer
0, Integer
0], Integer
1)
, ([Integer
0, Integer
0, Integer
0, Integer
0, Integer
4, -Integer
5, Integer
0], Integer
1)
, ([Integer
0, Integer
0, Integer
0, Integer
0, Integer
0, Integer
4, -Integer
5], Integer
1)
]
case soln of
NonHomogeneous ([Integer]
xs:[[Integer]]
_) [[Integer]]
_ -> [Integer] -> IO [Integer]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [Integer]
xs
Solution
_ -> Int -> IO [Integer]
search (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)