mirror of
https://github.com/Z3Prover/z3
synced 2025-04-28 03:15:50 +00:00
updates to seq and bug fixes (#4056)
* na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix #4037 * nicer output for skolem functions * more overhaul of seq, some bug fixes * na * added offset_eq file * na * fix #4044 * fix #4040 * fix #4045 * updated ignore * new rewrites for indexof based on #4036 * add shortcuts * updated ne solver for seq, fix #4025 * use pair vectors for equalities that are reduced by seq_rewriter * use erase_and_swap * remove unit-walk * na * add check for #3200 * nits Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * name a type Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove fp check Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove unsound axiom instantiation for non-contains Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix rewrites Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix #4053 Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix #4052 Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
53c14bd554
commit
95a78b2450
39 changed files with 1516 additions and 1654 deletions
133
src/smt/seq_offset_eq.cpp
Normal file
133
src/smt/seq_offset_eq.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
seq_offset_eq.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Container for maintaining equalities between lengths of sequences.
|
||||
|
||||
Author:
|
||||
|
||||
Thai Minh Trinh 2017
|
||||
Nikolaj Bjorner (nbjorner) 2020-4-16
|
||||
|
||||
--*/
|
||||
|
||||
#include "ast/ast_pp.h"
|
||||
#include "smt/seq_offset_eq.h"
|
||||
#include "smt/smt_context.h"
|
||||
|
||||
using namespace smt;
|
||||
|
||||
/**
|
||||
Match:
|
||||
e == val where val is an integer
|
||||
e == r1 - r2
|
||||
r1 == len(e1)
|
||||
r2 == len(e2)
|
||||
update m_offset_equalities to contain.
|
||||
r1 |-> [r2 |-> val]
|
||||
*/
|
||||
|
||||
seq_offset_eq::seq_offset_eq(theory& th, ast_manager& m):
|
||||
th(th), m(m), seq(m), a(m), m_propagation_level(-1) {
|
||||
}
|
||||
|
||||
bool seq_offset_eq::match_x_minus_y(expr* e, expr*& x, expr*& y) const {
|
||||
expr* z = nullptr, *u = nullptr;
|
||||
rational fact;
|
||||
return
|
||||
a.is_add(e, x, z) &&
|
||||
a.is_mul(z, u, y) &&
|
||||
a.is_numeral(u, fact) &&
|
||||
fact.is_minus_one();
|
||||
}
|
||||
|
||||
|
||||
void seq_offset_eq::len_offset(expr* e, int val) {
|
||||
context & ctx = th.get_context();
|
||||
expr *x = nullptr, *y = nullptr;
|
||||
expr *e1 = nullptr, *e2 = nullptr;
|
||||
if (match_x_minus_y(e, x, y) &&
|
||||
ctx.e_internalized(x) &&
|
||||
ctx.e_internalized(y)) {
|
||||
TRACE("seq", tout << "eqc: " << mk_pp(e, m) << "\n";);
|
||||
enode* r1 = th.get_root(x);
|
||||
enode* r2 = th.get_root(y);
|
||||
for (enode* n1 : *r1) {
|
||||
if (!seq.str.is_length(n1->get_owner(), e1))
|
||||
continue;
|
||||
for (enode* n2 : *r2) {
|
||||
if (!seq.str.is_length(n2->get_owner(), e2))
|
||||
continue;
|
||||
if (r1->get_owner_id() > r2->get_owner_id()) {
|
||||
std::swap(r1, r2);
|
||||
val = -val;
|
||||
}
|
||||
m_offset_equalities.insert(r1, r2, val);
|
||||
m_has_offset_equality.insert(r1);
|
||||
m_has_offset_equality.insert(r2);
|
||||
TRACE("seq", tout << "a length pair: " << mk_pp(e1, m) << ", " << mk_pp(e2, m) << "\n";);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find the length offset from the congruence closure core
|
||||
void seq_offset_eq::prop_arith_to_len_offset() {
|
||||
rational val;
|
||||
for (enode* n : th.get_context().enodes()) {
|
||||
if (a.is_numeral(n->get_owner(), val) && val.is_int32() && INT_MIN < val.get_int32()) {
|
||||
TRACE("seq", tout << "offset: " << mk_pp(n->get_owner(), m) << "\n";);
|
||||
enode *next = n->get_next();
|
||||
while (next != n) {
|
||||
len_offset(next->get_owner(), val.get_int32());
|
||||
next = next->get_next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool seq_offset_eq::find(enode* n1, enode* n2, int& offset) const {
|
||||
n1 = n1->get_root();
|
||||
n2 = n2->get_root();
|
||||
if (n1->get_owner_id() > n2->get_owner_id())
|
||||
std::swap(n1, n2);
|
||||
return
|
||||
!a.is_numeral(n2->get_owner()) &&
|
||||
!a.is_numeral(n2->get_owner()) &&
|
||||
m_offset_equalities.find(n1, n2, offset);
|
||||
}
|
||||
|
||||
bool seq_offset_eq::contains(enode* r) {
|
||||
r = r->get_root();
|
||||
return !a.is_numeral(r->get_owner()) && m_has_offset_equality.contains(r);
|
||||
}
|
||||
|
||||
bool seq_offset_eq::propagate() {
|
||||
context& ctx = th.get_context();
|
||||
int lvl = (int) ctx.get_scope_level();
|
||||
if (lvl > m_propagation_level) {
|
||||
m_propagation_level = lvl;
|
||||
prop_arith_to_len_offset();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void seq_offset_eq::pop_scope_eh(unsigned num_scopes) {
|
||||
context& ctx = th.get_context();
|
||||
int new_lvl = (int) (ctx.get_scope_level() - num_scopes);
|
||||
if (m_propagation_level > new_lvl) {
|
||||
m_propagation_level = -1;
|
||||
m_offset_equalities.reset();
|
||||
m_has_offset_equality.reset();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue