z3-z3-4.13.0.src.muz.spacer.spacer_conjecture.cpp Maven / Gradle / Ivy
The newest version!
/**
Copyright (c) 2019 Microsoft Corporation and Arie Gurfinkel
Module Name:
spacer_conjecture.cpp
Abstract:
Methods to implement conjecture rule in gspacer
Author:
Arie Gurfinkel
Hari Govind
Notes:
--*/
#include "ast/for_each_expr.h"
#include "muz/spacer/spacer_context.h"
#include "muz/spacer/spacer_util.h"
namespace spacer {
/// Returns true if \p lit is LA/BV inequality with a single free variable
bool is_mono_var_lit(expr *lit, ast_manager &m) {
expr *e;
bv_util bv(m);
arith_util a_util(m);
if (m.is_not(lit, e)) return is_mono_var_lit(e, m);
if (a_util.is_arith_expr(lit) || bv.is_bv_ule(lit) ||
bv.is_bv_sle(lit)) {
return get_num_vars(lit) == 1 && !has_nonlinear_var_mul(lit, m);
}
return false;
}
/// Returns true if \p pattern contains a single mono-var literal
///
/// That is, \p pattern contains a single suitable literal.
/// The literal is returned in \p res
bool find_unique_mono_var_lit(const expr_ref &pattern, expr_ref &res) {
if (get_num_vars(pattern) != 1) return false;
ast_manager &m = res.m();
// if the pattern has multiple literals, check whether exactly one of them
// is leq
expr_ref_vector conj(m);
conj.push_back(pattern);
flatten_and(conj);
unsigned count = 0;
for (auto *lit : conj) {
if (is_mono_var_lit(lit, m)) {
if (count) return false;
res = lit;
count++;
}
}
SASSERT(count <= 1);
return count == 1;
}
/// Filter out a given literal \p lit from a list of literals
///
/// Returns true if at least one literal was filtered out
/// \p out contains all the remaining (not filtered) literals
/// \p out holds the result. Returns true if any literal has been dropped
bool filter_out_lit(const expr_ref_vector &vec, const expr_ref &lit, expr_ref_vector &out) {
ast_manager &m = vec.get_manager();
bool dirty = false, pos = false;
sem_matcher matcher(m);
substitution sub(m);
out.reset();
unsigned lit_num_vars = get_num_vars(lit.get());
SASSERT(!(m.is_not(lit) && m.is_eq(to_app(lit)->get_arg(0))));
for (auto &c : vec) {
sub.reset();
sub.reserve(1, lit_num_vars);
matcher.reset();
if (matcher(lit, c, sub, pos) && pos) {
if (is_numeric_sub(sub)) {
dirty = true;
continue;
}
}
out.push_back(c);
}
CTRACE("global", dirty,
tout << "Filtered " << lit << " from " << vec << "\n got " << out << "\n";);
return dirty;
}
} // namespace spacer