3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 16:45:31 +00:00

checkpoint

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2012-10-21 20:46:41 -07:00
parent 6fd63cd05a
commit 80b2df3621
29 changed files with 8 additions and 1329 deletions

40
src/api/z3_internal.h Normal file
View file

@ -0,0 +1,40 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
z3_internal.h
Abstract:
Z3 internal API for C and Python.
It provides access to internal Z3 components.
It should only be used by advanced users.
We used it to build regression tests in Python.
Author:
Leonardo de Moura (leonardo) 2012-10-18
Notes:
--*/
#ifndef _Z3_INTERNAL_H_
#define _Z3_INTERNAL_H_
#include"z3_macros.h"
#include"z3_api.h"
#include"z3_internal_types.h"
#include"z3_poly.h"
#undef __in
#undef __out
#undef __inout
#undef __in_z
#undef __out_z
#undef __ecount
#undef __in_ecount
#undef __out_ecount
#undef __inout_ecount
#endif

70
src/api/z3_logger.h Normal file
View file

@ -0,0 +1,70 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
z3_logger.h
Abstract:
Goodies for log generation
Author:
Leonardo de Moura (leonardo) 2011-09-22
Notes:
--*/
#include<iostream>
#include"symbol.h"
struct ll_escaped { char const * m_str; ll_escaped(char const * str):m_str(str) {} };
static std::ostream & operator<<(std::ostream & out, ll_escaped const & d) {
char const * s = d.m_str;
while (*s) {
char c = *s;
if (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
c == '~' || c == '!' || c == '@' || c == '#' || c == '$' || c == '%' || c == '^' || c == '&' ||
c == '*' || c == '-' || c == '_' || c == '+' || c == '.' || c == '?' || c == '/' || c == ' ' ||
c == '<' || c == '>') {
out << c;
}
else {
char str[4] = {'0', '0', '0', 0};
str[2] = '0' + (c % 10);
c /= 10;
str[1] = '0' + (c % 10);
c /= 10;
str[0] = '0' + c;
out << '\\' << str;
}
s++;
}
return out;
}
static void R() { *g_z3_log << "R\n"; g_z3_log->flush(); }
static void P(void * obj) { *g_z3_log << "P " << obj << "\n"; g_z3_log->flush(); }
static void I(__int64 i) { *g_z3_log << "I " << i << "\n"; g_z3_log->flush(); }
static void U(__uint64 u) { *g_z3_log << "U " << u << "\n"; g_z3_log->flush(); }
static void D(double d) { *g_z3_log << "D " << d << "\n"; g_z3_log->flush(); }
static void S(Z3_string str) { *g_z3_log << "S \"" << ll_escaped(str) << "\"\n"; g_z3_log->flush(); }
static void Sy(Z3_symbol sym) {
symbol s = symbol::mk_symbol_from_c_ptr(reinterpret_cast<void *>(sym));
if (s == symbol::null) {
*g_z3_log << "N\n";
}
else if (s.is_numerical()) {
*g_z3_log << "# " << s.get_num() << "\n";
}
else {
*g_z3_log << "$ |" << ll_escaped(s.bare_str()) << "|\n";
}
g_z3_log->flush();
}
static void Ap(unsigned sz) { *g_z3_log << "p " << sz << "\n"; g_z3_log->flush(); }
static void Au(unsigned sz) { *g_z3_log << "u " << sz << "\n"; g_z3_log->flush(); }
static void Asy(unsigned sz) { *g_z3_log << "s " << sz << "\n"; g_z3_log->flush(); }
static void C(unsigned id) { *g_z3_log << "C " << id << "\n"; g_z3_log->flush(); }
void _Z3_append_log(char const * msg) { *g_z3_log << "M \"" << ll_escaped(msg) << "\"\n"; g_z3_log->flush(); }

72
src/api/z3_poly.h Normal file
View file

@ -0,0 +1,72 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
z3_poly.h
Abstract:
Z3 multivariate polynomial API.
Author:
Leonardo de Moura (leonardo) 2012-10-18
Notes:
--*/
#ifndef _Z3_POLY_H_
#define _Z3_POLY_H_
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
\brief Create a new polynomial manager.
def_API('Z3_mk_polynomial_manager', POLYNOMIAL_MANAGER, (_in(CONTEXT),))
*/
Z3_polynomial_manager Z3_API Z3_mk_polynomial_manager(__in Z3_context c);
/**
\brief Delete the given polynomial manager.
def_API('Z3_del_polynomial_manager', VOID, (_in(CONTEXT), _in(POLYNOMIAL_MANAGER)))
*/
void Z3_API Z3_del_polynomial_manager(__in Z3_context c, __in Z3_polynomial_manager m);
/**
\brief Return the zero polynomial.
def_API('Z3_mk_zero_polynomial', POLYNOMIAL, (_in(CONTEXT), _in(POLYNOMIAL_MANAGER)))
*/
Z3_polynomial Z3_API Z3_mk_zero_polynomial(__in Z3_context c, __in Z3_polynomial_manager m);
/**
\brief Increment p's reference counter
def_API('Z3_polynomial_inc_ref', VOID, (_in(CONTEXT), _in(POLYNOMIAL_MANAGER), _in(POLYNOMIAL)))
*/
void Z3_API Z3_polynomial_inc_ref(__in Z3_context c, __in Z3_polynomial_manager m, __in Z3_polynomial p);
/**
\brief Decrement p's reference counter.
def_API('Z3_polynomial_dec_ref', VOID, (_in(CONTEXT), _in(POLYNOMIAL_MANAGER), _in(POLYNOMIAL)))
*/
void Z3_API Z3_polynomial_dec_ref(__in Z3_context c, __in Z3_polynomial_manager m, __in Z3_polynomial p);
/**
\brief Convert the given polynomial into a string.
def_API('Z3_polynomial_to_string', STRING, (_in(CONTEXT), _in(POLYNOMIAL_MANAGER), _in(POLYNOMIAL)))
*/
Z3_string Z3_API Z3_polynomial_to_string(__in Z3_context c, __in Z3_polynomial_manager m, __in Z3_polynomial p);
#ifdef __cplusplus
};
#endif // __cplusplus
#endif

80
src/api/z3_private.h Normal file
View file

@ -0,0 +1,80 @@
/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
z3_private.h
Abstract:
Z3 API.
Author:
Nikolaj Bjorner (nbjorner)
Leonardo de Moura (leonardo) 2007-06-8
Notes:
--*/
#include<iostream>
#include"rational.h"
#include"z3_macros.h"
#ifndef _Z3_PRIVATE__H_
#define _Z3_PRIVATE__H_
#ifndef CAMLIDL
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#else
[pointer_default(ref)] interface Z3 {
#endif // CAMLIDL
Z3_bool Z3_API Z3_get_numeral_rational(__in Z3_context c, __in Z3_ast a, rational& r);
/**
\brief \mlh exec_smtlib2_string c str \endmlh
Parse the given string using the SMT-LIB2 parser and execute its commands.
It returns a formula comprising of the conjunction of assertions in the scope
(up to push/pop) at the end of the string.
The returned formula is also asserted to the logical context on return.
*/
Z3_ast Z3_API Z3_exec_smtlib2_string(__in Z3_context c,
__in Z3_string str,
__in unsigned num_sorts,
__in_ecount(num_sorts) Z3_symbol sort_names[],
__in_ecount(num_sorts) Z3_sort sorts[],
__in unsigned num_decls,
__in_ecount(num_decls) Z3_symbol decl_names[],
__in_ecount(num_decls) Z3_func_decl decls[]
);
/**
\brief Similar to #Z3_exec_smtlib2_string, but reads the commands from a file.
*/
Z3_ast Z3_API Z3_exec_smtlib2_file(__in Z3_context c,
__in Z3_string file_name,
__in unsigned num_sorts,
__in_ecount(num_sorts) Z3_symbol sort_names[],
__in_ecount(num_sorts) Z3_sort sorts[],
__in unsigned num_decls,
__in_ecount(num_decls) Z3_symbol decl_names[],
__in_ecount(num_decls) Z3_func_decl decls[]
);
#ifndef CAMLIDL
#ifdef __cplusplus
};
#endif // __cplusplus
#else
}
#endif // CAMLIDL
#endif

711
src/api/z3_replayer.cpp Normal file
View file

@ -0,0 +1,711 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
z3_replayer.cpp
Abstract:
Interpreter for Z3 logs
Author:
Leonardo de Moura (leonardo) 2011-09-22
Notes:
--*/
#include"vector.h"
#include"map.h"
#include"z3_replayer.h"
#include"stream_buffer.h"
#include"symbol.h"
#include"trace.h"
void register_z3_replayer_cmds(z3_replayer & in);
void throw_invalid_reference() {
throw z3_replayer_exception("invalid argument reference");
}
struct z3_replayer::imp {
z3_replayer & m_owner;
std::istream & m_stream;
char m_curr; // current char;
int m_line; // line
svector<char> m_string;
symbol m_id;
__int64 m_int64;
__uint64 m_uint64;
double m_double;
size_t m_ptr;
size_t_map<void *> m_heap;
svector<z3_replayer_cmd> m_cmds;
enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY };
struct value {
value_kind m_kind;
union {
__int64 m_int;
__uint64 m_uint;
double m_double;
char const * m_str;
void * m_obj;
};
value():m_kind(OBJECT), m_int(0) {}
value(void * obj):m_kind(OBJECT), m_obj(obj) {}
value(value_kind k, char const * str):m_kind(k), m_str(str) {}
value(value_kind k, __uint64 u):m_kind(k), m_uint(u) {}
value(value_kind k, __int64 i):m_kind(k), m_int(i) {}
value(value_kind k, double d):m_kind(k), m_double(d) {}
};
svector<value> m_args;
void * m_result;
vector<ptr_vector<void> > m_obj_arrays;
vector<svector<Z3_symbol> > m_sym_arrays;
vector<unsigned_vector> m_unsigned_arrays;
imp(z3_replayer & o, std::istream & in):
m_owner(o),
m_stream(in),
m_curr(0),
m_line(1) {
next();
}
void display_arg(std::ostream & out, value const & v) const {
switch (v.m_kind) {
case INT64:
out << v.m_int;
break;
case UINT64:
out << v.m_uint;
break;
case DOUBLE:
out << v.m_double;
break;
case STRING:
out << v.m_str;
break;
case SYMBOL:
out << symbol::mk_symbol_from_c_ptr(v.m_str);
break;
case OBJECT:
out << v.m_obj;
break;
case UINT_ARRAY:
case OBJECT_ARRAY:
case SYMBOL_ARRAY:
out << "<array>";
break;
default:
out << "<unknown>";
break;
}
}
void display_args(std::ostream & out) const {
for (unsigned i = 0; i < m_args.size(); i++) {
if (i > 0) out << " ";
display_arg(out, m_args[i]);
}
}
char curr() const { return m_curr; }
void new_line() { m_line++; }
void next() { m_curr = m_stream.get(); }
void read_string_core(char delimiter) {
if (curr() != delimiter)
throw z3_replayer_exception("invalid string/symbol");
m_string.reset();
next();
while (true) {
char c = curr();
if (c == EOF) {
throw z3_replayer_exception("unexpected end of file");
}
else if (c == '\n') {
throw z3_replayer_exception("unexpected end of line");
}
else if (c == '\\') {
next();
unsigned val = 0;
unsigned sz = 0;
while (sz < 3) {
c = curr();
if ('0' <= c && c <= '9') {
val *= 10;
val += c - '0';
sz++;
}
else {
throw z3_replayer_exception("invalid scaped character");
}
if (val > 255)
throw z3_replayer_exception("invalid scaped character");
next();
}
TRACE("z3_replayer_escape", tout << "val: " << val << "\n";);
m_string.push_back(static_cast<char>(val));
}
else if (c == delimiter) {
next();
m_string.push_back(0);
return;
}
else {
m_string.push_back(c);
next();
}
}
}
void read_string() {
read_string_core('"');
}
void read_quoted_symbol() {
read_string_core('|');
m_id = m_string.begin();
}
void read_int64() {
if (!(curr() == '-' || ('0' <= curr() && curr() <= '9')))
throw z3_replayer_exception("invalid integer");
bool sign = false;
if (curr() == '-') {
sign = true;
next();
if (!('0' <= curr() && curr() <= '9'))
throw z3_replayer_exception("invalid integer");
}
m_int64 = 0;
while (true) {
char c = curr();
if ('0' <= c && c <= '9') {
m_int64 = 10*m_int64 + (c - '0');
next();
}
else {
break;
}
}
if (sign)
m_int64 = -m_int64;
}
void read_uint64() {
if (!('0' <= curr() && curr() <= '9'))
throw z3_replayer_exception("invalid unsigned");
m_uint64 = 0;
while (true) {
char c = curr();
if ('0' <= c && c <= '9') {
m_uint64 = 10*m_uint64 + (c - '0');
next();
}
else {
break;
}
}
}
bool is_double_char() const {
return curr() == '-' || curr() == '.' || ('0' <= curr() && curr() <= '9') || curr() == 'e' || curr() == 'E';
}
void read_double() {
m_string.reset();
while (is_double_char()) {
m_string.push_back(curr());
next();
}
if (m_string.empty())
throw z3_replayer_exception("invalid double");
m_string.push_back(0);
char * ptr;
m_double = strtod(m_string.begin(), &ptr);
}
void read_ptr() {
if (!(('0' <= curr() && curr() <= '9') || ('A' <= curr() && curr() <= 'F') || ('a' <= curr() && curr() <= 'f')))
throw z3_replayer_exception("invalid ptr");
m_ptr = 0;
while (true) {
char c = curr();
if ('0' <= c && c <= '9') {
m_ptr = m_ptr * 16 + (c - '0');
}
else if ('a' <= c && c <= 'f') {
m_ptr = m_ptr * 16 + 10 + (c - 'a');
}
else if ('A' <= c && c <= 'F') {
m_ptr = m_ptr * 16 + 10 + (c - 'A');
}
else {
return;
}
next();
}
}
void skip_blank() {
while (true) {
char c = curr();
if (c == '\n') {
new_line();
next();
}
else if (c == ' ' || c == '\t') {
next();
}
else {
break;
}
}
}
void push_array(unsigned sz, value_kind k) {
unsigned asz = m_args.size();
if (sz > asz)
throw z3_replayer_exception("invalid array size");
__uint64 aidx;
value_kind nk;
for (unsigned i = asz - sz; i < asz; i++) {
if (m_args[i].m_kind != k)
throw z3_replayer_exception("invalid array: mixed value types");
}
if (k == UINT64) {
aidx = m_unsigned_arrays.size();
nk = UINT_ARRAY;
m_unsigned_arrays.push_back(unsigned_vector());
unsigned_vector & v = m_unsigned_arrays.back();
for (unsigned i = asz - sz; i < asz; i++) {
v.push_back(static_cast<unsigned>(m_args[i].m_uint));
}
}
else if (k == SYMBOL) {
aidx = m_sym_arrays.size();
nk = SYMBOL_ARRAY;
m_sym_arrays.push_back(svector<Z3_symbol>());
svector<Z3_symbol> & v = m_sym_arrays.back();
for (unsigned i = asz - sz; i < asz; i++) {
v.push_back(reinterpret_cast<Z3_symbol>(const_cast<char*>(m_args[i].m_str)));
}
}
else if (k == OBJECT) {
TRACE("z3_replayer_bug",
tout << "args: "; display_args(tout); tout << "\n";
tout << "push_back, sz: " << sz << ", m_obj_arrays.size(): " << m_obj_arrays.size() << "\n";
for (unsigned i = asz - sz; i < asz; i++) {
tout << "pushing: " << m_args[i].m_obj << "\n";
});
aidx = m_obj_arrays.size();
nk = OBJECT_ARRAY;
m_obj_arrays.push_back(ptr_vector<void>());
ptr_vector<void> & v = m_obj_arrays.back();
for (unsigned i = asz - sz; i < asz; i++) {
v.push_back(m_args[i].m_obj);
}
}
else {
throw z3_replayer_exception("unsupported array type");
}
m_args.shrink(asz - sz);
m_args.push_back(value(nk, aidx));
}
#define TICK_FREQUENCY 100000
void parse() {
unsigned long long counter = 0;
unsigned tick = 0;
while (true) {
IF_VERBOSE(1, {
counter++; tick++;
if (tick >= TICK_FREQUENCY) {
std::cout << "[replayer] " << counter << " operations executed" << std::endl;
tick = 0;
}
});
skip_blank();
char c = curr();
if (c == EOF)
return;
switch (c) {
case 'R':
// reset
next();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "R\n";);
reset();
break;
case 'P': {
// push pointer
next(); skip_blank(); read_ptr();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "P " << m_ptr << "\n";);
if (m_ptr == 0) {
m_args.push_back(0);
}
else {
void * obj = 0;
if (!m_heap.find(m_ptr, obj))
throw z3_replayer_exception("invalid pointer");
m_args.push_back(value(obj));
TRACE("z3_replayer_bug", tout << "args after 'P':\n"; display_args(tout); tout << "\n";);
}
break;
}
case 'S': {
// push string
next(); skip_blank(); read_string();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "S " << m_string.begin() << "\n";);
symbol sym(m_string.begin()); // save string
m_args.push_back(value(STRING, sym.bare_str()));
break;
}
case 'N':
// push null symbol
next();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "N\n";);
m_args.push_back(value(SYMBOL, static_cast<char const *>(0)));
break;
case '$': {
// push symbol
next(); skip_blank(); read_quoted_symbol();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "$ " << m_id << "\n";);
m_args.push_back(value(SYMBOL, m_id.bare_str()));
break;
}
case '#': {
// push numeral symbol
next(); skip_blank(); read_uint64();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "# " << m_uint64 << "\n";);
symbol sym(static_cast<unsigned>(m_uint64));
m_args.push_back(value(SYMBOL, static_cast<char const *>(sym.c_ptr())));
break;
}
case 'I':
// push integer;
next(); skip_blank(); read_int64();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "I " << m_int64 << "\n";);
m_args.push_back(value(INT64, m_int64));
break;
case 'U':
// push unsigned;
next(); skip_blank(); read_uint64();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "U " << m_uint64 << "\n";);
m_args.push_back(value(UINT64, m_uint64));
break;
case 'D':
// push double
next(); skip_blank(); read_double();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "D " << m_double << "\n";);
m_args.push_back(value(DOUBLE, m_double));
break;
case 'p':
case 's':
case 'u':
// push array
next(); skip_blank(); read_uint64();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "A " << m_uint64 << "\n";);
if (c == 'p')
push_array(static_cast<unsigned>(m_uint64), OBJECT);
else if (c == 's')
push_array(static_cast<unsigned>(m_uint64), SYMBOL);
else
push_array(static_cast<unsigned>(m_uint64), UINT64);
break;
case 'C': {
// call procedure
next(); skip_blank(); read_uint64();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "C " << m_uint64 << "\n";);
unsigned idx = static_cast<unsigned>(m_uint64);
if (idx >= m_cmds.size())
throw z3_replayer_exception("invalid command");
try {
m_cmds[idx](m_owner);
}
catch (z3_error & ex) {
throw ex;
}
catch (z3_exception & ex) {
std::cout << "[z3 exception]: " << ex.msg() << std::endl;
}
break;
}
case '=':
// save result
// = obj_id
next(); skip_blank(); read_ptr();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "= " << m_ptr << "\n";);
m_heap.insert(m_ptr, m_result);
break;
case '*': {
// save out
// @ obj_id pos
next(); skip_blank(); read_ptr(); skip_blank(); read_uint64();
unsigned pos = static_cast<unsigned>(m_uint64);
TRACE("z3_replayer", tout << "[" << m_line << "] " << "* " << m_ptr << " " << pos << "\n";);
if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT)
throw_invalid_reference();
m_heap.insert(m_ptr, m_args[pos].m_obj);
break;
}
case '@': {
// save array out
// @ obj_id array_pos idx
next(); skip_blank(); read_ptr(); skip_blank(); read_uint64();
unsigned pos = static_cast<unsigned>(m_uint64);
if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT_ARRAY)
throw_invalid_reference();
unsigned aidx = static_cast<unsigned>(m_args[pos].m_uint);
ptr_vector<void> & v = m_obj_arrays[aidx];
skip_blank(); read_uint64();
unsigned idx = static_cast<unsigned>(m_uint64);
TRACE("z3_replayer", tout << "[" << m_line << "] " << "@ " << m_ptr << " " << pos << " " << idx << "\n";);
TRACE("z3_replayer_bug", tout << "v[idx]: " << v[idx] << "\n";);
m_heap.insert(m_ptr, v[idx]);
break;
}
case 'M':
// user message
next(); skip_blank(); read_string();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "M " << m_string.begin() << "\n";);
std::cout << m_string.begin() << "\n"; std::cout.flush();
break;
default:
TRACE("z3_replayer", tout << "unknown command " << c << "\n";);
throw z3_replayer_exception("unknown log command");
break;
}
}
}
int get_int(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != INT64)
throw_invalid_reference();
return static_cast<int>(m_args[pos].m_int);
}
__int64 get_int64(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != INT64)
throw_invalid_reference();
return m_args[pos].m_int;
}
unsigned get_uint(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != UINT64)
throw_invalid_reference();
return static_cast<unsigned>(m_args[pos].m_uint);
}
__uint64 get_uint64(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != UINT64)
throw_invalid_reference();
return m_args[pos].m_uint;
}
double get_double(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != DOUBLE)
throw_invalid_reference();
return m_args[pos].m_double;
}
Z3_string get_str(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != STRING)
throw_invalid_reference();
return m_args[pos].m_str;
}
Z3_symbol get_symbol(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != SYMBOL)
throw_invalid_reference();
return reinterpret_cast<Z3_symbol>(const_cast<char*>(m_args[pos].m_str));
}
void * get_obj(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT)
throw_invalid_reference();
return m_args[pos].m_obj;
}
unsigned * get_uint_array(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != UINT_ARRAY)
throw_invalid_reference();
unsigned idx = static_cast<unsigned>(m_args[pos].m_uint);
return m_unsigned_arrays[idx].c_ptr();
}
Z3_symbol * get_symbol_array(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != SYMBOL_ARRAY)
throw_invalid_reference();
unsigned idx = static_cast<unsigned>(m_args[pos].m_uint);
return m_sym_arrays[idx].c_ptr();
}
void ** get_obj_array(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT_ARRAY)
throw_invalid_reference();
unsigned idx = static_cast<unsigned>(m_args[pos].m_uint);
ptr_vector<void> const & v = m_obj_arrays[idx];
TRACE("z3_replayer_bug", tout << "pos: " << pos << ", idx: " << idx << " size(): " << v.size() << "\n";
for (unsigned i = 0; i < v.size(); i++) tout << v[i] << " "; tout << "\n";);
return v.c_ptr();
}
int * get_int_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != INT64)
throw_invalid_reference();
return reinterpret_cast<int*>(&(m_args[pos].m_int));
}
__int64 * get_int64_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != INT64)
throw_invalid_reference();
return &(m_args[pos].m_int);
}
unsigned * get_uint_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != UINT64)
throw_invalid_reference();
return reinterpret_cast<unsigned*>(&(m_args[pos].m_uint));
}
__uint64 * get_uint64_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != UINT64)
throw_invalid_reference();
return &(m_args[pos].m_uint);
}
Z3_string * get_str_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != STRING)
throw_invalid_reference();
return &(m_args[pos].m_str);
}
void ** get_obj_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT)
throw_invalid_reference();
return &(m_args[pos].m_obj);
}
void store_result(void * obj) {
m_result = obj;
}
void register_cmd(unsigned id, z3_replayer_cmd cmd) {
m_cmds.reserve(id+1, 0);
m_cmds[id] = cmd;
}
void reset() {
m_result = 0;
m_args.reset();
m_obj_arrays.reset();
m_sym_arrays.reset();
m_unsigned_arrays.reset();
}
};
z3_replayer::z3_replayer(std::istream & in) {
m_imp = alloc(imp, *this, in);
register_z3_replayer_cmds(*this);
}
z3_replayer::~z3_replayer() {
dealloc(m_imp);
}
unsigned z3_replayer::get_line() const {
return m_imp->m_line;
}
bool z3_replayer::get_bool(unsigned pos) const {
return get_int(pos) != 0;
}
int z3_replayer::get_int(unsigned pos) const {
return m_imp->get_int(pos);
}
unsigned z3_replayer::get_uint(unsigned pos) const {
return m_imp->get_uint(pos);
}
__int64 z3_replayer::get_int64(unsigned pos) const {
return m_imp->get_int64(pos);
}
__uint64 z3_replayer::get_uint64(unsigned pos) const {
return m_imp->get_uint64(pos);
}
double z3_replayer::get_double(unsigned pos) const {
return m_imp->get_double(pos);
}
Z3_string z3_replayer::get_str(unsigned pos) const {
return m_imp->get_str(pos);
}
Z3_symbol z3_replayer::get_symbol(unsigned pos) const {
return m_imp->get_symbol(pos);
}
void * z3_replayer::get_obj(unsigned pos) const {
return m_imp->get_obj(pos);
}
unsigned * z3_replayer::get_uint_array(unsigned pos) const {
return m_imp->get_uint_array(pos);
}
Z3_symbol * z3_replayer::get_symbol_array(unsigned pos) const {
return m_imp->get_symbol_array(pos);
}
void ** z3_replayer::get_obj_array(unsigned pos) const {
return m_imp->get_obj_array(pos);
}
int * z3_replayer::get_int_addr(unsigned pos) {
return m_imp->get_int_addr(pos);
}
__int64 * z3_replayer::get_int64_addr(unsigned pos) {
return m_imp->get_int64_addr(pos);
}
unsigned * z3_replayer::get_uint_addr(unsigned pos) {
return m_imp->get_uint_addr(pos);
}
__uint64 * z3_replayer::get_uint64_addr(unsigned pos) {
return m_imp->get_uint64_addr(pos);
}
Z3_string * z3_replayer::get_str_addr(unsigned pos) {
return m_imp->get_str_addr(pos);
}
void ** z3_replayer::get_obj_addr(unsigned pos) {
return m_imp->get_obj_addr(pos);
}
void z3_replayer::store_result(void * obj) {
return m_imp->store_result(obj);
}
void z3_replayer::register_cmd(unsigned id, z3_replayer_cmd cmd) {
return m_imp->register_cmd(id, cmd);
}
void z3_replayer::parse() {
return m_imp->parse();
}

