3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 01:25:31 +00:00

Reorganizing the code

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2012-10-20 20:53:33 -07:00
parent 6bdb009c3e
commit 2b8fb6c718
13 changed files with 7 additions and 7 deletions

206
src/model/array_factory.cpp Normal file
View file

@ -0,0 +1,206 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
array_factory.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-10-28.
Revision History:
--*/
#include"array_factory.h"
#include"array_decl_plugin.h"
#include"proto_model.h"
#include"func_interp.h"
#include"ast_pp.h"
func_decl * mk_aux_decl_for_array_sort(ast_manager & m, sort * s) {
ptr_buffer<sort> domain;
sort * range = get_array_range(s);
unsigned arity = get_array_arity(s);
for (unsigned i = 0; i < arity; i++) {
domain.push_back(get_array_domain(s, i));
}
return m.mk_fresh_func_decl(symbol::null, symbol::null, arity, domain.c_ptr(), range);
}
array_factory::array_factory(ast_manager & m, proto_model & md):
struct_factory(m, m.get_family_id("array"), md) {
}
/**
\brieft Return as-array[f] where f is a fresh function symbol with the right domain and range for the array sort s.
Store in fi the function interpretation for f.
*/
expr * array_factory::mk_array_interp(sort * s, func_interp * & fi) {
func_decl * f = mk_aux_decl_for_array_sort(m_manager, s);
fi = alloc(func_interp, m_manager, get_array_arity(s));
m_model.register_decl(f, fi);
parameter p[1] = { parameter(f) };
expr * val = m_manager.mk_app(get_family_id(), OP_AS_ARRAY, 1, p);
register_value(val);
return val;
}
void array_factory::get_some_args_for(sort * s, ptr_buffer<expr> & args) {
unsigned arity = get_array_arity(s);
for (unsigned i = 0; i < arity; i++) {
sort * d = get_array_domain(s, i);
expr * a = m_model.get_some_value(d);
args.push_back(a);
}
}
expr * array_factory::get_some_value(sort * s) {
TRACE("array_factory", tout << mk_pp(s, m_manager) << "\n";);
value_set * set = 0;
if (m_sort2value_set.find(s, set) && !set->empty())
return *(set->begin());
func_interp * fi;
expr * val = mk_array_interp(s, fi);
ptr_buffer<expr> args;
get_some_args_for(s, args);
fi->insert_entry(args.c_ptr(), m_model.get_some_value(get_array_range(s)));
return val;
}
bool array_factory::mk_two_diff_values_for(sort * s) {
DEBUG_CODE({
value_set * set = 0;
SASSERT(!m_sort2value_set.find(s, set) || set->size() == 0);
});
expr_ref r1(m_manager);
expr_ref r2(m_manager);
sort * range = get_array_range(s);
if (!m_model.get_some_values(range, r1, r2))
return false; // failed... the range is probably unit.
ptr_buffer<expr> args;
get_some_args_for(s, args);
func_interp * fi1;
func_interp * fi2;
mk_array_interp(s, fi1);
mk_array_interp(s, fi2);
fi1->insert_entry(args.c_ptr(), r1);
fi2->insert_entry(args.c_ptr(), r2);
DEBUG_CODE({
value_set * set = 0;
SASSERT(m_sort2value_set.find(s, set) && set->size() == 2);
});
return true;
}
bool array_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
value_set * set = 0;
if (!m_sort2value_set.find(s, set) || set->size() == 0) {
if (!mk_two_diff_values_for(s))
return false;
}
m_sort2value_set.find(s, set);
SASSERT(set != 0);
SASSERT(set->size() > 0);
if (set->size() == 1) {
v1 = *(set->begin());
v2 = get_fresh_value(s);
return v2.get() != 0;
}
else {
SASSERT(set->size() >= 2);
value_set::iterator it = set->begin();
v1 = *it;
++it;
v2 = *it;
return true;
}
}
//
// TODO: I have to check if the following procedure is really correct.
// I'm supporting partial arrays where the "else" can be set later by the model_finder or model classes.
// Projection functions may be also used.
//
// If projections are not used, then the following code should work if the "else" of a partial array
// is set with the result of some entry.
//
expr * array_factory::get_fresh_value(sort * s) {
value_set * set = get_value_set(s);
if (set->empty()) {
// easy case
return get_some_value(s);
}
sort * range = get_array_range(s);
expr * range_val = m_model.get_fresh_value(range);
if (range_val != 0) {
// easy case
func_interp * fi;
expr * val = mk_array_interp(s, fi);
ptr_buffer<expr> args;
get_some_args_for(s, args);
fi->insert_entry(args.c_ptr(), range_val);
return val;
}
else {
TRACE("array_factory_bug", tout << "array fresh value: using fresh index, range: " << mk_pp(range, m_manager) << "\n";);
expr_ref v1(m_manager);
expr_ref v2(m_manager);
if (m_model.get_some_values(range, v1, v2)) {
// Claim: A is fresh if A[i1] = v1 and A[i2] = v2 where i1 and i2 are fresh values,
// and v1 and v2 are distinct.
//
// Proof: let assume there is an Array A' such that A' = A.
// Then A[i1] == A'[i1] and A[i2] == A'[i2]. Since, i1 and i2 are fresh,
// A' does not have an entry for i1 or i2, So A'[i1] == A'[i2] == A'.m_else.
// Thus, A[i1] == A[i2] which is a contradiction since v1 != v2 and A[i1] = v1 and A[i2] = v2.
TRACE("array_factory_bug", tout << "v1: " << mk_pp(v1, m_manager) << " v2: " << mk_pp(v2, m_manager) << "\n";);
ptr_buffer<expr> args1;
ptr_buffer<expr> args2;
bool found = false;
unsigned arity = get_array_arity(s);
for (unsigned i = 0; i < arity; i++) {
sort * d = get_array_domain(s, i);
if (!found) {
expr * arg1 = m_model.get_fresh_value(d);
expr * arg2 = m_model.get_fresh_value(d);
if (arg1 != 0 && arg2 != 0) {
found = true;
args1.push_back(arg1);
args2.push_back(arg2);
continue;
}
}
expr * arg = m_model.get_some_value(d);
args1.push_back(arg);
args2.push_back(arg);
}
if (found) {
func_interp * fi;
expr * val = mk_array_interp(s, fi);
fi->insert_entry(args1.c_ptr(), v1);
fi->insert_entry(args2.c_ptr(), v2);
return val;
}
}
}
// TODO: use more expensive procedures to create a fresh array value.
// Example: track the values used in the domain.
// Remark: in the current implementation, this function
// will never fail, since if a type is finite, then
// type_pred will be applied and get_fresh_value will not
// need to be used.
// failed to create a fresh array value
TRACE("array_factory_bug", tout << "failed to build fresh array value\n";);
return 0;
}

