z3-z3-4.13.0.src.ast.rewriter.bv_bounds.h Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2016 Microsoft Corporation
Module Name:
bv_bounds.h
Abstract:
A class used to determine bounds on bit-vector variables.
The satisfiability procedure is polynomial.
Author:
Mikolas Janota (MikolasJanota)
Revision History:
--*/
#pragma once
#include "ast/ast.h"
#include "ast/bv_decl_plugin.h"
#include "ast/rewriter/rewriter_types.h"
/* \brief A class to analyze constraints on bit vectors.
The objective is to identify inconsistencies in polynomial time.
All bounds/intervals are closed. Methods that add new constraints
return false if inconsistency has already been reached.
Typical usage is to call repeatedly add_constraint(e) and call is_sat() in the end.
*/
class bv_bounds {
public:
typedef rational numeral;
typedef std::pair interval;
typedef obj_map bound_map;
bv_bounds(ast_manager& m) : m_m(m), m_bv_util(m), m_okay(true) {};
~bv_bounds();
public: // bounds addition methods
br_status rewrite(unsigned limit, func_decl * f, unsigned num, expr * const * args, expr_ref& result);
/** \brief Add a constraint to the system.
The added constraints are to be considered by is_sat.
Currently, only special types of inequalities are supported, e.g. v <= v+1.
Other constraints are ignored.
Returns false if the system became trivially unsatisfiable
**/
bool add_constraint(expr* e);
bool bound_up(app * v, const numeral& u); // v <= u
bool bound_lo(app * v, const numeral& l); // l <= v
inline bool add_neg_bound(app * v, const numeral& a, const numeral& b); // not (a<=v<=b)
bool add_bound_signed(app * v, const numeral& a, const numeral& b, bool negate);
bool add_bound_unsigned(app * v, const numeral& a, const numeral& b, bool negate);
public:
bool is_sat(); ///< Determine if the set of considered constraints is satisfiable.
bool is_okay();
const bound_map& singletons() { return m_singletons; }
bv_util& bvu() { return m_bv_util; }
void reset();
protected:
struct ninterval {
//ninterval(app * v, numeral lo, numeral hi, bool negated) : v(v), lo(lo), hi(hi), negated(negated) {}
app * v;
numeral lo, hi;
bool negated;
};
enum conv_res { CONVERTED, UNSAT, UNDEF };
conv_res convert(expr * e, vector& nis, bool negated);
conv_res record(app * v, numeral lo, numeral hi, bool negated, vector& nis);
conv_res convert_signed(app * v, const numeral& a, const numeral& b, bool negate, vector& nis);
typedef vector intervals;
typedef obj_map intervals_map;
ast_manager& m_m;
bound_map m_unsigned_lowers;
bound_map m_unsigned_uppers;
intervals_map m_negative_intervals;
bound_map m_singletons;
bv_util m_bv_util;
bool m_okay;
bool is_sat(app * v);
bool is_sat_core(app * v);
inline bool in_range(app *v, const numeral& l);
inline bool is_constant_add(unsigned bv_sz, expr * e, app*& v, numeral& val);
void record_singleton(app * v, numeral& singleton_value);
inline bool to_bound(const expr * e) const;
bool is_uleq(expr * e, expr * & v, numeral & c);
};
inline bool bv_bounds::is_okay() { return m_okay; }
inline bool bv_bounds::to_bound(const expr * e) const {
return is_app(e) && m_bv_util.is_bv(e)
&& !m_bv_util.is_bv_add(e)
&& !m_bv_util.is_numeral(e);
}
inline bool bv_bounds::in_range(app *v, const bv_bounds::numeral& n) {
const unsigned bv_sz = m_bv_util.get_bv_size(v);
const bv_bounds::numeral zero(0);
const bv_bounds::numeral mod(rational::power_of_two(bv_sz));
return (zero <= n) && (n < mod);
}
inline bool bv_bounds::is_constant_add(unsigned bv_sz, expr * e, app*& v, numeral& val) {
SASSERT(e && !v);
SASSERT(m_bv_util.get_bv_size(e) == bv_sz);
expr *lhs(nullptr), *rhs(nullptr);
if (!m_bv_util.is_bv_add(e, lhs, rhs)) {
v = to_app(e);
val = rational(0);
return true;
}
if (to_bound(lhs) && m_bv_util.is_numeral(rhs, val, bv_sz)) {
v = to_app(lhs);
return true;
}
if (to_bound(rhs) && m_bv_util.is_numeral(lhs, val, bv_sz)) {
v = to_app(rhs);
return true;
}
return false;
}