我有这个定理(不确定是否是正确的词),我想获得所有的解决方案。
pairCube limit = do
m <- natural exists "m"
n <- natural exists "n"
a <- natural exists "a"
constrain $ m^3 .== n^2
constrain $ m .< limit
return $ m + n .== a^2
res <- allSat (pairCube 1000)
-- Run from ghci
extractModels res :: [[Integer]]
这试图解决问题:
有无限对整数(m,n),使得m ^ 3 = n ^ 2且m + n是一个理想平方。 m小于1000的那对是什么?
我只是通过蛮力就知道了实际的答案,但我想使用SBV。
但是,当我运行代码时,它仅提供以下值(格式为[m,n,a]):
[[9,27,6],[64,512,24],[]]
但是,不包括m值小于1000的其他几种解决方案。
最佳答案
给出完整的程序总是好的:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.SBV
pairCube :: SInteger -> Symbolic SBool
pairCube limit = do
(m :: SInteger) <- exists "m"
(n :: SInteger) <- exists "n"
(a :: SInteger) <- exists "a"
constrain $ m^(3::Integer) .== n^(2::Integer)
constrain $ m .< limit
return $ m + n .== a^(2::Integer)
main :: IO ()
main = print =<< allSat (pairCube 1000)
当我运行它时,我得到:
Main> main
Solution #1:
m = 0 :: Integer
n = 0 :: Integer
a = 0 :: Integer
Solution #2:
m = 9 :: Integer
n = 27 :: Integer
a = -6 :: Integer
Solution #3:
m = 1 :: Integer
n = -1 :: Integer
a = 0 :: Integer
Solution #4:
m = 9 :: Integer
n = 27 :: Integer
a = 6 :: Integer
Solution #5:
m = 64 :: Integer
n = 512 :: Integer
a = -24 :: Integer
Solution #6:
m = 64 :: Integer
n = 512 :: Integer
a = 24 :: Integer
Unknown
注意最后的
Unknown.
从本质上讲,SBV查询了Z3,并得到了6个解决方案。当SBV要求第七名时,Z3说:“我不知道是否还有其他解决方案。”使用非线性算术,此行为是预期的。
为了回答原始问题(即找到最大值
m
),我将约束更改为:constrain $ m .== limit
并结合以下“驱动程序”:
main :: IO ()
main = loop 1000
where loop (-1) = putStrLn "Can't find the largest m!"
loop m = do putStrLn $ "Trying: " ++ show m
mbModel <- extractModel `fmap` sat (pairCube m)
case mbModel of
Nothing -> loop (m-1)
Just r -> print (r :: (Integer, Integer, Integer))
在我的计算机上运行大约50分钟后,Z3产生了:
(576,13824,-120)
因此,很明显,基于
allSat
的方法导致Z3放弃的方式早于如果我们修复m
并进行自我迭代时可以实际实现的方式。对于非线性问题,对于通用SMT求解器来说,期望更快/更好的东西太多了。