mirror of
https://github.com/Z3Prover/z3
synced 2025-08-14 23:05:26 +00:00
130 lines
4.5 KiB
C++
130 lines
4.5 KiB
C++
/*++
|
|
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:
|
|
--*/
|
|
#ifndef BV_BOUNDS_H_23754
|
|
#define BV_BOUNDS_H_23754
|
|
#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<numeral, numeral> interval;
|
|
typedef obj_map<app, numeral> 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<ninterval>& nis, bool negated);
|
|
conv_res record(app * v, numeral lo, numeral hi, bool negated, vector<ninterval>& nis);
|
|
conv_res convert_signed(app * v, const numeral& a, const numeral& b, bool negate, vector<ninterval>& nis);
|
|
|
|
typedef vector<interval> intervals;
|
|
typedef obj_map<app, intervals*> 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;
|
|
}
|
|
|
|
|
|
#endif /* BV_BOUNDS_H_23754 */
|