3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-13 20:38:43 +00:00
z3/src/smt/seq_offset_eq.cpp
Nikolaj Bjorner 95a78b2450
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>
2020-04-22 13:18:55 -07:00

134 lines
3.6 KiB
C++

/*++
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();
}
}