45
src/model/array_factory.h Normal file
View file

@ -0,0 +1,45 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
array_factory.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-10-28.
Revision History:
--*/
#ifndef _ARRAY_FACTORY_H_
#define _ARRAY_FACTORY_H_
#include"struct_factory.h"
class func_interp;
func_decl * mk_aux_decl_for_array_sort(ast_manager & m, sort * s);
class array_factory : public struct_factory {
expr * mk_array_interp(sort * s, func_interp * & fi);
void get_some_args_for(sort * s, ptr_buffer<expr> & args);
bool mk_two_diff_values_for(sort * s);
public:
array_factory(ast_manager & m, proto_model & md);
virtual ~array_factory() {}
virtual expr * get_some_value(sort * s);
virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2);
virtual expr * get_fresh_value(sort * s);
};
#endif /* _ARRAY_FACTORY_H_ */

View file

@ -0,0 +1,215 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
datatype_factory.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-11-06.
Revision History:
--*/
#include"datatype_factory.h"
#include"proto_model.h"
#include"ast_pp.h"
#include"ast_ll_pp.h"
datatype_factory::datatype_factory(ast_manager & m, proto_model & md):
struct_factory(m, m.get_family_id("datatype"), md),
m_util(m) {
}
expr * datatype_factory::get_some_value(sort * s) {
value_set * set = 0;
if (m_sort2value_set.find(s, set) && !set->empty())
return *(set->begin());
func_decl * c = m_util.get_non_rec_constructor(s);
ptr_vector<expr> args;
unsigned num = c->get_arity();
for (unsigned i = 0; i < num; i++) {
args.push_back(m_model.get_some_value(c->get_domain(i)));
}
expr * r = m_manager.mk_app(c, args.size(), args.c_ptr());
register_value(r);
TRACE("datatype_factory", tout << mk_pp(r, m_util.get_manager()) << "\n";);
return r;
}
/**
\brief Return the last fresh (or almost) fresh value of sort s.
*/
expr * datatype_factory::get_last_fresh_value(sort * s) {
expr * val = 0;
if (m_last_fresh_value.find(s, val))
return val;
value_set * set = get_value_set(s);
if (set->empty())
val = get_some_value(s);
else
val = *(set->begin());
if (m_util.is_recursive(s))
m_last_fresh_value.insert(s, val);
return val;
}
/**
\brief Create an almost fresh value. If s is recursive, then the result is not 0.
It also updates m_last_fresh_value
*/
expr * datatype_factory::get_almost_fresh_value(sort * s) {
value_set * set = get_value_set(s);
if (set->empty()) {
expr * val = get_some_value(s);
if (m_util.is_recursive(s))
m_last_fresh_value.insert(s, val);
return val;
}
// Traverse constructors, and try to invoke get_fresh_value of one of the arguments (if the argument is not a sibling datatype of s).
// If the argumet is a sibling datatype of s, then
// use get_last_fresh_value.
ptr_vector<func_decl> const * constructors = m_util.get_datatype_constructors(s);
ptr_vector<func_decl>::const_iterator it = constructors->begin();
ptr_vector<func_decl>::const_iterator end = constructors->end();
for (; it != end; ++it) {
func_decl * constructor = *it;
expr_ref_vector args(m_manager);
bool found_fresh_arg = false;
bool recursive = false;
unsigned num = constructor->get_arity();
for (unsigned i = 0; i < num; i++) {
sort * s_arg = constructor->get_domain(i);
if (!found_fresh_arg && (!m_util.is_datatype(s_arg) || !m_util.are_siblings(s, s_arg))) {
expr * new_arg = m_model.get_fresh_value(s_arg);
if (new_arg != 0) {
found_fresh_arg = true;
args.push_back(new_arg);
continue;
}
}
if (!found_fresh_arg && m_util.is_datatype(s_arg) && m_util.are_siblings(s, s_arg)) {
recursive = true;
expr * last_fresh = get_last_fresh_value(s_arg);
args.push_back(last_fresh);
}
else {
expr * some_arg = m_model.get_some_value(s_arg);
args.push_back(some_arg);
}
}
if (recursive || found_fresh_arg) {
expr * new_value = m_manager.mk_app(constructor, args.size(), args.c_ptr());
SASSERT(!found_fresh_arg || !set->contains(new_value));
register_value(new_value);
if (m_util.is_recursive(s))
m_last_fresh_value.insert(s, new_value);
return new_value;
}
}
SASSERT(!m_util.is_recursive(s));
return 0;
}
expr * datatype_factory::get_fresh_value(sort * s) {
TRACE("datatype_factory", tout << "generating fresh value for: " << s->get_name() << "\n";);
value_set * set = get_value_set(s);
// Approach 0)
// if no value for s was generated so far, then used get_some_value
if (set->empty()) {
expr * val = get_some_value(s);
if (m_util.is_recursive(s))
m_last_fresh_value.insert(s, val);
TRACE("datatype_factory", tout << "0. result: " << mk_pp(val, m_manager) << "\n";);
return val;
}
// Approach 1)
// Traverse constructors, and try to invoke get_fresh_value of one of the
// arguments (if the argument is not a sibling datatype of s).
// Two datatypes are siblings if they were defined together in the same mutually recursive definition.
ptr_vector<func_decl> const * constructors = m_util.get_datatype_constructors(s);
ptr_vector<func_decl>::const_iterator it = constructors->begin();
ptr_vector<func_decl>::const_iterator end = constructors->end();
for (; it != end; ++it) {
func_decl * constructor = *it;
expr_ref_vector args(m_manager);
bool found_fresh_arg = false;
unsigned num = constructor->get_arity();
for (unsigned i = 0; i < num; i++) {
sort * s_arg = constructor->get_domain(i);
if (!found_fresh_arg && (!m_util.is_recursive(s) || !m_util.is_datatype(s_arg) || !m_util.are_siblings(s, s_arg))) {
expr * new_arg = m_model.get_fresh_value(s_arg);
if (new_arg != 0) {
found_fresh_arg = true;
args.push_back(new_arg);
continue;
}
}
expr * some_arg = m_model.get_some_value(s_arg);
args.push_back(some_arg);
}
expr_ref new_value(m_manager);
new_value = m_manager.mk_app(constructor, args.size(), args.c_ptr());
CTRACE("datatype_factory", found_fresh_arg && set->contains(new_value), tout << mk_pp(new_value, m_manager) << "\n";);
SASSERT(!found_fresh_arg || !set->contains(new_value));
if (!set->contains(new_value)) {
register_value(new_value);
if (m_util.is_recursive(s))
m_last_fresh_value.insert(s, new_value);
TRACE("datatype_factory", tout << "1. result: " << mk_pp(new_value, m_manager) << "\n";);
return new_value;
}
}
// Approach 2)
// For recursive datatypes.
// search for constructor...
if (m_util.is_recursive(s)) {
while(true) {
TRACE("datatype_factory", tout << mk_pp(get_last_fresh_value(s), m_manager) << "\n";);
ptr_vector<func_decl> const * constructors = m_util.get_datatype_constructors(s);
ptr_vector<func_decl>::const_iterator it = constructors->begin();
ptr_vector<func_decl>::const_iterator end = constructors->end();
for (; it != end; ++it) {
func_decl * constructor = *it;
expr_ref_vector args(m_manager);
bool found_sibling = false;
unsigned num = constructor->get_arity();
for (unsigned i = 0; i < num; i++) {
sort * s_arg = constructor->get_domain(i);
if (!found_sibling && m_util.is_datatype(s_arg) && m_util.are_siblings(s, s_arg)) {
found_sibling = true;
expr * maybe_new_arg = get_almost_fresh_value(s_arg);
args.push_back(maybe_new_arg);
}
else {
expr * some_arg = m_model.get_some_value(s_arg);
args.push_back(some_arg);
}
}
if (found_sibling) {
expr_ref new_value(m_manager);
new_value = m_manager.mk_app(constructor, args.size(), args.c_ptr());
m_last_fresh_value.insert(s, new_value);
if (!set->contains(new_value)) {
register_value(new_value);
TRACE("datatype_factory", tout << "2. result: " << mk_pp(new_value, m_manager) << "\n";);
return new_value;
}
}
}
}
}
// Approach 3)
// for non-recursive datatypes.
// Search for value that was not created before.
SASSERT(!m_util.is_recursive(s));
return 0;
}

View file

@ -0,0 +1,40 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
datatype_factory.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-11-06.
Revision History:
--*/
#ifndef _DATATYPE_FACTORY_H_
#define _DATATYPE_FACTORY_H_
#include"struct_factory.h"
#include"datatype_decl_plugin.h"
class datatype_factory : public struct_factory {
datatype_util m_util;
obj_map<sort, expr *> m_last_fresh_value;
expr * get_last_fresh_value(sort * s);
expr * get_almost_fresh_value(sort * s);
public:
datatype_factory(ast_manager & m, proto_model & md);
virtual ~datatype_factory() {}
virtual expr * get_some_value(sort * s);
virtual expr * get_fresh_value(sort * s);
};
#endif /* _DATATYPE_FACTORY_H_ */

View file

@ -0,0 +1,52 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
numeral_factory.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-10-28.
Revision History:
--*/
#include"numeral_factory.h"
#include"ast_pp.h"
app * arith_factory::mk_value_core(rational const & val, sort * s) {
return m_util.mk_numeral(val, s);
}
arith_factory::arith_factory(ast_manager & m):
numeral_factory(m, m.get_family_id("arith")),
m_util(m) {
}
arith_factory::~arith_factory() {
}
app * arith_factory::mk_value(rational const & val, bool is_int) {
return numeral_factory::mk_value(val, is_int ? m_util.mk_int() : m_util.mk_real());
}
bv_factory::bv_factory(ast_manager & m):
numeral_factory(m, m.get_family_id("bv")),
m_util(m) {
}
bv_factory::~bv_factory() {
}
app * bv_factory::mk_value_core(rational const & val, sort * s) {
return m_util.mk_numeral(val, s);
}
app * bv_factory::mk_value(rational const & val, unsigned bv_size) {
return numeral_factory::mk_value(val, m_util.mk_sort(bv_size));
}