66
src/api/z3_replayer.h Normal file
View file

@ -0,0 +1,66 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
z3_replayer.h
Abstract:
Interpreter for Z3 logs
Author:
Leonardo de Moura (leonardo) 2011-09-22
Notes:
--*/
#ifndef _Z3_REPLAYER_H_
#define _Z3_REPLAYER_H_
#include<iostream>
#include"z3.h"
#include"z3_exception.h"
class z3_replayer;
typedef void (*z3_replayer_cmd)(z3_replayer &);
typedef default_exception z3_replayer_exception;
class z3_replayer {
struct imp;
imp * m_imp;
public:
z3_replayer(std::istream & in);
~z3_replayer();
void parse();
unsigned get_line() const;
int get_int(unsigned pos) const;
unsigned get_uint(unsigned pos) const;
__int64 get_int64(unsigned pos) const;
__uint64 get_uint64(unsigned pos) const;
double get_double(unsigned pos) const;
bool get_bool(unsigned pos) const;
Z3_string get_str(unsigned pos) const;
Z3_symbol get_symbol(unsigned pos) const;
void * get_obj(unsigned pos) const;
unsigned * get_uint_array(unsigned pos) const;
Z3_symbol * get_symbol_array(unsigned pos) const;
void ** get_obj_array(unsigned pos) const;
int * get_int_addr(unsigned pos);
__int64 * get_int64_addr(unsigned pos);
unsigned * get_uint_addr(unsigned pos);
__uint64 * get_uint64_addr(unsigned pos);
Z3_string * get_str_addr(unsigned pos);
void ** get_obj_addr(unsigned pos);
void store_result(void * obj);
void register_cmd(unsigned id, z3_replayer_cmd cmd);
};
#endif

1304
src/api/z3_solver.cpp Normal file

File diff suppressed because it is too large Load diff

1007
src/api/z3_solver.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,46 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
value_compiler_extension.h
Abstract:
Compiler extension for creating values (i.e., "interpreted" constants that
are different any other constant).
Author:
Leonardo de Moura (leonardo) 2006-10-31.
Revision History:
--*/
#ifndef _VALUE_COMPILER_EXTENSION_H_
#define _VALUE_COMPILER_EXTENSION_H_
#include"ast_compiler.h"
class value_compiler_extension : public ast_compiler_plugin {
context & m_context;
public:
value_compiler_extension(ast_manager & m, context & ctx):
ast_compiler_plugin(m.get_family_id(symbol("interpreted_value"))),
m_context(ctx) {
ctx.register_plugin(this);
}
virtual ~value_compiler_extension() {
}
virtual bool compile_term(ast_compiler & c, const_ast * a, enode * & r) {
SASSERT(a->get_decl()->get_family_id() == m_fid);
const_decl_ast * d = a->get_decl();
r = m_context.mk_interpreted_const(d);
return true;
}
};
#endif /* _VALUE_COMPILER_EXTENSION_H_ */

View file

@ -0,0 +1,48 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
default_tactic.cpp
Abstract:
General purpose tactic for the Z3 logic (when the logic is not specified).
Author:
Leonardo (leonardo) 2012-02-22
Notes:
--*/
#include"default_tactic.h"
#include"simplify_tactic.h"
#include"qfbv_tactic.h"
#include"smt_tactic.h"
#include"qflia_tactic.h"
#include"qflra_tactic.h"
#include"qfnia_tactic.h"
#include"qfnra_tactic.h"
#include"nra_tactic.h"
#include"probe_arith.h"
tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
tactic * st = using_params(and_then(mk_simplify_tactic(m),
cond(mk_is_qfbv_probe(),
mk_qfbv_tactic(m),
cond(mk_is_qflia_probe(),
mk_qflia_tactic(m),
cond(mk_is_qflra_probe(),
mk_qflra_tactic(m),
cond(mk_is_qfnra_probe(),
mk_qfnra_tactic(m),
cond(mk_is_qfnia_probe(),
mk_qfnia_tactic(m),
cond(mk_is_nra_probe(),
mk_nra_tactic(m),
mk_smt_tactic()))))))),
p);
return st;
}

View file

