3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 10:25:18 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2016-01-02 23:31:36 -08:00
parent 1147037a99
commit b5969326bc
3 changed files with 107 additions and 27 deletions

View file

@ -8959,11 +8959,8 @@ class SeqRef(ExprRef):
def sort(self):
return SeqSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx)
def __add__(self, other):
v = (Ast * 2)()
v[0] = self.as_ast()
v[1] = other.as_ast()
return SeqRef(Z3_mk_seq_concat(self.ctx_ref(), 2, v), self.ctx)
def __add__(self, other):
return Concat(self, other)
def __getitem__(self, i):
return SeqRef(Z3_mk_seq_at(self.ctx_ref(), self.as_ast(), i.as_ast()), self.ctx)
@ -8985,23 +8982,36 @@ def _coerce_seq(s, ctx=None):
s = String(s, ctx)
return s
def _get_ctx2(a, b):
def _get_ctx2(a, b, ctx=None):
if is_expr(a):
return a.ctx
if is_expr(b):
return b.ctx
return None
return ctx
def is_seq(a):
"""Return `True` if `a` is a Z3 sequence expression."""
"""Return `True` if `a` is a Z3 sequence expression.
>>> print (is_seq(Unit(IntVal(0))))
True
>>> print (is_seq(String("abc")))
True
"""
return isinstance(a, SeqRef)
def is_string_sort(a):
"""Return `True` if `a` is a Z3 string expression."""
"""Return `True` if `a` is a Z3 string expression.
>>> print (is_string_sort(String("ab")))
True
"""
return isinstance(a, SeqRef) and a.is_string_sort()
def is_string_value(a):
"""return 'True' if 'a' is a Z3 string constant expression."""
"""return 'True' if 'a' is a Z3 string constant expression.
>>> print (is_string_value(String("a")))
True
>>> print (is_string_value(String("a") + String("b")))
False
"""
return isinstance(a, SeqRef) and a.is_string_value()
def String(s, ctx=None):
@ -9028,21 +9038,42 @@ def Unit(a):
return SeqRef(Z3_mk_seq_unit(a.ctx_ref(), a.as_ast()), a.ctx)
def PrefixOf(a, b):
"""Check if 'a' is a prefix of 'b'"""
"""Check if 'a' is a prefix of 'b'
>>> s1 = PrefixOf("ab", "abc")
>>> print (simplify(s1))
True
>>> s2 = PrefixOf("bc", "abc")
>>> print (simplify(s2))
False
"""
ctx = _get_ctx2(a, b)
a = _coerce_seq(a, ctx)
b = _coerce_seq(b, ctx)
return BoolRef(Z3_mk_seq_prefix(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
def SuffixOf(a, b):
"""Check if 'a' is a suffix of 'b'"""
"""Check if 'a' is a suffix of 'b'
>>> s1 = SuffixOf("ab", "abc")
>>> print (simplify(s1))
False
>>> s2 = SuffixOf("bc", "abc")
>>> print (simplify(s2))
True
"""
ctx = _get_ctx2(a, b)
a = _coerce_seq(a, ctx)
b = _coerce_seq(b, ctx)
return BoolRef(Z3_mk_seq_suffix(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx)
def Contains(a, b):
"""Check if 'a' contains 'b'"""
"""Check if 'a' contains 'b'
>>> s1 = Contains("abc", "ab")
>>> print (simplify(s1))
True
>>> s2 = SuffixOf("abc", "bc")
>>> print (simplify(s2))
True
"""
ctx = _get_ctx2(a, b)
a = _coerce_seq(a, ctx)
b = _coerce_seq(b, ctx)
@ -9052,20 +9083,34 @@ def Contains(a, b):
# """Extract a sequence at offset with indicated length"""
# return SeqRef(Z3_mk_seq_extract(a.ctx_ref(), a.as_ast(), offset.as_ast()), length.ctx)
def Replace(src, dst, s):
"""Replace the first occurrence of 'src' by 'dst' in 's'"""
ctx = _get_ctx2(src, _get_ctx2(dst, s))
def Replace(s, src, dst):
"""Replace the first occurrence of 'src' by 'dst' in 's'
>>> r = Replace("aaa", "a", "b")
>>> print (simplify(r))
"baa"
"""
ctx = _get_ctx2(dst, s)
if ctx is None and is_expr(src):
ctx = src.ctx
src = _coerce_seq(src, ctx)
dst = _coerce_seq(dst, ctx)
s = _coerce_seq(s, ctx)
return SeqRef(Z3_mk_seq_replace(src.ctx_ref(), src.as_ast(), dst.as_ast()), s.ctx)
return SeqRef(Z3_mk_seq_replace(src.ctx_ref(), s.as_ast(), src.as_ast(), dst.as_ast()), s.ctx)
def Length(s):
"""Obtain the length of a sequence 's'"""
return ArithRef(Z3_mk_seq_length(s.ctx_ref(), s.as_ast(), s.ctx))
"""Obtain the length of a sequence 's'
>>> l = Length(String("abc"))
>>> print (simplify(l))
3
"""
return ArithRef(Z3_mk_seq_length(s.ctx_ref(), s.as_ast()), s.ctx)
def Re(s, ctx=None):
"""The regular expression that accepts sequence 's'"""
"""The regular expression that accepts sequence 's'
>>> s1 = Re("ab")
>>> s2 = Re(String("ab"))
>>> s3 = Re(Unit(BoolVal(True)))
"""
s = _coerce_seq(s, ctx)
return ReRef(Z3_mk_seq_to_re(s.ctx_ref(), s.as_ast()), s.ctx)
@ -9090,20 +9135,45 @@ def ReSort(s):
class ReRef(ExprRef):
"""Regular expressions."""
def __add__(self, other):
v = (Ast * 2)()
v[0] = self.as_ast()
v[1] = other.as_ast()
return SeqRef(Z3_mk_re_union(self.ctx_ref(), 2, v), self.ctx)
def __add__(self, other):
return Union(self, other)
def is_re(s):
return isinstance(s, ReRef)
def InRe(s, re):
"""Create regular expression membership test
>>> re = Union(Re("a"),Re("b"))
>>> print (simplify(InRe("a", re)))
True
>>> print (simplify(InRe("b", re)))
True
>>> print (simplify(InRe("c", re)))
False
"""
s = _coerce_seq(s, re.ctx)
return BoolRef(Z3_mk_seq_in_re(s.ctx_ref(), s.as_ast(), re.as_ast()), s.ctx)
def Union(*args):
"""Create union of regular expressions.
>>> re = Union(Re("a"), Re("b"), Re("c"))
>>> print (simplify(InRe("d", re)))
False
"""
args = _get_args(args)
sz = len(args)
if __debug__:
_z3_assert(sz >= 2, "At least two arguments expected.")
_z3_assert(all([is_re(a) for a in args]), "All arguments must be regular expressions.")
ctx = args[0].ctx
v = (Ast * sz)()
for i in range(sz):
v[i] = args[i].as_ast()
return ReRef(Z3_mk_re_union(ctx.ref(), sz, v), ctx)
def Plus(re):
"""Create the regular expression accepting one or more repetitions of argument.
>>> re = Plus(Re("a"))
@ -9117,6 +9187,15 @@ def Plus(re):
return ReRef(Z3_mk_re_plus(re.ctx_ref(), re.as_ast()), re.ctx)
def Option(re):
"""Create the regular expression that optionally accepts the argument.
>>> re = Option(Re("a"))
>>> print(simplify(InRe("a", re)))
True
>>> print(simplify(InRe("", re)))
True
>>> print(simplify(InRe("aa", re)))
False
"""
return ReRef(Z3_mk_re_option(re.ctx_ref(), re.as_ast()), re.ctx)
def Star(re):

View file

@ -3251,7 +3251,7 @@ extern "C" {
def_API('Z3_mk_seq_replace' ,AST ,(_in(CONTEXT), _in(AST), _in(AST), _in(AST)))
*/
Z3_ast Z3_API Z3_mk_seq_replace(Z3_context c, Z3_ast src, Z3_ast dst, Z3_ast s);
Z3_ast Z3_API Z3_mk_seq_replace(Z3_context c, Z3_ast s, Z3_ast src, Z3_ast dst);
/**
\brief Retrieve from \s the unit sequence positioned at position \c index.

View file

@ -822,7 +822,8 @@ br_status seq_rewriter::mk_re_plus(expr* a, expr_ref& result) {
br_status seq_rewriter::mk_re_opt(expr* a, expr_ref& result) {
sort* s;
VERIFY(m_util.is_re(a, s));
result = m_util.re.mk_union(m_util.re.mk_to_re(m_util.str.mk_empty(s)), a);
sort_ref seq(m_util.str.mk_seq(s), m());
result = m_util.re.mk_union(m_util.re.mk_to_re(m_util.str.mk_empty(seq)), a);
return BR_REWRITE1;
}