View file

@ -0,0 +1,57 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
numeral_factory.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-10-28.
Revision History:
--*/
#ifndef _NUMERAL_FACTORY_H_
#define _NUMERAL_FACTORY_H_
#include"value_factory.h"
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
class numeral_factory : public simple_factory<rational> {
public:
numeral_factory(ast_manager & m, family_id fid):simple_factory<rational>(m, fid) {}
virtual ~numeral_factory() {}
};
class arith_factory : public numeral_factory {
arith_util m_util;
virtual app * mk_value_core(rational const & val, sort * s);
public:
arith_factory(ast_manager & m);
virtual ~arith_factory();
app * mk_value(rational const & val, bool is_int);
};
class bv_factory : public numeral_factory {
bv_util m_util;
virtual app * mk_value_core(rational const & val, sort * s);
public:
bv_factory(ast_manager & m);
virtual ~bv_factory();
app * mk_value(rational const & val, unsigned bv_size);
};
#endif /* _NUMERAL_FACTORY_H_ */

View file

@ -0,0 +1,78 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
struct_factory.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-11-06.
Revision History:
--*/
#include"struct_factory.h"
#include"proto_model.h"
struct_factory::value_set * struct_factory::get_value_set(sort * s) {
value_set * set = 0;
if (!m_sort2value_set.find(s, set)) {
set = alloc(value_set);
m_sort2value_set.insert(s, set);
m_sorts.push_back(s);
m_sets.push_back(set);
}
SASSERT(set != 0);
return set;
}
struct_factory::struct_factory(ast_manager & m, family_id fid, proto_model & md):
value_factory(m, fid),
m_model(md),
m_values(m),
m_sorts(m) {
}
struct_factory::~struct_factory() {
std::for_each(m_sets.begin(), m_sets.end(), delete_proc<value_set>());
}
void struct_factory::register_value(expr * new_value) {
sort * s = m_manager.get_sort(new_value);
value_set * set = get_value_set(s);
if (!set->contains(new_value)) {
m_values.push_back(new_value);
set->insert(new_value);
}
}
bool struct_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
value_set * set = get_value_set(s);
switch (set->size()) {
case 0:
v1 = get_fresh_value(s);
v2 = get_fresh_value(s);
return v1 != 0 && v2 != 0;
case 1:
v1 = get_some_value(s);
v2 = get_fresh_value(s);
return v2 != 0;
default:
obj_hashtable<expr>::iterator it = set->begin();
v1 = *it;
++it;
v2 = *it;
return true;
}
}

View file

@ -0,0 +1,56 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
struct_factory.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-11-06.
Revision History:
--*/
#ifndef _STRUCT_FACTORY_H_
#define _STRUCT_FACTORY_H_
#include"value_factory.h"
#include"obj_hashtable.h"
class proto_model;
/**
\brief Abstract factory for structured values such as: arrays and algebraic datatypes.
*/
class struct_factory : public value_factory {
protected:
typedef obj_hashtable<expr> value_set;
typedef obj_map<sort, value_set *> sort2value_set;
proto_model & m_model;
sort2value_set m_sort2value_set;
expr_ref_vector m_values;
sort_ref_vector m_sorts;
ptr_vector<value_set> m_sets;
value_set * get_value_set(sort * s);
public:
struct_factory(ast_manager & m, family_id fid, proto_model & md);
virtual ~struct_factory();
virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2);
virtual void register_value(expr * array_value);
proto_model & get_model() { return m_model; }
};
#endif /* _STRUCT_FACTORY_H_ */