@ -0,0 +1,28 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
default_tactic.h
Abstract:
General purpose tactic for the Z3 logic (when the logic is not specified).
Author:
Leonardo (leonardo) 2012-02-22
Notes:
--*/
#ifndef _DEFAULT_TACTIC_
#define _DEFAULT_TACTIC_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_default_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,236 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
install_tactics.cpp
Abstract:
Install tactics in the SMT 2.0 frontend.
Author:
Leonardo (leonardo) 2012-02-19
Notes:
--*/
#include"tactic_cmds.h"
#include"cmd_context.h"
#include"simplify_tactic.h"
#include"split_clause_tactic.h"
#include"normalize_bounds_tactic.h"
#include"elim_uncnstr_tactic.h"
#include"add_bounds_tactic.h"
#include"ctx_simplify_tactic.h"
#include"ctx_solver_simplify_tactic.h"
#include"bit_blaster_tactic.h"
#include"bv1_blaster_tactic.h"
#include"der_tactic.h"
#include"aig_tactic.h"
#include"smt_tactic.h"
#include"sat_tactic.h"
#include"occf_tactic.h"
#include"qe_tactic.h"
#include"qe_sat_tactic.h"
#include"propagate_values_tactic.h"
#include"nnf_tactic.h"
#include"solve_eqs_tactic.h"
#include"max_bv_sharing_tactic.h"
#include"elim_term_ite_tactic.h"
#include"fix_dl_var_tactic.h"
#include"tseitin_cnf_tactic.h"
#include"degree_shift_tactic.h"
#include"purify_arith_tactic.h"
#include"nla2bv_tactic.h"
#include"nlsat_tactic.h"
#include"factor_tactic.h"
#include"fm_tactic.h"
#include"diff_neq_tactic.h"
#include"lia2pb_tactic.h"
#include"fpa2bv_tactic.h"
#include"qffpa_tactic.h"
#include"pb2bv_tactic.h"
#include"recover_01_tactic.h"
#include"symmetry_reduce_tactic.h"
#include"distribute_forall_tactic.h"
#include"reduce_args_tactic.h"
#include"bv_size_reduction_tactic.h"
#include"propagate_ineqs_tactic.h"
#include"cofactor_term_ite_tactic.h"
#include"mip_tactic.h"
#include"vsubst_tactic.h"
#include"sls_tactic.h"
#include"probe_arith.h"
#include"qflia_tactic.h"
#include"qflra_tactic.h"
#include"qfnia_tactic.h"
#include"qfnra_tactic.h"
#include"qfbv_tactic.h"
#include"subpaving_tactic.h"
#include"unit_subsumption_tactic.h"
#include"qfnra_nlsat_tactic.h"
MK_SIMPLE_TACTIC_FACTORY(simplifier_fct, mk_simplify_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(split_clause_fct, mk_split_clause_tactic(p));
MK_SIMPLE_TACTIC_FACTORY(normalize_bounds_fct, mk_normalize_bounds_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(elim_uncnstr_fct, mk_elim_uncnstr_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(add_bounds_fct, mk_add_bounds_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(bitblaster_fct, mk_bit_blaster_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(bv1blaster_fct, mk_bv1_blaster_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(aig_fct, mk_aig_tactic(p));
MK_SIMPLE_TACTIC_FACTORY(skip_fct, mk_skip_tactic());
MK_SIMPLE_TACTIC_FACTORY(fail_fct, mk_fail_tactic());
MK_SIMPLE_TACTIC_FACTORY(smt_fct, mk_smt_tactic(p));
MK_SIMPLE_TACTIC_FACTORY(sat_fct, mk_sat_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(sat_preprocess_fct, mk_sat_preprocessor_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(ctx_simplify_fct, mk_ctx_simplify_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(ctx_solver_simplify_fct, mk_ctx_solver_simplify_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(unit_subsume_fct, mk_unit_subsumption_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(der_fct, mk_der_tactic(m));
MK_SIMPLE_TACTIC_FACTORY(occf_fct, mk_occf_tactic(m));
MK_SIMPLE_TACTIC_FACTORY(qe_fct, mk_qe_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qe_sat_fct, qe::mk_sat_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(propagate_values_fct, mk_propagate_values_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(snf_fct, mk_snf_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(nnf_fct, mk_nnf_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(solve_eqs_fct, mk_solve_eqs_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(max_bv_sharing_fct, mk_max_bv_sharing_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(elim_term_ite_fct, mk_elim_term_ite_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(fix_dl_var_fct, mk_fix_dl_var_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(tseitin_cnf_fct, mk_tseitin_cnf_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(tseitin_cnf_core_fct, mk_tseitin_cnf_core_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(degree_shift_fct, mk_degree_shift_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(purify_arith_fct, mk_purify_arith_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(nlsat_fct, mk_nlsat_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(factor_fct, mk_factor_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(fm_fct, mk_fm_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(fail_if_undecided_fct, mk_fail_if_undecided_tactic());
MK_SIMPLE_TACTIC_FACTORY(diff_neq_fct, mk_diff_neq_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(lia2pb_fct, mk_lia2pb_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(fpa2bv_fct, mk_fpa2bv_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qffpa_fct, mk_qffpa_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(pb2bv_fct, mk_pb2bv_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(recover_01_fct, mk_recover_01_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(elim_and_fct, mk_elim_and_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(symmetry_reduce_fct, mk_symmetry_reduce_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(distribute_forall_fct, mk_distribute_forall_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(reduce_args_fct, mk_reduce_args_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(bv_size_reduction_fct, mk_bv_size_reduction_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(propagate_ineqs_fct, mk_propagate_ineqs_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(cofactor_term_ite_fct, mk_cofactor_term_ite_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(mip_fct, mk_mip_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(nla2bv_fct, mk_nla2bv_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(vsubst_fct, mk_vsubst_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfbv_sls_fct, mk_qfbv_sls_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(subpaving_fct, mk_subpaving_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qflia_fct, mk_qflia_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qflra_fct, mk_qflra_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfbv_fct, mk_qfbv_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfnia_fct, mk_qfnia_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfnra_fct, mk_qfnra_tactic(m, p));
#define ADD_TACTIC_CMD(NAME, DESCR, FACTORY) ctx.insert(alloc(tactic_cmd, symbol(NAME), DESCR, alloc(FACTORY)))
#define ADD_PROBE(NAME, DESCR, PROBE) ctx.insert(alloc(probe_info, symbol(NAME), DESCR, PROBE))
void install_tactics(tactic_manager & ctx) {
ADD_TACTIC_CMD("simplify", "apply simplification rules.", simplifier_fct);
ADD_TACTIC_CMD("split-clause", "split a clause in many subgoals.", split_clause_fct);
ADD_TACTIC_CMD("normalize-bounds", "replace a variable x with lower bound k <= x with x' = x - k.", normalize_bounds_fct);
ADD_TACTIC_CMD("elim-uncnstr", "eliminate application containing unconstrained variables.", elim_uncnstr_fct);
ADD_TACTIC_CMD("elim-and", "convert (and a b) into (not (or (not a) (not b))).", elim_and_fct);
ADD_TACTIC_CMD("add-bounds", "add bounds to unbounded variables (under approximation).", add_bounds_fct);
ADD_TACTIC_CMD("aig", "simplify Boolean structure using AIGs.", aig_fct);
ADD_TACTIC_CMD("skip", "do nothing tactic.", skip_fct);
ADD_TACTIC_CMD("fail", "always fail tactic.", fail_fct);
ADD_TACTIC_CMD("smt", "apply a SAT based SMT solver.", smt_fct);
ADD_TACTIC_CMD("bit-blast", "reduce bit-vector expressions into SAT.", bitblaster_fct);
ADD_TACTIC_CMD("bv1-blast", "reduce bit-vector expressions into bit-vectors of size 1 (notes: only equality, extract and concat are supported).", bv1blaster_fct);
ADD_TACTIC_CMD("sat", "(try to) solve goal using a SAT solver.", sat_fct);
ADD_TACTIC_CMD("sat-preprocess", "Apply SAT solver preprocessing procedures (bounded resolution, Boolean constant propagation, 2-SAT, subsumption, subsumption resolution).", sat_preprocess_fct);
ADD_TACTIC_CMD("ctx-simplify", "apply contextual simplification rules.", ctx_simplify_fct);
ADD_TACTIC_CMD("ctx-solver-simplify", "apply solver-based contextual simplification rules.", ctx_solver_simplify_fct);
ADD_TACTIC_CMD("der", "destructive equality resolution.", der_fct);
ADD_TACTIC_CMD("unit-subsume-simplify", "unit subsumption simplification.", unit_subsume_fct);
ADD_TACTIC_CMD("occf", "put goal in one constraint per clause normal form (notes: fails if proof generation is enabled; only clauses are considered).", occf_fct);
ADD_TACTIC_CMD("qe", "apply quantifier elimination.", qe_fct);
ADD_TACTIC_CMD("qe-sat", "check satisfiability of quantified formulas using quantifier elimination.", qe_sat_fct);
ADD_TACTIC_CMD("propagate-values", "propagate constants.", propagate_values_fct);
ADD_TACTIC_CMD("snf", "put goal in skolem normal form.", snf_fct);
ADD_TACTIC_CMD("nnf", "put goal in negation normal form.", nnf_fct);
ADD_TACTIC_CMD("solve-eqs", "eliminate variables by solving equations.", solve_eqs_fct);
ADD_TACTIC_CMD("max-bv-sharing", "use heuristics to maximize the sharing of bit-vector expressions such as adders and multipliers.", max_bv_sharing_fct);
ADD_TACTIC_CMD("elim-term-ite", "eliminate term if-then-else by adding fresh auxiliary declarations.", elim_term_ite_fct);
ADD_TACTIC_CMD("fix-dl-var", "if goal is in the difference logic fragment, then fix the variable with the most number of occurrences at 0.",
fix_dl_var_fct);
ADD_TACTIC_CMD("tseitin-cnf", "convert goal into CNF using tseitin-like encoding (note: quantifiers are ignored).", tseitin_cnf_fct);
ADD_TACTIC_CMD("tseitin-cnf-core", "convert goal into CNF using tseitin-like encoding (note: quantifiers are ignored). This tactic does not apply required simplifications to the input goal like the tseitin-cnf tactic.", tseitin_cnf_core_fct);
ADD_TACTIC_CMD("degree-shift", "try to reduce degree of polynomials (remark: :mul2power simplification is automatically applied).", degree_shift_fct);
ADD_TACTIC_CMD("purify-arith", "eliminate unnecessary operators: -, /, div, mod, rem, is-int, to-int, ^, root-objects.", purify_arith_fct);
ADD_TACTIC_CMD("nlsat", "(try to) solve goal using a nonlinear arithmetic solver.", nlsat_fct);
ADD_TACTIC_CMD("factor", "polynomial factorization.", factor_fct);
ADD_TACTIC_CMD("fm", "eliminate variables using fourier-motzkin elimination.", fm_fct);
ADD_TACTIC_CMD("fail-if-undecided", "fail if goal is undecided.", fail_if_undecided_fct);
ADD_TACTIC_CMD("diff-neq", "specialized solver for integer arithmetic problems that contain only atoms of the form (<= k x) (<= x k) and (not (= (- x y) k)), where x and y are constants and k is a numberal, and all constants are bounded.", diff_neq_fct);
ADD_TACTIC_CMD("lia2pb", "convert bounded integer variables into a sequence of 0-1 variables.", lia2pb_fct);
ADD_TACTIC_CMD("fpa2bv", "convert floating point numbers to bit-vectors.", fpa2bv_fct);
ADD_TACTIC_CMD("qffpa", "(try to) solve goal using the tactic for QF_FPA.", qffpa_fct);
ADD_TACTIC_CMD("pb2bv", "convert pseudo-boolean constraints to bit-vectors.", pb2bv_fct);
ADD_TACTIC_CMD("recover-01", "recover 0-1 variables hidden as Boolean variables.", recover_01_fct);
ADD_TACTIC_CMD("symmetry-reduce", "apply symmetry reduction.", symmetry_reduce_fct);
ADD_TACTIC_CMD("distribute-forall", "distribute forall over conjunctions.", distribute_forall_fct);
ADD_TACTIC_CMD("reduce-args", "reduce the number of arguments of function applications, when for all occurrences of a function f the i-th is a value.",
reduce_args_fct);
ADD_TACTIC_CMD("reduce-bv-size", "try to reduce bit-vector sizes using inequalities.", bv_size_reduction_fct);
ADD_TACTIC_CMD("propagate-ineqs", "propagate ineqs/bounds, remove subsumed inequalities.", propagate_ineqs_fct);
ADD_TACTIC_CMD("cofactor-term-ite", "eliminate term if-the-else using cofactors.", cofactor_term_ite_fct);
ADD_TACTIC_CMD("mip", "solver for mixed integer programming problems.", mip_fct);
ADD_TACTIC_CMD("nla2bv", "convert a nonlinear arithmetic problem into a bit-vector problem, in most cases the resultant goal is an under approximation and is useul for finding models.", nla2bv_fct);
ADD_TACTIC_CMD("vsubst", "checks satsifiability of quantifier-free non-linear constraints using virtual substitution.", vsubst_fct);
ADD_TACTIC_CMD("qfbv-sls", "(try to) solve using stochastic local search for QF_BV.", qfbv_sls_fct);
ADD_TACTIC_CMD("qflia", "builtin strategy for solving QF_LIA problems.", qflia_fct);
ADD_TACTIC_CMD("qflra", "builtin strategy for solving QF_LRA problems.", qflra_fct);
ADD_TACTIC_CMD("qfnia", "builtin strategy for solving QF_NIA problems.", qfnia_fct);
ADD_TACTIC_CMD("qfnra", "builtin strategy for solving QF_NRA problems.", qfnra_fct);
ADD_TACTIC_CMD("qfnra-nlsat", "builtin strategy for solving QF_NRA problems using only nlsat.", qfnra_nlsat_fct);
ADD_TACTIC_CMD("qfbv", "builtin strategy for solving QF_BV problems.", qfbv_fct);
#ifndef _EXTERNAL_RELEASE
ADD_TACTIC_CMD("subpaving", "tactic for testing subpaving module.", subpaving_fct);
#endif
ADD_PROBE("memory", "ammount of used memory in megabytes.", mk_memory_probe());
ADD_PROBE("depth", "depth of the input goal.", mk_depth_probe());
ADD_PROBE("size", "number of assertions in the given goal.", mk_size_probe());
ADD_PROBE("num-exprs", "number of expressions/terms in the given goal.", mk_num_exprs_probe());
ADD_PROBE("num-consts", "number of non Boolean constants in the given goal.", mk_num_consts_probe());
ADD_PROBE("num-bool-consts", "number of Boolean constants in the given goal.", mk_num_bool_consts_probe());
ADD_PROBE("num-arith-consts", "number of arithmetic constants in the given goal.", mk_num_arith_consts_probe());
ADD_PROBE("num-bv-consts", "number of bit-vector constants in the given goal.", mk_num_bv_consts_probe());
ADD_PROBE("produce-proofs", "true if proof generation is enabled for the given goal.", mk_produce_proofs_probe());
ADD_PROBE("produce-model", "true if model generation is enabled for the given goal.", mk_produce_models_probe());
ADD_PROBE("produce-unsat-cores", "true if unsat-core generation is enabled for the given goal.", mk_produce_unsat_cores_probe());
ADD_PROBE("has-patterns", "true if the goal contains quantifiers with patterns.", mk_has_pattern_probe());
ADD_PROBE("is-propositional", "true if the goal is in propositional logic.", mk_is_propositional_probe());
ADD_PROBE("is-qfbv", "true if the goal is in QF_BV.", mk_is_qfbv_probe());
ADD_PROBE("is-qfbv-eq", "true if the goal is in a fragment of QF_BV which uses only =, extract, concat.", mk_is_qfbv_eq_probe());
ADD_PROBE("is-qflia", "true if the goal is in QF_LIA.", mk_is_qflia_probe());
ADD_PROBE("is-qflra", "true if the goal is in QF_LRA.", mk_is_qflra_probe());
ADD_PROBE("is-qflira", "true if the goal is in QF_LIRA.", mk_is_qflira_probe());
ADD_PROBE("is-ilp", "true if the goal is ILP.", mk_is_ilp_probe());
ADD_PROBE("is-mip", "true if the goal is MIP.", mk_is_mip_probe());
ADD_PROBE("is-unbounded", "true if the goal contains integer/real constants that do not have lower/upper bounds.", mk_is_unbounded_probe());
ADD_PROBE("is-pb", "true if the goal is a pseudo-boolean problem.", mk_is_pb_probe());
ADD_PROBE("arith-max-deg", "max polynomial total degree of an arithmetic atom.", mk_arith_max_degree_probe());
ADD_PROBE("arith-avg-deg", "avg polynomial total degree of an arithmetic atom.", mk_arith_avg_degree_probe());
ADD_PROBE("arith-max-bw", "max coefficient bit width.", mk_arith_max_bw_probe());
ADD_PROBE("arith-avg-bw", "avg coefficient bit width.", mk_arith_avg_bw_probe());
ADD_PROBE("is-qfnia", "true if the goal is in QF_NIA (quantifier-free nonlinear integer arithmetic).", mk_is_qfnia_probe());
ADD_PROBE("is-qfnra", "true if the goal is in QF_NRA (quantifier-free nonlinear real arithmetic).", mk_is_qfnra_probe());
ADD_PROBE("is-nia", "true if the goal is in NIA (nonlinear integer arithmetic, formula may have quantifiers).", mk_is_nia_probe());
ADD_PROBE("is-nra", "true if the goal is in NRA (nonlinear real arithmetic, formula may have quantifiers).", mk_is_nra_probe());
}

View file

@ -0,0 +1,24 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
install_tactics.h
Abstract:
Install tactics in the SMT 2.0 frontend.
Author:
Leonardo (leonardo) 2012-02-19
Notes:
--*/
#ifndef _INSTALL_TACTICS_H_
#define _INSTALL_TACTICS_H_
class tactic_manager;
void install_tactics(tactic_manager & ctx);
#endif

View file

@ -0,0 +1,104 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
smt_strategic_solver.h
Abstract:
Create a strategic solver with tactic for all main logics
used in SMT.
Author:
Leonardo (leonardo) 2012-02-19
Notes:
--*/
#include"cmd_context.h"
#include"ni_solver.h"
#include"strategic_solver.h"
#include"qfbv_tactic.h"
#include"qflia_tactic.h"
#include"qfnia_tactic.h"
#include"qfnra_tactic.h"
#include"qfuf_tactic.h"
#include"qflra_tactic.h"
#include"quant_tactics.h"
#include"qfauflia_tactic.h"
#include"qfaufbv_tactic.h"
#include"qfufbv_tactic.h"
#include"qfidl_tactic.h"
#include"default_tactic.h"
#include"ufbv_strategy.h"
#include"st2tactic.h"
#include"qffpa_tactic.h"
#define MK_ST2TACTIC_FACTORY(NAME, ST) \
class NAME : public tactic_factory { \
public: \
virtual ~NAME() {} \
virtual tactic * operator()(ast_manager & m, params_ref const & p) { return st2tactic(ST); } \
};
MK_ST2TACTIC_FACTORY(ufbv_fct, mk_ufbv_strategy(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfuf_fct, mk_qfuf_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfidl_fct, mk_qfidl_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfauflia_fct, mk_qfauflia_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(auflia_fct, mk_auflia_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(auflira_fct, mk_auflira_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(aufnira_fct, mk_aufnira_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(ufnia_fct, mk_ufnia_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(uflra_fct, mk_uflra_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(lra_fct, mk_lra_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfbv_fct, mk_qfbv_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(default_fct, mk_default_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfaufbv_fct, mk_qfaufbv_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qflra_fct, mk_qflra_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qflia_fct, mk_qflia_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfufbv_fct, mk_qfufbv_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfnia_fct, mk_qfnia_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qfnra_fct, mk_qfnra_tactic(m, p));
MK_SIMPLE_TACTIC_FACTORY(qffpa_fct, mk_qffpa_tactic(m, p));
static void init(strategic_solver * s) {
s->set_default_tactic(alloc(default_fct));
s->set_tactic_for(symbol("QF_UF"), alloc(qfuf_fct));
s->set_tactic_for(symbol("QF_BV"), alloc(qfbv_fct));
s->set_tactic_for(symbol("QF_IDL"), alloc(qfidl_fct));
s->set_tactic_for(symbol("QF_LIA"), alloc(qflia_fct));
s->set_tactic_for(symbol("QF_LRA"), alloc(qflra_fct));
s->set_tactic_for(symbol("QF_NIA"), alloc(qfnia_fct));
s->set_tactic_for(symbol("QF_NRA"), alloc(qfnra_fct));
s->set_tactic_for(symbol("QF_AUFLIA"), alloc(qfauflia_fct));
s->set_tactic_for(symbol("QF_AUFBV"), alloc(qfaufbv_fct));
s->set_tactic_for(symbol("QF_ABV"), alloc(qfaufbv_fct));
s->set_tactic_for(symbol("QF_UFBV"), alloc(qfufbv_fct));
s->set_tactic_for(symbol("AUFLIA"), alloc(auflia_fct));
s->set_tactic_for(symbol("AUFLIRA"), alloc(auflira_fct));
s->set_tactic_for(symbol("AUFNIRA"), alloc(aufnira_fct));
s->set_tactic_for(symbol("UFNIA"), alloc(ufnia_fct));
s->set_tactic_for(symbol("UFLRA"), alloc(uflra_fct));
s->set_tactic_for(symbol("LRA"), alloc(lra_fct));
s->set_tactic_for(symbol("UFBV"), alloc(ufbv_fct));
s->set_tactic_for(symbol("BV"), alloc(ufbv_fct));
s->set_tactic_for(symbol("QF_FPA"), alloc(qffpa_fct));
}
solver * mk_smt_strategic_solver(cmd_context & ctx) {
strategic_solver * s = alloc(strategic_solver_cmd, ctx);
s->set_inc_solver(mk_quasi_incremental_smt_solver(ctx));
init(s);
return s;
}
solver * mk_smt_strategic_solver(bool force_tactic) {
strategic_solver * s = alloc(strategic_solver_api);
s->force_tactic(force_tactic);
s->set_inc_solver(mk_default_solver());
init(s);
return s;
}

View file

@ -0,0 +1,29 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
smt_strategic_solver.h
Abstract:
Create a strategic solver with tactic for all main logics
used in SMT.
Author:
Leonardo (leonardo) 2012-02-19
Notes:
--*/
#ifndef _SMT_STRATEGIC_SOLVER_H_
#define _SMT_STRATEGIC_SOLVER_H_
class cmd_context;
// Create a strategic solver for the SMT 2.0 frontend.
solver * mk_smt_strategic_solver(cmd_context & ctx);
// Create a strategic solver for the Z3 API
solver * mk_smt_strategic_solver(bool force_tactic=false);
#endif

View file

@ -0,0 +1,284 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
ctx_solver_simplify_tactic.cpp
Abstract:
Context simplifier for propagating solver assignments.
Author:
Nikolaj (nbjorner) 2012-3-6
Notes:
--*/
#include"ctx_solver_simplify_tactic.h"
#include"arith_decl_plugin.h"
#include"front_end_params.h"
#include"smt_solver.h"
#include"ast_pp.h"
#include"mk_simplified_app.h"
class ctx_solver_simplify_tactic : public tactic {
ast_manager& m;
params_ref m_params;
front_end_params m_front_p;
smt::solver m_solver;
arith_util m_arith;
mk_simplified_app m_mk_app;
func_decl_ref m_fn;
unsigned m_num_steps;
public:
ctx_solver_simplify_tactic(ast_manager & m, params_ref const & p = params_ref()):
m(m), m_params(p), m_solver(m, m_front_p), m_arith(m), m_mk_app(m), m_fn(m), m_num_steps(0) {
sort* i_sort = m_arith.mk_int();
m_fn = m.mk_func_decl(symbol(0xbeef101), i_sort, m.mk_bool_sort());
}
virtual tactic * translate(ast_manager & m) {
return alloc(ctx_solver_simplify_tactic, m, m_params);
}
virtual ~ctx_solver_simplify_tactic() {}
virtual void updt_params(params_ref const & p) {
m_solver.updt_params(p);
}
virtual void collect_param_descrs(param_descrs & r) {
m_solver.collect_param_descrs(r);
}
virtual void collect_statistics(statistics & st) const {
st.update("solver-simplify-steps", m_num_steps);
}
virtual void reset_statistics() { m_num_steps = 0; }
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
reduce(*(in.get()));
in->inc_depth();
result.push_back(in.get());
}
virtual void cleanup() {
reset_statistics();
m_solver.reset();
}
protected:
virtual void set_cancel(bool f) {
m_solver.set_cancel(f);
}
void reduce(goal& g) {
SASSERT(g.is_well_sorted());
bool proofs_enabled = g.proofs_enabled();
m_num_steps = 0;
expr_ref fml(m);
tactic_report report("ctx-solver-simplify", g);
unsigned sz = g.size();
if (g.inconsistent())
return;
ptr_vector<expr> fmls;
g.get_formulas(fmls);
fml = m.mk_and(fmls.size(), fmls.c_ptr());
reduce(fml);
g.reset();
g.assert_expr(fml, 0, 0);
IF_VERBOSE(TACTIC_VERBOSITY_LVL, verbose_stream() << "(ctx-solver-simplify :num-steps " << m_num_steps << ")\n";);
SASSERT(g.is_well_sorted());
}
void reduce(expr_ref& result){
SASSERT(m.is_bool(result));
ptr_vector<expr> todo;
ptr_vector<expr> names;
svector<bool> is_checked;
svector<unsigned> parent_ids, self_ids;
expr_ref_vector fresh_vars(m), trail(m);
expr_ref res(m);
obj_map<expr,std::pair<unsigned, expr*> > cache;
unsigned id = 1;
expr* n = m.mk_app(m_fn, m_arith.mk_numeral(rational(id++), true));
expr* n2, *fml;
unsigned path_id = 0, self_pos = 0;
app * a;
unsigned sz;
std::pair<unsigned,expr*> path_r;
ptr_vector<expr> found;
fml = result.get();
m_solver.assert_expr(m.mk_not(m.mk_iff(fml, n)));
trail.push_back(n);
todo.push_back(fml);
names.push_back(n);
is_checked.push_back(false);
parent_ids.push_back(0);
self_ids.push_back(0);
m_solver.push();
while (!todo.empty()) {
expr_ref res(m);
ptr_buffer<expr> args;
expr* e = todo.back();
unsigned pos = parent_ids.back();
n = names.back();
bool checked = is_checked.back();
if (cache.contains(e)) {
goto done;
}
if (!m.is_bool(e)) {
res = e;
goto done;
}
if (m.is_bool(e) && !checked && simplify_bool(n, res)) {
goto done;
}
if (!is_app(e)) {
res = e;
goto done;
}
a = to_app(e);
if (!is_checked.back()) {
self_ids.back() = ++path_id;
is_checked.back() = true;
}
self_pos = self_ids.back();
sz = a->get_num_args();
n2 = 0;
found.reset(); // arguments already simplified.
for (unsigned i = 0; i < sz; ++i) {
expr* arg = a->get_arg(i);
if (!m.is_bool(arg)) {
args.push_back(arg);
}
else if (cache.find(arg, path_r) && !found.contains(arg)) {
//
// This is a single traversal version of the context
// simplifier. It simplifies only the first occurrence of
// a formula with respect to the context.
//
found.push_back(arg);
if (path_r.first == self_pos) {
TRACE("ctx_solver_simplify_tactic", tout << "cached " << mk_pp(arg, m) << "\n";);
args.push_back(path_r.second);
}
else {
res = local_simplify(a, n, id, i);
TRACE("ctx_solver_simplify_tactic",
tout << "Already cached: " << path_r.first << " " << mk_pp(res, m) << "\n";);
args.push_back(arg);
}
}
else if (!n2 && !found.contains(arg)) {
n2 = m.mk_app(m_fn, m_arith.mk_numeral(rational(id++), true));
todo.push_back(arg);
parent_ids.push_back(self_pos);
self_ids.push_back(0);
names.push_back(n2);
trail.push_back(n2);
args.push_back(n2);
is_checked.push_back(false);
}
else {
args.push_back(arg);
}
}
m_mk_app(a->get_decl(), args.size(), args.c_ptr(), res);
trail.push_back(res);
// child needs to be visited.
if (n2) {
m_solver.push();
m_solver.assert_expr(m.mk_eq(res, n));
continue;
}
done:
if (res) {
cache.insert(e, std::make_pair(pos, res));
}
TRACE("ctx_solver_simplify_tactic",
tout << mk_pp(e, m) << " checked: " << checked << " cached: " << mk_pp(res?res.get():e, m) << "\n";);
todo.pop_back();
parent_ids.pop_back();
self_ids.pop_back();
names.pop_back();
is_checked.pop_back();
m_solver.pop(1);
}
VERIFY(cache.find(fml, path_r));
result = path_r.second;
}
bool simplify_bool(expr* n, expr_ref& res) {
m_solver.push();
m_solver.assert_expr(n);
lbool is_sat = m_solver.check();
m_solver.pop(1);
if (is_sat == l_false) {
res = m.mk_true();
return true;
}
m_solver.push();
m_solver.assert_expr(m.mk_not(n));
is_sat = m_solver.check();
m_solver.pop(1);
if (is_sat == l_false) {
res = m.mk_false();
return true;
}
return false;
}
expr_ref local_simplify(app* a, expr* n, unsigned& id, unsigned index) {
SASSERT(index < a->get_num_args());
SASSERT(m.is_bool(a->get_arg(index)));
expr_ref n2(m), result(m);
n2 = m.mk_app(m_fn, m_arith.mk_numeral(rational(id++), true));
ptr_buffer<expr> args;
for (unsigned i = 0; i < a->get_num_args(); ++i) {
if (i == index) {
args.push_back(n2);
}
else {
args.push_back(a->get_arg(i));
}
}
m_mk_app(a->get_decl(), args.size(), args.c_ptr(), result);
m_solver.push();
m_solver.assert_expr(m.mk_eq(result, n));
if (!simplify_bool(n2, result)) {
result = a;
}
m_solver.pop(1);
return result;
}
};
tactic * mk_ctx_solver_simplify_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(ctx_solver_simplify_tactic, m, p));
}

View file

@ -0,0 +1,26 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
ctx_solver_simplify_tactic.h
Abstract:
Context simplifier for propagating solver assignments.
Author:
Nikolaj (nbjorner) 2012-3-6
Notes:
--*/
#ifndef _CTX_SOLVER_SIMPLIFY_TACTIC_H_
#define _CTX_SOLVER_SIMPLIFY_TACTIC_H_
#include"tactical.h"
tactic * mk_ctx_solver_simplify_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

3
src/smt/mk_database.sh Normal file
View file

@ -0,0 +1,3 @@
#!/bin/sh
dos2unix database.smt
./gen database.smt | awk 'BEGIN { print "char const * g_pattern_database =" } { print "\"" $0 "\\n\"" } END { print ";" }' > database.h

236
src/smt/ni_solver.cpp Normal file
View file

@ -0,0 +1,236 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
ni_solver.cpp
Abstract:
Wrappers for smt::solver that are non-incremental & (quasi-incremental).
Author:
Leonardo (leonardo) 2011-03-30
Notes:
--*/
#include"ni_solver.h"
#include"smt_solver.h"
#include"cmd_context.h"
class ni_smt_solver : public solver {
protected:
cmd_context & m_cmd_ctx;
smt::solver * m_context;
progress_callback * m_callback;
public:
ni_smt_solver(cmd_context & ctx):m_cmd_ctx(ctx), m_context(0), m_callback(0) {}
virtual ~ni_smt_solver() {
if (m_context != 0)
dealloc(m_context);
}
virtual void init(ast_manager & m, symbol const & logic) {
// do nothing
}
virtual void collect_statistics(statistics & st) const {
if (m_context == 0) {
return;
}
else {
m_context->collect_statistics(st);
}
}
virtual void reset() {
if (m_context != 0) {
#pragma omp critical (ni_solver)
{
dealloc(m_context);
m_context = 0;
}
}
}
virtual void assert_expr(expr * t) {
// do nothing
}
virtual void push() {
// do nothing
}
virtual void pop(unsigned n) {
// do nothing
}
virtual unsigned get_scope_level() const {
return m_cmd_ctx.num_scopes();
}
void assert_exprs() {
ptr_vector<expr>::const_iterator it = m_cmd_ctx.begin_assertions();
ptr_vector<expr>::const_iterator end = m_cmd_ctx.end_assertions();
for (; it != end; ++it) {
m_context->assert_expr(*it);
}
}
void init_solver() {
reset();
#pragma omp critical (ni_solver)
{
m_context = alloc(smt::solver, m_cmd_ctx.m(), m_cmd_ctx.params());
}
if (m_cmd_ctx.has_logic())
m_context->set_logic(m_cmd_ctx.get_logic());
if (m_callback)
m_context->set_progress_callback(m_callback);
assert_exprs();
}
virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) {
// erase current solver, and create a new one.
init_solver();
if (num_assumptions == 0) {
return m_context->setup_and_check();
}
else {
return m_context->check(num_assumptions, assumptions);
}
}
virtual void get_unsat_core(ptr_vector<expr> & r) {
SASSERT(m_context);
unsigned sz = m_context->get_unsat_core_size();
for (unsigned i = 0; i < sz; i++)
r.push_back(m_context->get_unsat_core_expr(i));
}
virtual void get_model(model_ref & m) {
SASSERT(m_context);
m_context->get_model(m);
}
virtual proof * get_proof() {
SASSERT(m_context);
return m_context->get_proof();
}
virtual std::string reason_unknown() const {
SASSERT(m_context);
return m_context->last_failure_as_string();
}
virtual void get_labels(svector<symbol> & r) {
SASSERT(m_context);
buffer<symbol> tmp;
m_context->get_relevant_labels(0, tmp);
r.append(tmp.size(), tmp.c_ptr());
}
virtual void set_cancel(bool f) {
#pragma omp critical (ni_solver)
{
if (m_context)
m_context->set_cancel(f);
}
}
virtual void set_progress_callback(progress_callback * callback) {
m_callback = callback;
if (m_context)
m_context->set_progress_callback(callback);
}
virtual void collect_param_descrs(param_descrs & r) {
smt::solver::collect_param_descrs(r);
}
};
solver * mk_non_incremental_smt_solver(cmd_context & ctx) {
return alloc(ni_smt_solver, ctx);
}
class qi_smt_solver : public ni_smt_solver {
bool m_inc_mode;
public:
qi_smt_solver(cmd_context & ctx):ni_smt_solver(ctx), m_inc_mode(false) {}
virtual ~qi_smt_solver() {}
virtual void init(ast_manager & m, symbol const & logic) {
if (m_inc_mode) {
init_solver();
m_inc_mode = true;
}
}
virtual void reset() {
ni_smt_solver::reset();
m_inc_mode = false;
}
void switch_to_inc() {
if (!m_inc_mode) {
init_solver();
m_inc_mode = true;
}
SASSERT(m_inc_mode);
}
virtual void assert_expr(expr * t) {
if (m_context != 0 && !m_inc_mode) {
// solver was already created to solve a check_sat query...
switch_to_inc();
}
if (m_inc_mode) {
SASSERT(m_context);
m_context->assert_expr(t);
}
}
virtual void push() {
switch_to_inc();
SASSERT(m_context);
m_context->push();
SASSERT(m_inc_mode);
}
virtual void pop(unsigned n) {
switch_to_inc();
SASSERT(m_context);
m_context->pop(n);
SASSERT(m_inc_mode);
}
virtual unsigned get_scope_level() const {
if (!m_inc_mode)
return 0;
else
return m_context->get_scope_level();
}
virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) {
if (!m_inc_mode) {
lbool r = ni_smt_solver::check_sat(num_assumptions, assumptions);
SASSERT(!m_inc_mode);
return r;
}
else {
return m_context->check(num_assumptions, assumptions);
}
}
};
solver * mk_quasi_incremental_smt_solver(cmd_context & ctx) {
return alloc(qi_smt_solver, ctx);
}

30
src/smt/ni_solver.h Normal file
View file

@ -0,0 +1,30 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
ni_solver.h
Abstract:
Wrappers for smt::context that are non-incremental & (quasi-incremental).
Author:
Leonardo (leonardo) 2011-03-30
Notes:
--*/
#ifndef _NI_SOLVER_H_
#define _NI_SOLVER_H_
#include"solver.h"
class cmd_context;
// Creates a solver that restarts from scratch for every call to check_sat
solver * mk_non_incremental_smt_solver(cmd_context & ctx);
// Creates a solver that restarts from scratch for the first call to check_sat, and then moves to incremental behavior.
solver * mk_quasi_incremental_smt_solver(cmd_context & ctx);
#endif

View file

@ -0,0 +1,493 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
ufbv_strategy.cpp
Abstract:
General purpose strategy for UFBV benchmarks.
Author:
Christoph (cwinter) 2011-07-28
Notes:
--*/
#include"assertion_set_rewriter.h"
#include"smt_solver_strategy.h"
#include"nnf.h"
#include"der_strategy.h"
#include"distribute_forall.h"
#include"macro_finder.h"
#include"arith_simplifier_plugin.h"
#include"bv_simplifier_plugin.h"
#include"demodulator.h"
#include"quasi_macros.h"
#include"reduce_args.h"
#include"ufbv_strategy.h"
#include"shallow_context_simplifier.h"
#include"gaussian_elim.h"
#include"elim_var_model_converter.h"
#include"ast_smt2_pp.h"
// --- TRACE STRATEGY
#ifdef _TRACE
class trace_as_st : public assertion_set_strategy {
ast_manager & m;
const char * tag;
public:
trace_as_st(ast_manager & m, const char * tag) : m(m),tag(tag) { }
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
TRACE(tag, { s.display(tout); });
}
virtual void cleanup() {}
};
#endif
as_st * mk_trace_as(ast_manager & m, const char * tag) {
#ifdef _TRACE
return alloc(trace_as_st, m, tag);
#else
return noop();
#endif
}
as_st * mk_der_fp(ast_manager & m, params_ref const & p) {
return repeat(and_then(mk_der(m), mk_simplifier(m, p)));
}
// --- DISTRIBUTE-FORALL STRATEGY
class distribute_forall_st : public assertion_set_strategy {
ast_manager & m;
params_ref m_params;
bool m_produce_models;
bool m_cancel;
public:
distribute_forall_st(ast_manager & m, params_ref const & p = params_ref()) : m(m),m_params(p),m_produce_models(false),m_cancel(false) { }
virtual ~distribute_forall_st() {}
virtual void updt_params(params_ref const & p) {
m_produce_models = p.get_bool(":produce-models", false);
}
static void get_param_descrs(param_descrs & r) {
insert_produce_models(r);
}
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
as_st_report report("distribute-forall", s);
basic_simplifier_plugin bsimp(m);
bsimp.set_eliminate_and(true);
distribute_forall apply_dist(m, bsimp);
for (unsigned i = 0; i < s.size(); i++) {
if (m_cancel)
throw strategy_exception(STE_CANCELED_MSG);
expr * n = s.form(i);
expr_ref r(m);
apply_dist(n, r);
if (n != r.get()) {
if (m.proofs_enabled()) {
proof * old_pr = s.pr(i);
proof_ref new_pr(m);
new_pr = m.mk_rewrite_star(n, r, 0, 0);
new_pr = m.mk_modus_ponens(old_pr, new_pr);
s.update(i, r, new_pr);
}
else
s.update(i, r, 0);
}
}
mc = 0; // CMW: No model conversion necessary; variables and functions don't change.
TRACE("distribute_forall", s.display(tout););
}
virtual void cleanup() {}
protected:
virtual void set_cancel(bool f) { m_cancel = f; }
};
as_st * mk_distribute_forall(ast_manager & m, params_ref const & p) {
return alloc(distribute_forall_st, m, p);
}
model_converter * macro_manager2model_converter(macro_manager const & mm) {
elim_var_model_converter * mc = alloc(elim_var_model_converter, mm.get_manager());
unsigned num = mm.get_num_macros();
for (unsigned i = 0; i < num; i++) {
expr_ref f_interp(mm.get_manager());
func_decl * f = mm.get_macro_interpretation(i, f_interp);
mc->insert(f, f_interp);
}
return mc;
}
// --- MACRO FINDER STRATEGY
class macro_finder_st : public assertion_set_strategy {
ast_manager & m;
params_ref m_params;
bool m_produce_models;
bool m_cancel;
bool m_elim_and;
public:
macro_finder_st(ast_manager & m, params_ref const & p = params_ref(), bool elim_and=false) : m(m),m_params(p),m_produce_models(false),m_cancel(false),m_elim_and(elim_and) { }
virtual ~macro_finder_st() {}
virtual void updt_params(params_ref const & p) {
m_produce_models = p.get_bool(":produce-models", false);
}
static void get_param_descrs(param_descrs & r) {
insert_produce_models(r);
}
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
TRACE("debug_ids", m.display_free_ids(tout); tout << "\n";);
as_st_report report("macro-finder", s);
simplifier simp(m);
basic_simplifier_plugin * bsimp = alloc(basic_simplifier_plugin, m);
bsimp->set_eliminate_and(m_elim_and);
simp.register_plugin(bsimp);
arith_simplifier_params a_params;
arith_simplifier_plugin * asimp = alloc(arith_simplifier_plugin, m, *bsimp, a_params);
simp.register_plugin(asimp);
bv_simplifier_params bv_params;
bv_simplifier_plugin * bvsimp = alloc(bv_simplifier_plugin, m, *bsimp, bv_params);
simp.register_plugin(bvsimp);
macro_manager mm(m, simp);
macro_finder mf(m, mm);
expr_ref_vector forms(m), new_forms(m);
proof_ref_vector proofs(m), new_proofs(m);
for (unsigned i = 0; i < s.size(); i++) {
forms.push_back(s.form(i));
proofs.push_back(s.pr(i));
}
mf(forms.size(), forms.c_ptr(), proofs.c_ptr(), new_forms, new_proofs);
s.reset();
for (unsigned i = 0; i < new_forms.size(); i++) {
s.assert_expr(new_forms.get(i), (m.proofs_enabled()) ? new_proofs.get(i) : 0);
}
mc = macro_manager2model_converter(mm);
TRACE("debug_ids", m.display_free_ids(tout); tout << "\n";);
}
virtual void cleanup() {}
protected:
virtual void set_cancel(bool f) { m_cancel = f; }
};
as_st * mk_macro_finder(ast_manager & m, params_ref const & p, bool elim_and=false) {
return alloc(macro_finder_st, m, p, elim_and);
}
// --- DEMODULATOR STRATEGY
class demodulator_st : public assertion_set_strategy {
ast_manager & m;
params_ref m_params;
bool m_produce_models;
bool m_cancel;
public:
demodulator_st(ast_manager & m, params_ref const & p = params_ref()) : m(m),m_params(p),m_produce_models(false),m_cancel(false) { }
virtual ~demodulator_st() {}
virtual void updt_params(params_ref const & p) {
m_produce_models = p.get_bool(":produce-models", false);
}
static void get_param_descrs(param_descrs & r) {
insert_produce_models(r);
}
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
as_st_report report("demodulator", s);
basic_simplifier_plugin bsimp(m);
bsimp.set_eliminate_and(true);
demodulator dem(m, bsimp);
expr_ref_vector forms(m), new_forms(m);
proof_ref_vector proofs(m), new_proofs(m);
for (unsigned i = 0; i < s.size(); i++) {
forms.push_back(s.form(i));
proofs.push_back(s.pr(i));
}
dem(forms.size(), forms.c_ptr(), proofs.c_ptr(), new_forms, new_proofs);
s.reset();
for (unsigned i = 0; i < new_forms.size(); i++) {
s.assert_expr(new_forms.get(i), (m.proofs_enabled()) ? new_proofs.get(i) : 0);
}
mc = 0; // CMW: The demodulator could potentially remove all references to a variable.
}
virtual void cleanup() {}
protected:
virtual void set_cancel(bool f) { m_cancel = f; }
};
as_st * mk_demodulator(ast_manager & m, params_ref const & p) {
return alloc(demodulator_st, m, p);
}
// --- QUASI-MACROS STRATEGY
class quasi_macros_st : public assertion_set_strategy {
ast_manager & m;
params_ref m_params;
bool m_produce_models;
bool m_cancel;
public:
quasi_macros_st(ast_manager & m, params_ref const & p = params_ref()) : m(m),m_params(p),m_produce_models(false),m_cancel(false) { }
virtual ~quasi_macros_st() {}
virtual void updt_params(params_ref const & p) {
m_produce_models = p.get_bool(":produce-models", false);
}
static void get_param_descrs(param_descrs & r) {
insert_produce_models(r);
}
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
as_st_report report("quasi-macros", s);
simplifier simp(m);
basic_simplifier_plugin * bsimp = alloc(basic_simplifier_plugin, m);
bsimp->set_eliminate_and(true);
simp.register_plugin(bsimp);
arith_simplifier_params a_params;
arith_simplifier_plugin * asimp = alloc(arith_simplifier_plugin, m, *bsimp, a_params);
simp.register_plugin(asimp);
bv_simplifier_params bv_params;
bv_simplifier_plugin * bvsimp = alloc(bv_simplifier_plugin, m, *bsimp, bv_params);
simp.register_plugin(bvsimp);
macro_manager mm(m, simp);
quasi_macros qm(m, mm, *bsimp, simp);
bool more = true;
expr_ref_vector forms(m), new_forms(m);
proof_ref_vector proofs(m), new_proofs(m);
for (unsigned i = 0; i < s.size(); i++) {
forms.push_back(s.form(i));
proofs.push_back(s.pr(i));
}
while (more) { // CMW: This is applied until fixpoint; should we have a fixpoint_as_st for that?
if (m_cancel)
throw strategy_exception(STE_CANCELED_MSG);
new_forms.reset();
new_proofs.reset();
more = qm(forms.size(), forms.c_ptr(), proofs.c_ptr(), new_forms, new_proofs);
forms.swap(new_forms);
proofs.swap(new_proofs);
}
s.reset();
for (unsigned i = 0; i < forms.size(); i++) {
s.assert_expr(forms.get(i), (m.proofs_enabled()) ? proofs.get(i) : 0);
}
mc = macro_manager2model_converter(mm);
}
virtual void cleanup() {}
protected:
virtual void set_cancel(bool f) { m_cancel = f; }
};
as_st * mk_quasi_macros(ast_manager & m, params_ref const & p) {
return alloc(quasi_macros_st, m, p);
}
// --- ELIMINATE AND STRATEGY
as_st * mk_eliminate_and(ast_manager & m, params_ref const & p) {
params_ref elim_and_p;
elim_and_p.set_bool(":elim-and", true);
return using_params(mk_simplifier(m, p), elim_and_p);
}
// --- DISPLAY ASSERTION SET STRATEGY
// CMW: This was a temporary hack. Use cmd_context to print benchmark files.
//class display_as_st : public assertion_set_strategy {
// ast_manager & m;
// params_ref m_params;
//
//public:
// display_as_st (ast_manager & m, params_ref const & p = params_ref()) : m(m),m_params(p) { }
// virtual ~display_as_st() {}
//
// virtual void updt_params(params_ref const & p) {}
//
// static void get_param_descrs(param_descrs & r) {}
//
// virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
//
// struct find_uf_proc {
// ast_manager & m_manager;
// obj_hashtable<func_decl> & m_fds;
//
// find_uf_proc(ast_manager & m, obj_hashtable<func_decl> & fds):
// m_manager(m),
// m_fds(fds) {
// }
//
// void operator()(var * n) {}
//
// void operator()(quantifier * n) {}
//
// void operator()(app * n) {
// func_decl * d = n->get_decl();
// if (d->get_family_id() != null_family_id)
// return; // ignore interpreted symbols
// m_fds.insert(d);
// }
// };
//
// virtual void operator()(assertion_set & s, model_converter_ref & mc) {
// std::cerr << "(set-info :source ||)" << std::endl;
// std::cerr << "(set-info :status unknown)" << std::endl;
// std::cerr << "(set-logic UFBV)" << std::endl;
//
// // Find functions
// obj_hashtable<func_decl> fds;
// find_uf_proc proc(m, fds);
// unsigned sz = s.size();
// for (unsigned i = 0; i < sz; i++) {
// expr_fast_mark1 visited;
// quick_for_each_expr(proc, visited, s.form(i));
// }
//
// // print functions
// for (obj_hashtable<func_decl>::iterator it = fds.begin(); it != fds.end(); it++) {
// // How do we print (declare-fun ...) ?
// std::cerr << mk_ismt2_pp(*it, m) << std::endl;
// }
//
// // print assertions
// for (unsigned i = 0; i < s.size(); i++) {
// std::cerr << "(assert ";
// std::cerr << mk_ismt2_pp(s.form(i), m);
// std::cerr << ")" << std::endl;
// }
// std::cerr << "(check-sat)" << std::endl;
// }
//
// virtual void cleanup() {}
//protected:
// virtual void set_cancel(bool f) {}
//};
//
//as_st * mk_display_as(ast_manager & m, params_ref const & p) {
// return alloc(display_as_st, m, p);
//}
class debug_ids_st : public assertion_set_strategy {
ast_manager & m;
struct proc {
ast_manager & m;
proc(ast_manager & _m):m(_m) {}
void operator()(var * n) { TRACE_CODE(tout << n->get_id() << " ";); }
void operator()(app * n) { TRACE_CODE(tout << n->get_id() << " ";); }
void operator()(quantifier * n) { TRACE_CODE(tout << n->get_id() << " ";); }
};
public:
debug_ids_st(ast_manager & _m):m(_m) {}
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
mc = 0;
TRACE("debug_ids",
tout << "free ids:\n"; m.display_free_ids(tout); tout << "\n";
proc p(m);
tout << "assertion_set ids:\n";
for_each_expr_as(p, s);
tout << "\n";);
}
virtual void cleanup() {}
};
// --- UFBV STRATEGY
as_st * mk_preprocessor(ast_manager & m, params_ref const & p) {
return and_then(mk_trace_as(m, "ufbv_pre"),
and_then( mk_simplifier(m, p),
mk_constant_propagation(m, p),
and_then(mk_macro_finder(m, p, false), mk_simplifier(m, p)),
and_then(mk_snf(p), mk_simplifier(m, p)),
mk_eliminate_and(m, p),
mk_eq_solver(m, p),
and_then(mk_der_fp(m, p), mk_simplifier(m, p)),
and_then(mk_distribute_forall(m, p), mk_simplifier(m, p))
),
and_then( and_then(mk_reduce_args(m, p), mk_simplifier(m, p)),
and_then(mk_macro_finder(m, p, true), mk_simplifier(m, p)),
and_then(mk_demodulator(m, p), mk_simplifier(m, p)),
and_then(mk_quasi_macros(m, p), mk_simplifier(m, p)),
and_then(mk_der_fp(m, p), mk_simplifier(m, p)),
mk_simplifier(m, p)),
mk_trace_as(m, "ufbv_post"));
}
as_st * mk_ufbv_strategy(ast_manager & m, params_ref const & p) {
params_ref main_p(p);
main_p.set_bool(":mbqi", true);
main_p.set_uint(":mbqi-max-iterations", -1);
main_p.set_bool(":elim-and", true);
main_p.set_bool(":solver", true);
// this prints the skolemized version of a benchmark
// as_st * st = and_then(mk_skolemizer(m, main_p), mk_display_as(m, main_p));
as_st * st = and_then(repeat(mk_preprocessor(m, main_p), 2),
alloc(debug_ids_st, m),
using_params(mk_smt_solver(false), main_p));
st->updt_params(p);
return st;
}

View file

@ -0,0 +1,28 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
ufbv_strategy.h
Abstract:
General purpose strategy for UFBV benchmarks.
Author:
Christoph (cwinter) 2011-07-28
Notes:
--*/
#ifndef _UFBV_STRATEGY_H_
#define _UFBV_STRATEGY_H_
#include"assertion_set_strategy.h"
as_st * mk_ufbv_strategy(ast_manager & m, params_ref const & p);
MK_SIMPLE_ST_FACTORY(ufbv_stf, mk_ufbv_strategy(m, p));
#endif