mirror of
https://github.com/Z3Prover/z3
synced 2025-05-09 00:35:47 +00:00
Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
3f9edad676
commit
e9eab22e5c
1186 changed files with 381859 additions and 0 deletions
202
lib/substitution.h
Normal file
202
lib/substitution.h
Normal file
|
@ -0,0 +1,202 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
substitution.h
|
||||
|
||||
Abstract:
|
||||
|
||||
A substitution, that is, a mapping from (variable, offset) to (expr, offset).
|
||||
We use offsets in order to avoid creating variants of terms.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-01.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SUBSTITUTION_H_
|
||||
#define _SUBSTITUTION_H_
|
||||
|
||||
#include"expr_offset_map.h"
|
||||
#include"var_offset_map.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
/**
|
||||
\brief A mapping from (variable,offset) to expr_offset.
|
||||
*/
|
||||
class substitution {
|
||||
ast_manager & m_manager;
|
||||
var_offset_map<expr_offset> m_subst;
|
||||
|
||||
// field for backtracking
|
||||
typedef std::pair<unsigned, unsigned> var_offset;
|
||||
svector<var_offset> m_vars;
|
||||
unsigned_vector m_scopes;
|
||||
|
||||
// fields for applying substitutions
|
||||
svector<expr_offset> m_todo;
|
||||
expr_offset_map<expr *> m_apply_cache;
|
||||
expr_ref_vector m_new_exprs;
|
||||
|
||||
// fields for checking for cycles
|
||||
enum color { White, Grey, Black };
|
||||
expr_offset_map<color> m_color;
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
unsigned m_max_offset_since_reset;
|
||||
#endif
|
||||
void apply_visit(expr_offset const & n, bool & visited);
|
||||
|
||||
|
||||
color get_color(expr_offset const & p) const;
|
||||
void set_color(expr_offset const & p, color c);
|
||||
|
||||
void visit(expr_offset const & p, bool & visited);
|
||||
bool visit_children(expr_offset const & p);
|
||||
bool acyclic(expr_offset p);
|
||||
|
||||
public:
|
||||
substitution(ast_manager & m);
|
||||
ast_manager & get_manager() const { return m_manager; }
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Reserve memory for the given number of
|
||||
// offsets and variables.
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
void reserve(unsigned num_offsets, unsigned num_vars) { m_subst.reserve(num_offsets, num_vars); }
|
||||
void reserve_offsets(unsigned num_offsets) { m_subst.reserve_offsets(num_offsets); }
|
||||
void reserve_vars(unsigned num_vars) { m_subst.reserve_vars(num_vars); }
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Reset functions
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
// reset everything
|
||||
void reset();
|
||||
// reset only the mapping from variables to expressions
|
||||
void reset_subst();
|
||||
// reset only the substitution application cache
|
||||
void reset_cache();
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Backtracking
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
void push_scope() { m_scopes.push_back(m_vars.size()); }
|
||||
void pop_scope(unsigned num_scopes = 1);
|
||||
unsigned get_scope_lvl() { return m_scopes.size(); }
|
||||
bool top_scope_has_bindings() const { return m_scopes.empty() ? !m_vars.empty() : m_scopes.back() < m_vars.size(); }
|
||||
unsigned get_num_bindings() const { return m_vars.size(); }
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Cycle detection
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
bool acyclic();
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Insertion & Lookup
|
||||
//
|
||||
// get_binding supplies a way to inspect the substitution.
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
void insert(unsigned v_idx, unsigned offset, expr_offset const & t) {
|
||||
TRACE("subst_insert", tout << "inserting: #" << v_idx << ":" << offset << " --> " << mk_pp(t.get_expr(), m_manager)
|
||||
<< ":" << t.get_offset() << "\n";);
|
||||
m_vars.push_back(var_offset(v_idx, offset));
|
||||
m_subst.insert(v_idx, offset, t);
|
||||
}
|
||||
void insert(var * v, unsigned offset, expr_offset const & t) { insert(v->get_idx(), offset, t); }
|
||||
void insert(expr_offset v, expr_offset const & t) {
|
||||
SASSERT(is_var(v.get_expr()));
|
||||
insert(to_var(v.get_expr()), v.get_offset(), t);
|
||||
}
|
||||
|
||||
bool find(unsigned v_idx, unsigned offset, expr_offset & r) const { return m_subst.find(v_idx, offset, r); }
|
||||
bool find(var * v, unsigned offset, expr_offset & r) const { return find(v->get_idx(), offset, r); }
|
||||
bool find(expr_offset v, expr_offset & r) const {
|
||||
SASSERT(is_var(v.get_expr()));
|
||||
return find(to_var(v.get_expr()), v.get_offset(), r);
|
||||
}
|
||||
|
||||
void get_binding(unsigned binding_num, var_offset& var, expr_offset& r) {
|
||||
var = m_vars[binding_num];
|
||||
VERIFY(m_subst.find(var.first, var.second, r));
|
||||
}
|
||||
|
||||
bool contains(var * v, unsigned offset) { expr_offset r; return find(v, offset, r); }
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Application
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
/**
|
||||
\brief Apply the current substitution to the given
|
||||
expression+offset. The result is an expression.
|
||||
|
||||
The argument num_actual_offsets is the maximum offset used in a
|
||||
insert method since the last reset.
|
||||
|
||||
The argument deltas is an array of size num_actual_offsets. It contains
|
||||
the variable delta for each offset. A free variable x:i in an expression offset t:j is mapped
|
||||
to the variable x+delta[i].
|
||||
*/
|
||||
void apply(unsigned num_actual_offsets, unsigned const * deltas, expr_offset const & n, expr_ref & result) {
|
||||
apply(num_actual_offsets, deltas, n, expr_offset(0, 0), expr_offset(0, 0), result);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Similar to the previous method, but occurrences of s in n are substituted by t.
|
||||
If s != expr_offset(0,0), then the cache is reset before and after the execution of this procedure.
|
||||
*/
|
||||
void apply(unsigned num_actual_offsets, unsigned const* deltas, expr_offset const & n, expr_offset const & s, expr_offset const & t, expr_ref & result);
|
||||
|
||||
void apply(expr * n, expr_ref & result) {
|
||||
unsigned deltas[1] = { 0 };
|
||||
apply(1, deltas, expr_offset(n, 0), result);
|
||||
}
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Debugging
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
/**
|
||||
\brief Dump the current substitution (for debugging purposes).
|
||||
*/
|
||||
void display(std::ostream & out, unsigned num_actual_offsets, unsigned const * deltas);
|
||||
|
||||
/**
|
||||
\brief Dump the current substitution without normalizing expressions (for debugging purposes).
|
||||
*/
|
||||
void display(std::ostream & out);
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Compare terms modulo a substitution
|
||||
//
|
||||
// -----------------------------------
|
||||
bool compare(expr_offset t1, expr_offset t2);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue