我正在尝试使用python中的z3实现问题的求解器(需要字符串操作)。 我尝试阅读documentation,但信息不足。我也尝试阅读z3str documentation,但找不到使示例工作的方法。
我想设置:
len(string) = 8
string[6] = 'a'
string_possible_characters = '3456789a'
string.count("6") = 2
在这种情况下,最好使用itertools(排列+组合)之类的东西吗?
答案 0 :(得分:1)
z3可以相对轻松地解决此类问题。关于API的使用,有一些学习上的曲线,但是值得投资。话虽如此,如果您的约束相对简单且字符串较短,则枚举它们并使用常规编程检查约束可以很快并且有效的替代方案。但是对于更长的字符串和更复杂的约束,z3将是解决此类问题的理想选择。
这是我用Python编写示例的方式:
# Bring z3 to scope
from z3 import *
# Grab a solver
s = Solver ()
# Create a symbolic string
string = String('string')
# len(string) = 8
s.add(Length(string) == 8)
# string[6] = 'a'
s.add(SubSeq(string, 6, 1) == StringVal('a'))
# string_possible_characters = '3456789a'
chars = Union([Re(StringVal(c)) for c in '345789a']) # Note I left 6 out on purpose!
six = Re(StringVal('6'))
# string.count("6") = 2
# Create a regular expression that matches exactly two occurences
# of 6's and any other allowed character in other positions
template = Concat(Star(chars), six, Star(chars), six, Star(chars))
# Assert our string matches the template
s.add(InRe(string, template))
# Get a model
res = s.check()
if res == sat:
print s.model()
else:
print "Solver said:",
print res
运行它,我得到:
[string = "634436a9"]
满足您的所有约束。您可以在此模板上构建模型来建模其他约束。 API的相关部分在这里:https://z3prover.github.io/api/html/z3py_8py_source.html#l10190
请注意,Python并不是唯一提供对Z3正则表达式和字符串的访问的API。几乎所有其他对z3的高级绑定都提供一定程度的支持,包括C / C ++ / Java / Haskell等。而且,根据这些绑定提供的抽象,这些约束甚至可能更易于编程。例如,这是使用SBV Haskell软件包编码的相同问题,该软件包使用z3作为基础求解器:
{-# LANGUAGE OverloadedStrings #-}
import Data.SBV
import qualified Data.SBV.String as S
import Data.SBV.RegExp
p :: IO SatResult
p = sat $ do s <- sString "string"
let others = KStar $ oneOf "345789a"
template = others * "6" * others * "6" * others
constrain $ S.length s .== 8
constrain $ S.strToCharAt s 6 .== literal 'a'
constrain $ s `match` template
运行时,此程序将产生:
*Main> p
Satisfiable. Model:
string = "649576a8" :: String
如您所见,Haskell编码相当简洁且易于阅读,而其他语言(例如C,Java等)的编码可能更冗长。当然,您应该选择一种最适合您的宿主语言,但是如果您有这样做的自由,我建议您使用Haskell绑定以便于使用。详细信息在这里:http://hackage.haskell.org/package/sbv