mirror of
https://github.com/Z3Prover/z3
synced 2025-12-17 17:58:31 +00:00
restructure base class struct_factory so that enumeration of values for a sort comes together with hash-table access. This allows to use the enumeration view during value creations for finite sets
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
b53e87dcba
commit
1b918ce4ec
5 changed files with 44 additions and 49 deletions
|
|
@ -63,8 +63,8 @@ void array_factory::get_some_args_for(sort * s, ptr_buffer<expr> & args) {
|
||||||
expr * array_factory::get_some_value(sort * s) {
|
expr * array_factory::get_some_value(sort * s) {
|
||||||
TRACE(array_factory, tout << mk_pp(s, m_manager) << "\n";);
|
TRACE(array_factory, tout << mk_pp(s, m_manager) << "\n";);
|
||||||
value_set * set = nullptr;
|
value_set * set = nullptr;
|
||||||
if (m_sort2value_set.find(s, set) && !set->empty())
|
if (m_sort2value_set.find(s, set) && !set->set.empty())
|
||||||
return *(set->begin());
|
return *(set->set.begin());
|
||||||
func_interp * fi;
|
func_interp * fi;
|
||||||
expr * val = mk_array_interp(s, fi);
|
expr * val = mk_array_interp(s, fi);
|
||||||
fi->set_else(m_model.get_some_value(get_array_range(s)));
|
fi->set_else(m_model.get_some_value(get_array_range(s)));
|
||||||
|
|
@ -75,7 +75,7 @@ bool array_factory::mk_two_diff_values_for(sort * s) {
|
||||||
TRACE(array_factory, tout << mk_pp(s, m_manager) << "\n";);
|
TRACE(array_factory, tout << mk_pp(s, m_manager) << "\n";);
|
||||||
DEBUG_CODE({
|
DEBUG_CODE({
|
||||||
value_set * set = 0;
|
value_set * set = 0;
|
||||||
SASSERT(!m_sort2value_set.find(s, set) || set->size() <= 1);
|
SASSERT(!m_sort2value_set.find(s, set) || set->set.size() <= 1);
|
||||||
});
|
});
|
||||||
expr_ref r1(m_manager);
|
expr_ref r1(m_manager);
|
||||||
expr_ref r2(m_manager);
|
expr_ref r2(m_manager);
|
||||||
|
|
@ -92,24 +92,24 @@ bool array_factory::mk_two_diff_values_for(sort * s) {
|
||||||
fi2->insert_entry(args.data(), r2);
|
fi2->insert_entry(args.data(), r2);
|
||||||
DEBUG_CODE({
|
DEBUG_CODE({
|
||||||
value_set * set = 0;
|
value_set * set = 0;
|
||||||
SASSERT(m_sort2value_set.find(s, set) && set->size() >= 2);
|
SASSERT(m_sort2value_set.find(s, set) && set->set.size() >= 2);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool array_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
|
bool array_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
|
||||||
value_set * set = nullptr;
|
value_set * set = nullptr;
|
||||||
if (!m_sort2value_set.find(s, set) || set->size() < 2) {
|
if (!m_sort2value_set.find(s, set) || set->set.size() < 2) {
|
||||||
if (!mk_two_diff_values_for(s)) {
|
if (!mk_two_diff_values_for(s)) {
|
||||||
TRACE(array_factory_bug, tout << "could not create diff values: " << mk_pp(s, m_manager) << "\n";);
|
TRACE(array_factory_bug, tout << "could not create diff values: " << mk_pp(s, m_manager) << "\n";);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_sort2value_set.find(s, set);
|
m_sort2value_set.find(s, set);
|
||||||
SASSERT(set != 0);
|
SASSERT(set);
|
||||||
SASSERT(set->size() >= 2);
|
SASSERT(set->set.size() >= 2);
|
||||||
|
|
||||||
value_set::iterator it = set->begin();
|
auto it = set->set.begin();
|
||||||
v1 = *it;
|
v1 = *it;
|
||||||
++it;
|
++it;
|
||||||
v2 = *it;
|
v2 = *it;
|
||||||
|
|
@ -126,8 +126,8 @@ bool array_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
|
||||||
// is set with the result of some entry.
|
// is set with the result of some entry.
|
||||||
//
|
//
|
||||||
expr * array_factory::get_fresh_value(sort * s) {
|
expr * array_factory::get_fresh_value(sort * s) {
|
||||||
value_set * set = get_value_set(s);
|
auto& [set, values] = get_value_set(s);
|
||||||
if (set->empty()) {
|
if (set.empty()) {
|
||||||
// easy case
|
// easy case
|
||||||
return get_some_value(s);
|
return get_some_value(s);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ expr * datatype_factory::get_some_value(sort * s) {
|
||||||
if (!m_util.is_datatype(s))
|
if (!m_util.is_datatype(s))
|
||||||
return m_model.get_some_value(s);
|
return m_model.get_some_value(s);
|
||||||
value_set * set = nullptr;
|
value_set * set = nullptr;
|
||||||
if (m_sort2value_set.find(s, set) && !set->empty())
|
if (m_sort2value_set.find(s, set) && !set->set.empty())
|
||||||
return *(set->begin());
|
return *(set->set.begin());
|
||||||
func_decl * c = m_util.get_non_rec_constructor(s);
|
func_decl * c = m_util.get_non_rec_constructor(s);
|
||||||
ptr_vector<expr> args;
|
ptr_vector<expr> args;
|
||||||
unsigned num = c->get_arity();
|
unsigned num = c->get_arity();
|
||||||
|
|
@ -50,11 +50,11 @@ expr * datatype_factory::get_last_fresh_value(sort * s) {
|
||||||
expr * val = nullptr;
|
expr * val = nullptr;
|
||||||
if (m_last_fresh_value.find(s, val))
|
if (m_last_fresh_value.find(s, val))
|
||||||
return val;
|
return val;
|
||||||
value_set * set = get_value_set(s);
|
auto& [set, values] = get_value_set(s);
|
||||||
if (set->empty())
|
if (set.empty())
|
||||||
val = get_some_value(s);
|
val = get_some_value(s);
|
||||||
else
|
else
|
||||||
val = *(set->begin());
|
val = *(set.begin());
|
||||||
if (m_util.is_recursive(s))
|
if (m_util.is_recursive(s))
|
||||||
m_last_fresh_value.insert(s, val);
|
m_last_fresh_value.insert(s, val);
|
||||||
return val;
|
return val;
|
||||||
|
|
@ -78,8 +78,8 @@ bool datatype_factory::is_subterm_of_last_value(app* e) {
|
||||||
expr * datatype_factory::get_almost_fresh_value(sort * s) {
|
expr * datatype_factory::get_almost_fresh_value(sort * s) {
|
||||||
if (!m_util.is_datatype(s))
|
if (!m_util.is_datatype(s))
|
||||||
return m_model.get_some_value(s);
|
return m_model.get_some_value(s);
|
||||||
value_set * set = get_value_set(s);
|
auto& [set, values] = get_value_set(s);
|
||||||
if (set->empty()) {
|
if (set.empty()) {
|
||||||
expr * val = get_some_value(s);
|
expr * val = get_some_value(s);
|
||||||
SASSERT(val);
|
SASSERT(val);
|
||||||
if (m_util.is_recursive(s))
|
if (m_util.is_recursive(s))
|
||||||
|
|
@ -117,7 +117,7 @@ expr * datatype_factory::get_almost_fresh_value(sort * s) {
|
||||||
}
|
}
|
||||||
if (recursive || found_fresh_arg) {
|
if (recursive || found_fresh_arg) {
|
||||||
app * new_value = m_manager.mk_app(constructor, args);
|
app * new_value = m_manager.mk_app(constructor, args);
|
||||||
SASSERT(!found_fresh_arg || !set->contains(new_value));
|
SASSERT(!found_fresh_arg || !set.contains(new_value));
|
||||||
register_value(new_value);
|
register_value(new_value);
|
||||||
if (m_util.is_recursive(s)) {
|
if (m_util.is_recursive(s)) {
|
||||||
if (is_subterm_of_last_value(new_value)) {
|
if (is_subterm_of_last_value(new_value)) {
|
||||||
|
|
@ -140,10 +140,10 @@ expr * datatype_factory::get_fresh_value(sort * s) {
|
||||||
if (!m_util.is_datatype(s))
|
if (!m_util.is_datatype(s))
|
||||||
return m_model.get_fresh_value(s);
|
return m_model.get_fresh_value(s);
|
||||||
TRACE(datatype, tout << "generating fresh value for: " << s->get_name() << "\n";);
|
TRACE(datatype, tout << "generating fresh value for: " << s->get_name() << "\n";);
|
||||||
value_set * set = get_value_set(s);
|
auto& [set, values] = get_value_set(s);
|
||||||
// Approach 0)
|
// Approach 0)
|
||||||
// if no value for s was generated so far, then used get_some_value
|
// if no value for s was generated so far, then used get_some_value
|
||||||
if (set->empty()) {
|
if (set.empty()) {
|
||||||
expr * val = get_some_value(s);
|
expr * val = get_some_value(s);
|
||||||
if (m_util.is_recursive(s))
|
if (m_util.is_recursive(s))
|
||||||
m_last_fresh_value.insert(s, val);
|
m_last_fresh_value.insert(s, val);
|
||||||
|
|
@ -178,12 +178,11 @@ expr * datatype_factory::get_fresh_value(sort * s) {
|
||||||
expr * some_arg = m_model.get_some_value(s_arg);
|
expr * some_arg = m_model.get_some_value(s_arg);
|
||||||
args.push_back(some_arg);
|
args.push_back(some_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_value = m_manager.mk_app(constructor, args);
|
new_value = m_manager.mk_app(constructor, args);
|
||||||
CTRACE(datatype, found_fresh_arg && set->contains(new_value), tout << "seen: " << new_value << "\n";);
|
CTRACE(datatype, found_fresh_arg && set.contains(new_value), tout << "seen: " << new_value << "\n";);
|
||||||
if (found_fresh_arg && set->contains(new_value))
|
if (found_fresh_arg && set.contains(new_value))
|
||||||
goto retry_value;
|
goto retry_value;
|
||||||
if (!set->contains(new_value)) {
|
if (!set.contains(new_value)) {
|
||||||
register_value(new_value);
|
register_value(new_value);
|
||||||
if (m_util.is_recursive(s))
|
if (m_util.is_recursive(s))
|
||||||
m_last_fresh_value.insert(s, new_value);
|
m_last_fresh_value.insert(s, new_value);
|
||||||
|
|
@ -241,7 +240,7 @@ expr * datatype_factory::get_fresh_value(sort * s) {
|
||||||
new_value = m_manager.mk_app(constructor, args);
|
new_value = m_manager.mk_app(constructor, args);
|
||||||
TRACE(datatype, tout << "potential new value: " << mk_pp(new_value, m_manager) << "\n";);
|
TRACE(datatype, tout << "potential new value: " << mk_pp(new_value, m_manager) << "\n";);
|
||||||
m_last_fresh_value.insert(s, new_value);
|
m_last_fresh_value.insert(s, new_value);
|
||||||
if (!set->contains(new_value)) {
|
if (!set.contains(new_value)) {
|
||||||
register_value(new_value);
|
register_value(new_value);
|
||||||
TRACE(datatype, tout << "2. result: " << mk_pp(new_value, m_manager) << "\n";);
|
TRACE(datatype, tout << "2. result: " << mk_pp(new_value, m_manager) << "\n";);
|
||||||
return new_value;
|
return new_value;
|
||||||
|
|
|
||||||
|
|
@ -19,41 +19,39 @@ Revision History:
|
||||||
#include "model/struct_factory.h"
|
#include "model/struct_factory.h"
|
||||||
#include "model/model_core.h"
|
#include "model/model_core.h"
|
||||||
|
|
||||||
struct_factory::value_set * struct_factory::get_value_set(sort * s) {
|
struct_factory::value_set& struct_factory::get_value_set(sort * s) {
|
||||||
value_set * set = nullptr;
|
value_set * set = nullptr;
|
||||||
if (!m_sort2value_set.find(s, set)) {
|
if (!m_sort2value_set.find(s, set)) {
|
||||||
set = alloc(value_set);
|
set = alloc(value_set, m_model.get_manager());
|
||||||
m_sort2value_set.insert(s, set);
|
m_sort2value_set.insert(s, set);
|
||||||
m_sorts.push_back(s);
|
m_sorts.push_back(s);
|
||||||
m_sets.push_back(set);
|
m_sets.push_back(set);
|
||||||
}
|
}
|
||||||
SASSERT(set != 0);
|
SASSERT(set != 0);
|
||||||
return set;
|
return *set;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct_factory::struct_factory(ast_manager & m, family_id fid, model_core & md):
|
struct_factory::struct_factory(ast_manager & m, family_id fid, model_core & md):
|
||||||
value_factory(m, fid),
|
value_factory(m, fid),
|
||||||
m_model(md),
|
m_model(md),
|
||||||
m_values(m),
|
|
||||||
m_sorts(m) {
|
m_sorts(m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct_factory::~struct_factory() {
|
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) {
|
void struct_factory::register_value(expr * new_value) {
|
||||||
sort * s = new_value->get_sort();
|
sort * s = new_value->get_sort();
|
||||||
value_set * set = get_value_set(s);
|
auto& [set, values] = get_value_set(s);
|
||||||
if (!set->contains(new_value)) {
|
if (!set.contains(new_value)) {
|
||||||
m_values.push_back(new_value);
|
values.push_back(new_value);
|
||||||
set->insert(new_value);
|
set.insert(new_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool struct_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
|
bool struct_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
|
||||||
value_set * set = get_value_set(s);
|
auto& [set, values] = get_value_set(s);
|
||||||
switch (set->size()) {
|
switch (set.size()) {
|
||||||
case 0:
|
case 0:
|
||||||
v1 = get_fresh_value(s);
|
v1 = get_fresh_value(s);
|
||||||
v2 = get_fresh_value(s);
|
v2 = get_fresh_value(s);
|
||||||
|
|
@ -63,7 +61,7 @@ bool struct_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
|
||||||
v2 = get_fresh_value(s);
|
v2 = get_fresh_value(s);
|
||||||
return v2 != 0;
|
return v2 != 0;
|
||||||
default:
|
default:
|
||||||
obj_hashtable<expr>::iterator it = set->begin();
|
obj_hashtable<expr>::iterator it = set.begin();
|
||||||
v1 = *it;
|
v1 = *it;
|
||||||
++it;
|
++it;
|
||||||
v2 = *it;
|
v2 = *it;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ Revision History:
|
||||||
|
|
||||||
#include "model/value_factory.h"
|
#include "model/value_factory.h"
|
||||||
#include "util/obj_hashtable.h"
|
#include "util/obj_hashtable.h"
|
||||||
|
#include "util/scoped_ptr_vector.h"
|
||||||
|
|
||||||
class model_core;
|
class model_core;
|
||||||
|
|
||||||
|
|
@ -28,16 +29,19 @@ class model_core;
|
||||||
*/
|
*/
|
||||||
class struct_factory : public value_factory {
|
class struct_factory : public value_factory {
|
||||||
protected:
|
protected:
|
||||||
typedef obj_hashtable<expr> value_set;
|
struct value_set {
|
||||||
typedef obj_map<sort, value_set *> sort2value_set;
|
obj_hashtable<expr> set;
|
||||||
|
expr_ref_vector values;
|
||||||
|
value_set(ast_manager &m) : values(m) {}
|
||||||
|
};
|
||||||
|
using sort2value_set = obj_map<sort, value_set *>;
|
||||||
|
|
||||||
model_core & m_model;
|
model_core & m_model;
|
||||||
sort2value_set m_sort2value_set;
|
sort2value_set m_sort2value_set;
|
||||||
expr_ref_vector m_values;
|
|
||||||
sort_ref_vector m_sorts;
|
sort_ref_vector m_sorts;
|
||||||
ptr_vector<value_set> m_sets;
|
scoped_ptr_vector<value_set> m_sets;
|
||||||
|
|
||||||
value_set * get_value_set(sort * s);
|
value_set& get_value_set(sort * s);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct_factory(ast_manager & m, family_id fid, model_core & md);
|
struct_factory(ast_manager & m, family_id fid, model_core & md);
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,6 @@ Abstract:
|
||||||
Theory solver for finite sets.
|
Theory solver for finite sets.
|
||||||
Implements axiom schemas for finite set operations.
|
Implements axiom schemas for finite set operations.
|
||||||
|
|
||||||
Author:
|
|
||||||
|
|
||||||
GitHub Copilot Agent 2025
|
|
||||||
|
|
||||||
Revision History:
|
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#include "smt/theory_finite_set.h"
|
#include "smt/theory_finite_set.h"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue