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

move value factories to model

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2019-10-16 19:48:28 -07:00
parent 5122b2da7e
commit ca498e20d1
30 changed files with 167 additions and 145 deletions

View file

@ -1,11 +1,6 @@
z3_add_component(proto_model
SOURCES
array_factory.cpp
datatype_factory.cpp
numeral_factory.cpp
proto_model.cpp
struct_factory.cpp
value_factory.cpp
COMPONENT_DEPENDENCIES
model
rewriter

View file

@ -1,214 +0,0 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
array_factory.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-10-28.
Revision History:
--*/
#include "ast/array_decl_plugin.h"
#include "ast/ast_pp.h"
#include "model/func_interp.h"
#include "smt/proto_model/array_factory.h"
#include "smt/proto_model/proto_model.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.mk_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 = nullptr;
if (m_sort2value_set.find(s, set) && !set->empty())
return *(set->begin());
func_interp * fi;
expr * val = mk_array_interp(s, fi);
#if 0
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)));
#else
fi->set_else(m_model.get_some_value(get_array_range(s)));
#endif
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 = nullptr;
if (!m_sort2value_set.find(s, set) || set->empty()) {
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() != nullptr;
}
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 != nullptr) {
// easy case
func_interp * fi;
expr * val = mk_array_interp(s, fi);
#if 0
ptr_buffer<expr> args;
get_some_args_for(s, args);
fi->insert_entry(args.c_ptr(), range_val);
#else
fi->set_else(range_val);
#endif
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 != nullptr && arg2 != nullptr) {
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 nullptr;
}

View file

@ -1,45 +0,0 @@
/*++
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 "smt/proto_model/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);
~array_factory() override {}
expr * get_some_value(sort * s) override;
bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) override;
expr * get_fresh_value(sort * s) override;
};
#endif /* ARRAY_FACTORY_H_ */

View file

@ -1,250 +0,0 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
datatype_factory.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-11-06.
Revision History:
--*/
#include "smt/proto_model/datatype_factory.h"
#include "smt/proto_model/proto_model.h"
#include "ast/ast_pp.h"
#include "ast/expr_functors.h"
datatype_factory::datatype_factory(ast_manager & m, proto_model & md):
struct_factory(m, m.mk_family_id("datatype"), md),
m_util(m) {
}
expr * datatype_factory::get_some_value(sort * s) {
value_set * set = nullptr;
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", 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 = nullptr;
if (m_last_fresh_value.find(s, val)) {
TRACE("datatype", tout << "cached fresh value: " << mk_pp(val, m_manager) << "\n";);
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;
}
bool datatype_factory::is_subterm_of_last_value(app* e) {
expr* last;
if (!m_last_fresh_value.find(m_manager.get_sort(e), last)) {
return false;
}
contains_app contains(m_manager, e);
bool result = contains(last);
TRACE("datatype", tout << mk_pp(e, m_manager) << " in " << mk_pp(last, m_manager) << " " << result << "\n";);
return result;
}
/**
\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);
SASSERT(val);
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);
for (func_decl * constructor : constructors) {
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 != nullptr) {
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) {
app * 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)) {
if (is_subterm_of_last_value(new_value)) {
new_value = static_cast<app*>(m_last_fresh_value.find(s));
}
else {
m_last_fresh_value.insert(s, new_value);
}
}
TRACE("datatype", tout << "almost fresh: " << mk_pp(new_value, m_manager) << "\n";);
return new_value;
}
}
SASSERT(!m_util.is_recursive(s));
return nullptr;
}
expr * datatype_factory::get_fresh_value(sort * s) {
TRACE("datatype", 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", 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);
for (func_decl * constructor : constructors) {
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 != nullptr) {
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", 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", tout << "1. result: " << mk_pp(new_value, m_manager) << "\n";);
return new_value;
}
}
// Approach 2)
// For recursive datatypes.
// search for constructor...
unsigned num_iterations = 0;
if (m_util.is_recursive(s)) {
while(true) {
++num_iterations;
TRACE("datatype", tout << mk_pp(get_last_fresh_value(s), m_manager) << "\n";);
ptr_vector<func_decl> const & constructors = *m_util.get_datatype_constructors(s);
for (func_decl * constructor : constructors) {
expr_ref_vector args(m_manager);
bool found_sibling = false;
unsigned num = constructor->get_arity();
TRACE("datatype", tout << "checking constructor: " << constructor->get_name() << "\n";);
for (unsigned i = 0; i < num; i++) {
sort * s_arg = constructor->get_domain(i);
TRACE("datatype", tout << mk_pp(s, m_manager) << " "
<< mk_pp(s_arg, m_manager) << " are_siblings "
<< m_util.are_siblings(s, s_arg) << " is_datatype "
<< m_util.is_datatype(s_arg) << " found_sibling "
<< found_sibling << "\n";);
if (!found_sibling && m_util.is_datatype(s_arg) && m_util.are_siblings(s, s_arg)) {
found_sibling = true;
expr * maybe_new_arg = nullptr;
if (num_iterations <= 1) {
maybe_new_arg = get_almost_fresh_value(s_arg);
}
else {
maybe_new_arg = get_fresh_value(s_arg);
}
if (!maybe_new_arg) {
TRACE("datatype",
tout << "no argument found for " << mk_pp(s_arg, m_manager) << "\n";);
maybe_new_arg = m_model.get_some_value(s_arg);
found_sibling = false;
}
SASSERT(maybe_new_arg);
args.push_back(maybe_new_arg);
}
else {
expr * some_arg = m_model.get_some_value(s_arg);
SASSERT(some_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());
TRACE("datatype", tout << "potential new value: " << mk_pp(new_value, m_manager) << "\n";);
m_last_fresh_value.insert(s, new_value);
if (!set->contains(new_value)) {
register_value(new_value);
TRACE("datatype", 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 nullptr;
}

View file

@ -1,42 +0,0 @@
/*++
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 "smt/proto_model/struct_factory.h"
#include "ast/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);
bool is_subterm_of_last_value(app* e);
public:
datatype_factory(ast_manager & m, proto_model & md);
~datatype_factory() override {}
expr * get_some_value(sort * s) override;
expr * get_fresh_value(sort * s) override;
};
#endif /* DATATYPE_FACTORY_H_ */

View file

@ -1,52 +0,0 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
numeral_factory.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-10-28.
Revision History:
--*/
#include "smt/proto_model/numeral_factory.h"
#include "ast/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.mk_family_id("arith")),
m_util(m) {
}
arith_factory::~arith_factory() {
}
app * arith_factory::mk_num_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.mk_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_num_value(rational const & val, unsigned bv_size) {
return numeral_factory::mk_value(val, m_util.mk_sort(bv_size));
}

View file

@ -1,57 +0,0 @@
/*++
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 "smt/proto_model/value_factory.h"
#include "ast/arith_decl_plugin.h"
#include "ast/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) {}
~numeral_factory() override {}
};
class arith_factory : public numeral_factory {
arith_util m_util;
app * mk_value_core(rational const & val, sort * s) override;
public:
arith_factory(ast_manager & m);
~arith_factory() override;
app * mk_num_value(rational const & val, bool is_int);
};
class bv_factory : public numeral_factory {
bv_util m_util;
app * mk_value_core(rational const & val, sort * s) override;
public:
bv_factory(ast_manager & m);
~bv_factory() override;
app * mk_num_value(rational const & val, unsigned bv_size);
};
#endif /* NUMERAL_FACTORY_H_ */

View file

@ -192,9 +192,8 @@ void proto_model::cleanup_func_interp(func_interp * fi, func_decl_set & found_au
void proto_model::remove_aux_decls_not_in_set(ptr_vector<func_decl> & decls, func_decl_set const & s) {
unsigned sz = decls.size();
unsigned i = 0;
unsigned j = 0;
for (; i < sz; i++) {
for (unsigned i = 0; i < sz; i++) {
func_decl * f = decls[i];
if (!m_aux_decls.contains(f) || s.contains(f)) {
decls[j] = f;
@ -280,11 +279,10 @@ expr * proto_model::get_some_value(sort * s) {
if (m.is_uninterp(s)) {
return m_user_sort_factory->get_some_value(s);
}
else if (value_factory * f = get_factory(s->get_family_id())) {
return f->get_some_value(s);
}
else {
family_id fid = s->get_family_id();
value_factory * f = get_factory(fid);
if (f)
return f->get_some_value(s);
// there is no factory for the family id, then assume s is uninterpreted.
return m_user_sort_factory->get_some_value(s);
}
@ -294,13 +292,11 @@ bool proto_model::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
if (m.is_uninterp(s)) {
return m_user_sort_factory->get_some_values(s, v1, v2);
}
else if (value_factory * f = get_factory(s->get_family_id())) {
return f->get_some_values(s, v1, v2);
}
else {
family_id fid = s->get_family_id();
value_factory * f = get_factory(fid);
if (f)
return f->get_some_values(s, v1, v2);
else
return false;
return false;
}
}
@ -308,15 +304,13 @@ expr * proto_model::get_fresh_value(sort * s) {
if (m.is_uninterp(s)) {
return m_user_sort_factory->get_fresh_value(s);
}
else if (value_factory * f = get_factory(s->get_family_id())) {
return f->get_fresh_value(s);
}
else {
family_id fid = s->get_family_id();
value_factory * f = get_factory(fid);
if (f)
return f->get_fresh_value(s);
else
// Use user_sort_factory if the theory has no support for model construnction.
// This is needed when dummy theories are used for arithmetic or arrays.
return m_user_sort_factory->get_fresh_value(s);
// Use user_sort_factory if the theory has no support for model construnction.
// This is needed when dummy theories are used for arithmetic or arrays.
return m_user_sort_factory->get_fresh_value(s);
}
}
@ -336,7 +330,7 @@ void proto_model::register_value(expr * n) {
void proto_model::compress() {
for (func_decl* f : m_func_decls) {
func_interp * fi = get_func_interp(f);
SASSERT(fi != 0);
SASSERT(fi != nullptr);
fi->compress();
}
}

View file

@ -30,7 +30,7 @@ Revision History:
#include "model/model_core.h"
#include "model/model_evaluator.h"
#include "smt/proto_model/value_factory.h"
#include "model/value_factory.h"
#include "util/plugin_manager.h"
#include "ast/arith_decl_plugin.h"
#include "ast/func_decl_dependencies.h"
@ -71,10 +71,10 @@ public:
value_factory * get_factory(family_id fid);
expr * get_some_value(sort * s) override;
expr * get_fresh_value(sort * s) override;
bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2);
bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) override;
expr * get_fresh_value(sort * s);
void register_value(expr * n);

View file

@ -1,78 +0,0 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
struct_factory.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-11-06.
Revision History:
--*/
#include "smt/proto_model/struct_factory.h"
#include "smt/proto_model/proto_model.h"
struct_factory::value_set * struct_factory::get_value_set(sort * s) {
value_set * set = nullptr;
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

@ -1,54 +0,0 @@
/*++
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 "smt/proto_model/value_factory.h"
#include "util/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);
~struct_factory() override;
bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) override;
void register_value(expr * array_value) override;
};
#endif /* STRUCT_FACTORY_H_ */

View file

@ -1,117 +0,0 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
value_factory.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-10-28.
Revision History:
--*/
#include "smt/proto_model/value_factory.h"
value_factory::value_factory(ast_manager & m, family_id fid):
m_manager(m),
m_fid(fid) {
}
value_factory::~value_factory() {
}
basic_factory::basic_factory(ast_manager & m):
value_factory(m, m.get_basic_family_id()) {
}
expr * basic_factory::get_some_value(sort * s) {
if (m_manager.is_bool(s))
return m_manager.mk_false();
return nullptr;
}
bool basic_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
if (m_manager.is_bool(s)) {
v1 = m_manager.mk_false();
v2 = m_manager.mk_true();
return true;
}
return false;
}
expr * basic_factory::get_fresh_value(sort * s) {
return nullptr;
}
user_sort_factory::user_sort_factory(ast_manager & m):
simple_factory<unsigned>(m, m.mk_family_id("user-sort")) {
}
void user_sort_factory::freeze_universe(sort * s) {
if (!m_finite.contains(s)) {
value_set * set = nullptr;
m_sort2value_set.find(s, set);
if (!m_sort2value_set.find(s, set) || set->m_values.empty()) {
// we cannot freeze an empty universe.
get_some_value(s); // add one element to the universe...
}
SASSERT(m_sort2value_set.find(s, set) && set != 0 && !set->m_values.empty());
m_finite.insert(s);
}
}
obj_hashtable<expr> const & user_sort_factory::get_known_universe(sort * s) const {
value_set * set = nullptr;
if (m_sort2value_set.find(s, set)) {
return set->m_values;
}
return m_empty_universe;
}
expr * user_sort_factory::get_some_value(sort * s) {
if (is_finite(s)) {
value_set * set = nullptr;
m_sort2value_set.find(s, set);
SASSERT(set != 0);
SASSERT(!set->m_values.empty());
return *(set->m_values.begin());
}
return simple_factory<unsigned>::get_some_value(s);
}
bool user_sort_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
if (is_finite(s)) {
value_set * set = nullptr;
if (m_sort2value_set.find(s, set) && set->m_values.size() >= 2) {
obj_hashtable<expr>::iterator it = set->m_values.begin();
v1 = *it;
++it;
v2 = *it;
return true;
}
return false;
}
return simple_factory<unsigned>::get_some_values(s, v1, v2);
}
expr * user_sort_factory::get_fresh_value(sort * s) {
if (is_finite(s))
return nullptr;
return simple_factory<unsigned>::get_fresh_value(s);
}
void user_sort_factory::register_value(expr * n) {
SASSERT(!is_finite(m_manager.get_sort(n)));
simple_factory<unsigned>::register_value(n);
}
app * user_sort_factory::mk_value_core(unsigned const & val, sort * s) {
return m_manager.mk_model_value(val, s);
}

View file

@ -1,270 +0,0 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
value_factory.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-10-28.
Revision History:
--*/
#ifndef VALUE_FACTORY_H_
#define VALUE_FACTORY_H_
#include "ast/ast.h"
#include "util/obj_hashtable.h"
/**
\brief Auxiliary object used during model construction.
*/
class value_factory {
protected:
ast_manager & m_manager;
family_id m_fid;
public:
value_factory(ast_manager & m, family_id fid);
virtual ~value_factory();
/**
\brief Return some value of the given sort. The result is always different from zero.
*/
virtual expr * get_some_value(sort * s) = 0;
/**
\brief Return two distinct values of the given sort. The results are stored in v1 and v2.
Return false if the intended interpretation of the given sort has only one element.
*/
virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) = 0;
/**
\brief Return a fresh value of the given sort.
Return 0 if it is not possible to do that (e.g., the sort is finite).
*/
virtual expr * get_fresh_value(sort * s) = 0;
/**
\brief Used to register that the given value was used in model construction.
So, get_fresh_value cannot return this value anymore.
*/
virtual void register_value(expr * n) = 0;
family_id get_family_id() const { return m_fid; }
};
class basic_factory : public value_factory {
public:
basic_factory(ast_manager & m);
expr * get_some_value(sort * s) override;
bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) override;
expr * get_fresh_value(sort * s) override;
void register_value(expr * n) override { }
};
/**
\brief Template for value factories for numeric (and enumeration-like) sorts
*/
template<typename Number>
class simple_factory : public value_factory {
protected:
struct value_set {
obj_hashtable<expr> m_values;
Number m_next;
value_set():
m_next(0) {
}
};
typedef obj_map<sort, value_set *> sort2value_set;
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) {
value_set * set = nullptr;
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);
DEBUG_CODE({
value_set * set2 = 0;
SASSERT(m_sort2value_set.find(s, set2));
SASSERT(set == set2);
});
return set;
}
virtual app * mk_value_core(Number const & val, sort * s) = 0;
app * mk_value(Number const & val, sort * s, bool & is_new) {
value_set * set = get_value_set(s);
app * new_val = mk_value_core(val, s);
is_new = false;
if (!set->m_values.contains(new_val)) {
m_values.push_back(new_val);
set->m_values.insert(new_val);
is_new = true;
}
SASSERT(set->m_values.contains(new_val));
return new_val;
}
public:
simple_factory(ast_manager & m, family_id fid):
value_factory(m, fid),
m_values(m),
m_sorts(m) {
}
~simple_factory() override {
std::for_each(m_sets.begin(), m_sets.end(), delete_proc<value_set>());
}
expr * get_some_value(sort * s) override {
value_set * set = nullptr;
expr * result = nullptr;
if (m_sort2value_set.find(s, set) && !set->m_values.empty())
result = *(set->m_values.begin());
else
result = mk_value(Number(0), s);
return result;
}
bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) override {
value_set * set = nullptr;
if (m_sort2value_set.find(s, set)) {
switch (set->m_values.size()) {
case 0:
v1 = mk_value(Number(0), s);
v2 = mk_value(Number(1), s);
break;
case 1:
v1 = *(set->m_values.begin());
v2 = mk_value(Number(0), s);
if (v1 == v2)
v2 = mk_value(Number(1), s);
break;
default:
obj_hashtable<expr>::iterator it = set->m_values.begin();
v1 = *it;
++it;
v2 = *it;
break;
}
SASSERT(v1 != v2);
return true;
}
v1 = mk_value(Number(0), s);
v2 = mk_value(Number(1), s);
return true;
}
expr * get_fresh_value(sort * s) override {
value_set * set = get_value_set(s);
bool is_new = false;
expr * result = nullptr;
sort_info* s_info = s->get_info();
sort_size const* sz = s_info?&s_info->get_num_elements():nullptr;
bool has_max = false;
Number max_size(0);
if (sz && sz->is_finite() && sz->size() < UINT_MAX) {
unsigned usz = static_cast<unsigned>(sz->size());
max_size = Number(usz);
has_max = true;
}
Number start = set->m_next;
Number & next = set->m_next;
while (!is_new) {
result = mk_value(next, s, is_new);
next++;
if (has_max && next > max_size + start) {
return nullptr;
}
}
SASSERT(result != 0);
return result;
}
void register_value(expr * n) override {
sort * s = this->m_manager.get_sort(n);
value_set * set = get_value_set(s);
if (!set->m_values.contains(n)) {
m_values.push_back(n);
set->m_values.insert(n);
}
}
virtual app * mk_value(Number const & val, sort * s) {
bool is_new;
return mk_value(val, s, is_new);
}
unsigned get_num_sorts() const { return m_sorts.size(); }
sort * get_sort(unsigned idx) const { return m_sorts.get(idx); }
};
/**
\brief Factory for creating values for uninterpreted sorts and user
declared (uninterpreted) sorts.
*/
class user_sort_factory : public simple_factory<unsigned> {
obj_hashtable<sort> m_finite; //!< set of sorts that are marked as finite.
obj_hashtable<expr> m_empty_universe;
app * mk_value_core(unsigned const & val, sort * s) override;
public:
user_sort_factory(ast_manager & m);
~user_sort_factory() override {}
/**
\brief Make the universe of \c s finite, by preventing new
elements to be added to its universe.
*/
void freeze_universe(sort * s);
/**
\brief Return true if the universe of \c s is frozen and finite.
*/
bool is_finite(sort * s) const {
return m_finite.contains(s);
}
/**
\brief Return the "known" universe of \c s. It doesn't matter whether
s is finite or not. If \c s is finite, then it is the whole universe.
*/
obj_hashtable<expr> const & get_known_universe(sort * s) const;
/**
\brief Return sorts with finite interpretations.
*/
obj_hashtable<sort> const & get_finite_sorts() const { return m_finite; }
expr * get_some_value(sort * s) override;
bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) override;
expr * get_fresh_value(sort * s) override;
void register_value(expr * n) override;
};
#endif /* VALUE_FACTORY_H_ */

View file

@ -20,24 +20,24 @@ Revision History:
#ifndef THEORY_ARITH_H_
#define THEORY_ARITH_H_
#include "smt/smt_theory.h"
#include "util/map.h"
#include "util/heap.h"
#include "util/nat_set.h"
#include "util/inf_rational.h"
#include "util/s_integer.h"
#include "util/inf_s_integer.h"
#include "util/obj_pair_hashtable.h"
#include "util/uint_set.h"
#include "ast/arith_decl_plugin.h"
#include "model/numeral_factory.h"
#include "smt/smt_theory.h"
#include "smt/params/theory_arith_params.h"
#include "smt/arith_eq_adapter.h"
#include "smt/proto_model/numeral_factory.h"
#include "smt/smt_context.h"
#include "util/obj_pair_hashtable.h"
#include "smt/old_interval.h"
#include "math/grobner/grobner.h"
#include "smt/arith_eq_solver.h"
#include "smt/theory_opt.h"
#include "util/uint_set.h"
#include "math/grobner/grobner.h"
namespace smt {

View file

@ -22,7 +22,7 @@ Revision History:
#include "smt/smt_theory.h"
#include "smt/theory_array_bapa.h"
#include "ast/array_decl_plugin.h"
#include "smt/proto_model/array_factory.h"
#include "model/array_factory.h"
namespace smt {

View file

@ -19,13 +19,13 @@ Revision History:
#ifndef THEORY_BV_H_
#define THEORY_BV_H_
#include "smt/smt_theory.h"
#include "smt/params/theory_bv_params.h"
#include "ast/rewriter/bit_blaster/bit_blaster.h"
#include "util/trail.h"
#include "util/union_find.h"
#include "ast/arith_decl_plugin.h"
#include "smt/proto_model/numeral_factory.h"
#include "model/numeral_factory.h"
#include "smt/smt_theory.h"
#include "smt/params/theory_bv_params.h"
namespace smt {

View file

@ -22,9 +22,9 @@ Revision History:
#include "util/union_find.h"
#include "ast/array_decl_plugin.h"
#include "ast/datatype_decl_plugin.h"
#include "model/datatype_factory.h"
#include "smt/smt_theory.h"
#include "smt/params/theory_datatype_params.h"
#include "smt/proto_model/datatype_factory.h"
namespace smt {
class theory_datatype : public theory {

View file

@ -27,15 +27,15 @@ Revision History:
#include "util/inf_int_rational.h"
#include "util/s_integer.h"
#include "util/inf_s_integer.h"
#include "util/map.h"
#include "ast/arith_decl_plugin.h"
#include "model/numeral_factory.h"
#include "smt/smt_theory.h"
#include "smt/diff_logic.h"
#include "ast/arith_decl_plugin.h"
#include "smt/smt_justification.h"
#include "util/map.h"
#include "smt/params/smt_params.h"
#include "smt/arith_eq_adapter.h"
#include "smt/smt_model_generator.h"
#include "smt/proto_model/numeral_factory.h"
#include "smt/smt_clause.h"
#include "smt/theory_opt.h"
#include "math/simplex/simplex.h"

View file

@ -22,11 +22,11 @@ Revision History:
#ifndef THEORY_DIFF_LOGIC_DEF_H_
#define THEORY_DIFF_LOGIC_DEF_H_
#include "util/map.h"
#include "util/warning.h"
#include "ast/ast_pp.h"
#include "smt/theory_diff_logic.h"
#include "smt/smt_context.h"
#include "util/map.h"
#include "ast/ast_pp.h"
#include "util/warning.h"
#include "smt/smt_model_generator.h"
#include "model/model_implicant.h"

View file

@ -22,14 +22,14 @@ Revision History:
--*/
#include "smt/smt_theory.h"
#include "ast/dl_decl_plugin.h"
#include "smt/proto_model/value_factory.h"
#include "smt/smt_model_generator.h"
#include "ast/bv_decl_plugin.h"
#include "ast/ast_pp.h"
#include "model/value_factory.h"
#include "smt/smt_theory.h"
#include "smt/smt_model_generator.h"
#include "smt/theory_bv.h"
#include "smt/smt_context.h"
#include "ast/ast_pp.h"
// Basic approach: reduce theory to bit-vectors:
//

View file

@ -24,7 +24,7 @@ Revision History:
#include "ast/fpa/fpa2bv_converter.h"
#include "ast/fpa/fpa2bv_rewriter.h"
#include "ast/rewriter/th_rewriter.h"
#include "smt/proto_model/value_factory.h"
#include "model/value_factory.h"
#include "smt/smt_model_generator.h"
namespace smt {

View file

@ -28,20 +28,20 @@
#include "util/optional.h"
#include "util/lp/lp_params.hpp"
#include "util/inf_rational.h"
#include "util/cancel_eh.h"
#include "util/scoped_timer.h"
#include "util/nat_set.h"
#include "util/lp/nra_solver.h"
#include "ast/ast_pp.h"
#include "model/numeral_factory.h"
#include "smt/smt_theory.h"
#include "smt/smt_context.h"
#include "smt/theory_lra.h"
#include "smt/proto_model/numeral_factory.h"
#include "smt/smt_model_generator.h"
#include "smt/arith_eq_adapter.h"
#include "util/nat_set.h"
#include "util/lp/nra_solver.h"
#include "tactic/generic_model_converter.h"
#include "math/polynomial/algebraic_numbers.h"
#include "math/polynomial/polynomial.h"
#include "ast/ast_pp.h"
#include "util/cancel_eh.h"
#include "util/scoped_timer.h"
namespace lp_api {
enum bound_kind { lower_t, upper_t };

View file

@ -92,7 +92,7 @@ Outline:
#include "ast/ast_ll_pp.h"
#include "ast/ast_trail.h"
#include "ast/for_each_expr.h"
#include "smt/proto_model/value_factory.h"
#include "model/value_factory.h"
#include "smt/smt_context.h"
#include "smt/smt_model_generator.h"
#include "smt/theory_seq.h"

View file

@ -26,9 +26,9 @@
#include "ast/rewriter/th_rewriter.h"
#include "ast/rewriter/seq_rewriter.h"
#include "ast/seq_decl_plugin.h"
#include "model/value_factory.h"
#include "smt/smt_theory.h"
#include "smt/params/theory_str_params.h"
#include "smt/proto_model/value_factory.h"
#include "smt/smt_model_generator.h"
#include "smt/smt_arith_value.h"
#include<set>