mirror of
https://github.com/Z3Prover/z3
synced 2025-07-03 11:25:40 +00:00
Merge branch 'master' into heap
This commit is contained in:
commit
d5c0ae7bea
15 changed files with 297 additions and 127 deletions
2
.github/workflows/coverage.yml
vendored
2
.github/workflows/coverage.yml
vendored
|
@ -3,6 +3,8 @@ name: Code Coverage
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 11 * * *"
|
- cron: "0 11 * * *"
|
||||||
|
|
||||||
|
|
2
.github/workflows/docker-image.yml
vendored
2
.github/workflows/docker-image.yml
vendored
|
@ -41,7 +41,7 @@ jobs:
|
||||||
type=edge
|
type=edge
|
||||||
type=sha,prefix=ubuntu-20.04-bare-z3-sha-
|
type=sha,prefix=ubuntu-20.04-bare-z3-sha-
|
||||||
- name: Build and push Bare Z3 Docker Image
|
- name: Build and push Bare Z3 Docker Image
|
||||||
uses: docker/build-push-action@v6.4.0
|
uses: docker/build-push-action@v6.5.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
|
|
@ -1412,8 +1412,10 @@ class HTMLFormatter(Formatter):
|
||||||
ys_pp = group(seq(ys))
|
ys_pp = group(seq(ys))
|
||||||
if a.is_forall():
|
if a.is_forall():
|
||||||
header = "∀"
|
header = "∀"
|
||||||
else:
|
elif a.is_exists():
|
||||||
header = "∃"
|
header = "∃"
|
||||||
|
else:
|
||||||
|
header = "λ"
|
||||||
return group(compose(to_format(header, 1),
|
return group(compose(to_format(header, 1),
|
||||||
indent(1, compose(ys_pp, to_format(" :"), line_break(), body_pp))))
|
indent(1, compose(ys_pp, to_format(" :"), line_break(), body_pp))))
|
||||||
|
|
||||||
|
|
|
@ -220,17 +220,33 @@ namespace datatype {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace decl {
|
namespace decl {
|
||||||
|
|
||||||
plugin::~plugin() {
|
plugin::~plugin() {
|
||||||
finalize();
|
finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin::finalize() {
|
void plugin::finalize() {
|
||||||
for (auto& kv : m_defs) {
|
for (auto& kv : m_defs)
|
||||||
dealloc(kv.m_value);
|
dealloc(kv.m_value);
|
||||||
}
|
|
||||||
m_defs.reset();
|
m_defs.reset();
|
||||||
m_util = nullptr; // force deletion
|
m_util = nullptr; // force deletion
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin::reset() {
|
||||||
|
m_datatype2constructors.reset();
|
||||||
|
m_datatype2nonrec_constructor.reset();
|
||||||
|
m_constructor2accessors.reset();
|
||||||
|
m_constructor2recognizer.reset();
|
||||||
|
m_recognizer2constructor.reset();
|
||||||
|
m_accessor2constructor.reset();
|
||||||
|
m_is_recursive.reset();
|
||||||
|
m_is_enum.reset();
|
||||||
|
std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc<ptr_vector<func_decl> >());
|
||||||
|
m_vectors.reset();
|
||||||
|
dealloc(m_asts);
|
||||||
|
m_asts = nullptr;
|
||||||
|
++m_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
util & plugin::u() const {
|
util & plugin::u() const {
|
||||||
|
@ -578,6 +594,7 @@ namespace datatype {
|
||||||
if (m_defs.find(s, d))
|
if (m_defs.find(s, d))
|
||||||
dealloc(d);
|
dealloc(d);
|
||||||
m_defs.remove(s);
|
m_defs.remove(s);
|
||||||
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool plugin::is_value_visit(bool unique, expr * arg, ptr_buffer<app> & todo) const {
|
bool plugin::is_value_visit(bool unique, expr * arg, ptr_buffer<app> & todo) const {
|
||||||
|
@ -799,7 +816,7 @@ namespace datatype {
|
||||||
for (unsigned i = 0; i < n; ++i) {
|
for (unsigned i = 0; i < n; ++i) {
|
||||||
sort* ps = get_datatype_parameter_sort(s, i);
|
sort* ps = get_datatype_parameter_sort(s, i);
|
||||||
sz = get_sort_size(params, ps);
|
sz = get_sort_size(params, ps);
|
||||||
m_refs.push_back(sz);
|
plugin().m_refs.push_back(sz);
|
||||||
S.insert(d.params().get(i), sz);
|
S.insert(d.params().get(i), sz);
|
||||||
}
|
}
|
||||||
auto ss = d.sort_size();
|
auto ss = d.sort_size();
|
||||||
|
@ -896,7 +913,7 @@ namespace datatype {
|
||||||
}
|
}
|
||||||
TRACE("datatype", tout << "set sort size " << s << "\n";);
|
TRACE("datatype", tout << "set sort size " << s << "\n";);
|
||||||
d.set_sort_size(param_size::size::mk_plus(s_add));
|
d.set_sort_size(param_size::size::mk_plus(s_add));
|
||||||
m_refs.reset();
|
plugin().m_refs.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1008,9 +1025,7 @@ namespace datatype {
|
||||||
util::util(ast_manager & m):
|
util::util(ast_manager & m):
|
||||||
m(m),
|
m(m),
|
||||||
m_family_id(null_family_id),
|
m_family_id(null_family_id),
|
||||||
m_plugin(nullptr),
|
m_plugin(nullptr) {
|
||||||
m_asts(m),
|
|
||||||
m_start(0) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1027,24 +1042,24 @@ namespace datatype {
|
||||||
|
|
||||||
|
|
||||||
util::~util() {
|
util::~util() {
|
||||||
std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc<ptr_vector<func_decl> >());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr_vector<func_decl> const * util::get_datatype_constructors(sort * ty) {
|
ptr_vector<func_decl> const * util::get_datatype_constructors(sort * ty) {
|
||||||
SASSERT(is_datatype(ty));
|
SASSERT(is_datatype(ty));
|
||||||
ptr_vector<func_decl> * r = nullptr;
|
ptr_vector<func_decl> * r = nullptr;
|
||||||
if (m_datatype2constructors.find(ty, r))
|
if (plugin().m_datatype2constructors.find(ty, r))
|
||||||
return r;
|
return r;
|
||||||
r = alloc(ptr_vector<func_decl>);
|
r = alloc(ptr_vector<func_decl>);
|
||||||
m_asts.push_back(ty);
|
plugin().add_ast(ty);
|
||||||
m_vectors.push_back(r);
|
plugin().m_vectors.push_back(r);
|
||||||
m_datatype2constructors.insert(ty, r);
|
plugin().m_datatype2constructors.insert(ty, r);
|
||||||
if (!is_declared(ty))
|
if (!is_declared(ty))
|
||||||
m.raise_exception("datatype constructors have not been created");
|
m.raise_exception("datatype constructors have not been created");
|
||||||
def const& d = get_def(ty);
|
def const& d = get_def(ty);
|
||||||
for (constructor const* c : d) {
|
for (constructor const* c : d) {
|
||||||
func_decl_ref f = c->instantiate(ty);
|
func_decl_ref f = c->instantiate(ty);
|
||||||
m_asts.push_back(f);
|
plugin().add_ast(f);
|
||||||
r->push_back(f);
|
r->push_back(f);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -1053,13 +1068,13 @@ namespace datatype {
|
||||||
ptr_vector<func_decl> const * util::get_constructor_accessors(func_decl * con) {
|
ptr_vector<func_decl> const * util::get_constructor_accessors(func_decl * con) {
|
||||||
SASSERT(is_constructor(con));
|
SASSERT(is_constructor(con));
|
||||||
ptr_vector<func_decl> * res = nullptr;
|
ptr_vector<func_decl> * res = nullptr;
|
||||||
if (m_constructor2accessors.find(con, res)) {
|
if (plugin().m_constructor2accessors.find(con, res)) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
res = alloc(ptr_vector<func_decl>);
|
res = alloc(ptr_vector<func_decl>);
|
||||||
m_asts.push_back(con);
|
plugin().add_ast(con);
|
||||||
m_vectors.push_back(res);
|
plugin().m_vectors.push_back(res);
|
||||||
m_constructor2accessors.insert(con, res);
|
plugin().m_constructor2accessors.insert(con, res);
|
||||||
sort * datatype = con->get_range();
|
sort * datatype = con->get_range();
|
||||||
def const& d = get_def(datatype);
|
def const& d = get_def(datatype);
|
||||||
for (constructor const* c : d) {
|
for (constructor const* c : d) {
|
||||||
|
@ -1067,7 +1082,7 @@ namespace datatype {
|
||||||
for (accessor const* a : *c) {
|
for (accessor const* a : *c) {
|
||||||
func_decl_ref fn = a->instantiate(datatype);
|
func_decl_ref fn = a->instantiate(datatype);
|
||||||
res->push_back(fn);
|
res->push_back(fn);
|
||||||
m_asts.push_back(fn);
|
plugin().add_ast(fn);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1086,7 +1101,7 @@ namespace datatype {
|
||||||
func_decl * util::get_constructor_recognizer(func_decl * con) {
|
func_decl * util::get_constructor_recognizer(func_decl * con) {
|
||||||
SASSERT(is_constructor(con));
|
SASSERT(is_constructor(con));
|
||||||
func_decl * d = nullptr;
|
func_decl * d = nullptr;
|
||||||
if (m_constructor2recognizer.find(con, d))
|
if (plugin().m_constructor2recognizer.find(con, d))
|
||||||
return d;
|
return d;
|
||||||
sort * datatype = con->get_range();
|
sort * datatype = con->get_range();
|
||||||
def const& dd = get_def(datatype);
|
def const& dd = get_def(datatype);
|
||||||
|
@ -1097,9 +1112,9 @@ namespace datatype {
|
||||||
parameter ps[2] = { parameter(con), parameter(r) };
|
parameter ps[2] = { parameter(con), parameter(r) };
|
||||||
d = m.mk_func_decl(fid(), OP_DT_RECOGNISER, 2, ps, 1, &datatype);
|
d = m.mk_func_decl(fid(), OP_DT_RECOGNISER, 2, ps, 1, &datatype);
|
||||||
SASSERT(d);
|
SASSERT(d);
|
||||||
m_asts.push_back(con);
|
plugin().add_ast(con);
|
||||||
m_asts.push_back(d);
|
plugin().add_ast(d);
|
||||||
m_constructor2recognizer.insert(con, d);
|
plugin().m_constructor2recognizer.insert(con, d);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1120,10 +1135,10 @@ namespace datatype {
|
||||||
bool util::is_recursive(sort * ty) {
|
bool util::is_recursive(sort * ty) {
|
||||||
SASSERT(is_datatype(ty));
|
SASSERT(is_datatype(ty));
|
||||||
bool r = false;
|
bool r = false;
|
||||||
if (!m_is_recursive.find(ty, r)) {
|
if (!plugin().m_is_recursive.find(ty, r)) {
|
||||||
r = is_recursive_core(ty);
|
r = is_recursive_core(ty);
|
||||||
m_is_recursive.insert(ty, r);
|
plugin().m_is_recursive.insert(ty, r);
|
||||||
m_asts.push_back(ty);
|
plugin().add_ast(ty);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1147,21 +1162,21 @@ namespace datatype {
|
||||||
if (!is_datatype(s))
|
if (!is_datatype(s))
|
||||||
return false;
|
return false;
|
||||||
bool r = false;
|
bool r = false;
|
||||||
if (m_is_enum.find(s, r))
|
if (plugin().m_is_enum.find(s, r))
|
||||||
return r;
|
return r;
|
||||||
ptr_vector<func_decl> const& cnstrs = *get_datatype_constructors(s);
|
ptr_vector<func_decl> const& cnstrs = *get_datatype_constructors(s);
|
||||||
r = true;
|
r = true;
|
||||||
for (unsigned i = 0; r && i < cnstrs.size(); ++i)
|
for (unsigned i = 0; r && i < cnstrs.size(); ++i)
|
||||||
r = cnstrs[i]->get_arity() == 0;
|
r = cnstrs[i]->get_arity() == 0;
|
||||||
m_is_enum.insert(s, r);
|
plugin().m_is_enum.insert(s, r);
|
||||||
m_asts.push_back(s);
|
plugin().add_ast(s);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
func_decl * util::get_accessor_constructor(func_decl * accessor) {
|
func_decl * util::get_accessor_constructor(func_decl * accessor) {
|
||||||
SASSERT(is_accessor(accessor));
|
SASSERT(is_accessor(accessor));
|
||||||
func_decl * r = nullptr;
|
func_decl * r = nullptr;
|
||||||
if (m_accessor2constructor.find(accessor, r))
|
if (plugin().m_accessor2constructor.find(accessor, r))
|
||||||
return r;
|
return r;
|
||||||
sort * datatype = accessor->get_domain(0);
|
sort * datatype = accessor->get_domain(0);
|
||||||
symbol c_id = accessor->get_parameter(1).get_symbol();
|
symbol c_id = accessor->get_parameter(1).get_symbol();
|
||||||
|
@ -1174,26 +1189,15 @@ namespace datatype {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r = fn;
|
r = fn;
|
||||||
m_accessor2constructor.insert(accessor, r);
|
plugin().m_accessor2constructor.insert(accessor, r);
|
||||||
m_asts.push_back(accessor);
|
plugin().add_ast(accessor);
|
||||||
m_asts.push_back(r);
|
plugin().add_ast(r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void util::reset() {
|
void util::reset() {
|
||||||
m_datatype2constructors.reset();
|
plugin().reset();
|
||||||
m_datatype2nonrec_constructor.reset();
|
|
||||||
m_constructor2accessors.reset();
|
|
||||||
m_constructor2recognizer.reset();
|
|
||||||
m_recognizer2constructor.reset();
|
|
||||||
m_accessor2constructor.reset();
|
|
||||||
m_is_recursive.reset();
|
|
||||||
m_is_enum.reset();
|
|
||||||
std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc<ptr_vector<func_decl> >());
|
|
||||||
m_vectors.reset();
|
|
||||||
m_asts.reset();
|
|
||||||
++m_start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1205,7 +1209,7 @@ namespace datatype {
|
||||||
func_decl * util::get_non_rec_constructor(sort * ty) {
|
func_decl * util::get_non_rec_constructor(sort * ty) {
|
||||||
SASSERT(is_datatype(ty));
|
SASSERT(is_datatype(ty));
|
||||||
cnstr_depth cd;
|
cnstr_depth cd;
|
||||||
if (m_datatype2nonrec_constructor.find(ty, cd))
|
if (plugin().m_datatype2nonrec_constructor.find(ty, cd))
|
||||||
return cd.first;
|
return cd.first;
|
||||||
ptr_vector<sort> forbidden_set;
|
ptr_vector<sort> forbidden_set;
|
||||||
forbidden_set.push_back(ty);
|
forbidden_set.push_back(ty);
|
||||||
|
@ -1222,7 +1226,7 @@ namespace datatype {
|
||||||
each T_i is not a datatype or it is a datatype t not in forbidden_set,
|
each T_i is not a datatype or it is a datatype t not in forbidden_set,
|
||||||
and get_non_rec_constructor_core(T_i, forbidden_set union { T_i })
|
and get_non_rec_constructor_core(T_i, forbidden_set union { T_i })
|
||||||
*/
|
*/
|
||||||
util::cnstr_depth util::get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set) {
|
cnstr_depth util::get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set) {
|
||||||
// We must select a constructor c(T_1, ..., T_n):T such that
|
// We must select a constructor c(T_1, ..., T_n):T such that
|
||||||
// 1) T_i's are not recursive
|
// 1) T_i's are not recursive
|
||||||
// If there is no such constructor, then we select one that
|
// If there is no such constructor, then we select one that
|
||||||
|
@ -1231,7 +1235,7 @@ namespace datatype {
|
||||||
ptr_vector<func_decl> const& constructors = *get_datatype_constructors(ty);
|
ptr_vector<func_decl> const& constructors = *get_datatype_constructors(ty);
|
||||||
array_util autil(m);
|
array_util autil(m);
|
||||||
cnstr_depth result(nullptr, 0);
|
cnstr_depth result(nullptr, 0);
|
||||||
if (m_datatype2nonrec_constructor.find(ty, result))
|
if (plugin().m_datatype2nonrec_constructor.find(ty, result))
|
||||||
return result;
|
return result;
|
||||||
TRACE("util_bug", tout << "get-non-rec constructor: " << sort_ref(ty, m) << "\n";
|
TRACE("util_bug", tout << "get-non-rec constructor: " << sort_ref(ty, m) << "\n";
|
||||||
tout << "forbidden: ";
|
tout << "forbidden: ";
|
||||||
|
@ -1273,9 +1277,9 @@ namespace datatype {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result.first) {
|
if (result.first) {
|
||||||
m_asts.push_back(result.first);
|
plugin().add_ast(result.first);
|
||||||
m_asts.push_back(ty);
|
plugin().add_ast(ty);
|
||||||
m_datatype2nonrec_constructor.insert(ty, result);
|
plugin().m_datatype2nonrec_constructor.insert(ty, result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1291,6 +1295,7 @@ namespace datatype {
|
||||||
IF_VERBOSE(0, verbose_stream() << f->get_name() << "\n");
|
IF_VERBOSE(0, verbose_stream() << f->get_name() << "\n");
|
||||||
for (constructor* c : d)
|
for (constructor* c : d)
|
||||||
IF_VERBOSE(0, verbose_stream() << "!= " << c->name() << "\n");
|
IF_VERBOSE(0, verbose_stream() << "!= " << c->name() << "\n");
|
||||||
|
return UINT_MAX;
|
||||||
SASSERT(false);
|
SASSERT(false);
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -198,6 +198,8 @@ namespace datatype {
|
||||||
def* translate(ast_translation& tr, util& u);
|
def* translate(ast_translation& tr, util& u);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::pair<func_decl*, unsigned> cnstr_depth;
|
||||||
|
|
||||||
namespace decl {
|
namespace decl {
|
||||||
|
|
||||||
class plugin : public decl_plugin {
|
class plugin : public decl_plugin {
|
||||||
|
@ -213,6 +215,7 @@ namespace datatype {
|
||||||
|
|
||||||
void log_axiom_definitions(symbol const& s, sort * new_sort);
|
void log_axiom_definitions(symbol const& s, sort * new_sort);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
plugin(): m_id_counter(0), m_class_id(0), m_has_nested_rec(false) {}
|
plugin(): m_id_counter(0), m_class_id(0), m_has_nested_rec(false) {}
|
||||||
~plugin() override;
|
~plugin() override;
|
||||||
|
@ -259,6 +262,25 @@ namespace datatype {
|
||||||
|
|
||||||
bool has_nested_rec() const { return m_has_nested_rec; }
|
bool has_nested_rec() const { return m_has_nested_rec; }
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
|
||||||
|
obj_map<sort, ptr_vector<func_decl>*> m_datatype2constructors;
|
||||||
|
obj_map<sort, cnstr_depth> m_datatype2nonrec_constructor;
|
||||||
|
obj_map<func_decl, ptr_vector<func_decl>*> m_constructor2accessors;
|
||||||
|
obj_map<func_decl, func_decl*> m_constructor2recognizer;
|
||||||
|
obj_map<func_decl, func_decl*> m_recognizer2constructor;
|
||||||
|
obj_map<func_decl, func_decl*> m_accessor2constructor;
|
||||||
|
obj_map<sort, bool> m_is_recursive;
|
||||||
|
obj_map<sort, bool> m_is_enum;
|
||||||
|
mutable obj_map<sort, bool> m_is_fully_interp;
|
||||||
|
mutable ast_ref_vector* m_asts = nullptr;
|
||||||
|
sref_vector<param_size::size> m_refs;
|
||||||
|
ptr_vector<ptr_vector<func_decl> > m_vectors;
|
||||||
|
unsigned m_start = 0;
|
||||||
|
mutable ptr_vector<sort> m_fully_interp_trail;
|
||||||
|
void add_ast(ast* a) const { if (!m_asts) m_asts = alloc(ast_ref_vector, *m_manager); m_asts->push_back(a); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_value_visit(bool unique, expr * arg, ptr_buffer<app> & todo) const;
|
bool is_value_visit(bool unique, expr * arg, ptr_buffer<app> & todo) const;
|
||||||
bool is_value_aux(bool unique, app * arg) const;
|
bool is_value_aux(bool unique, app * arg) const;
|
||||||
|
@ -295,25 +317,10 @@ namespace datatype {
|
||||||
ast_manager & m;
|
ast_manager & m;
|
||||||
mutable family_id m_family_id;
|
mutable family_id m_family_id;
|
||||||
mutable decl::plugin* m_plugin;
|
mutable decl::plugin* m_plugin;
|
||||||
typedef std::pair<func_decl*, unsigned> cnstr_depth;
|
|
||||||
|
|
||||||
family_id fid() const;
|
family_id fid() const;
|
||||||
|
|
||||||
obj_map<sort, ptr_vector<func_decl> *> m_datatype2constructors;
|
|
||||||
obj_map<sort, cnstr_depth> m_datatype2nonrec_constructor;
|
|
||||||
obj_map<func_decl, ptr_vector<func_decl> *> m_constructor2accessors;
|
|
||||||
obj_map<func_decl, func_decl *> m_constructor2recognizer;
|
|
||||||
obj_map<func_decl, func_decl *> m_recognizer2constructor;
|
|
||||||
obj_map<func_decl, func_decl *> m_accessor2constructor;
|
|
||||||
obj_map<sort, bool> m_is_recursive;
|
|
||||||
obj_map<sort, bool> m_is_enum;
|
|
||||||
mutable obj_map<sort, bool> m_is_fully_interp;
|
|
||||||
mutable ast_ref_vector m_asts;
|
|
||||||
sref_vector<param_size::size> m_refs;
|
|
||||||
ptr_vector<ptr_vector<func_decl> > m_vectors;
|
|
||||||
unsigned m_start;
|
|
||||||
mutable ptr_vector<sort> m_fully_interp_trail;
|
|
||||||
|
|
||||||
cnstr_depth get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set);
|
cnstr_depth get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set);
|
||||||
|
|
||||||
friend class decl::plugin;
|
friend class decl::plugin;
|
||||||
|
|
|
@ -97,42 +97,41 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct statistics {
|
struct statistics {
|
||||||
unsigned m_make_feasible;
|
unsigned m_make_feasible = 0;
|
||||||
unsigned m_total_iterations;
|
unsigned m_total_iterations = 0;
|
||||||
unsigned m_iters_with_no_cost_growing;
|
unsigned m_iters_with_no_cost_growing = 0;
|
||||||
unsigned m_num_factorizations;
|
unsigned m_num_factorizations = 0;
|
||||||
unsigned m_num_of_implied_bounds;
|
unsigned m_num_of_implied_bounds = 0;
|
||||||
unsigned m_need_to_solve_inf;
|
unsigned m_need_to_solve_inf = 0;
|
||||||
unsigned m_max_cols;
|
unsigned m_max_cols = 0;
|
||||||
unsigned m_max_rows;
|
unsigned m_max_rows = 0;
|
||||||
unsigned m_gcd_calls;
|
unsigned m_gcd_calls = 0;
|
||||||
unsigned m_gcd_conflicts;
|
unsigned m_gcd_conflicts = 0;
|
||||||
unsigned m_cube_calls;
|
unsigned m_cube_calls = 0;
|
||||||
unsigned m_cube_success;
|
unsigned m_cube_success = 0;
|
||||||
unsigned m_patches;
|
unsigned m_patches = 0;
|
||||||
unsigned m_patches_success;
|
unsigned m_patches_success = 0;
|
||||||
unsigned m_hnf_cutter_calls;
|
unsigned m_hnf_cutter_calls = 0;
|
||||||
unsigned m_hnf_cuts;
|
unsigned m_hnf_cuts = 0;
|
||||||
unsigned m_nla_calls;
|
unsigned m_nla_calls = 0;
|
||||||
unsigned m_gomory_cuts;
|
unsigned m_gomory_cuts = 0;
|
||||||
unsigned m_nla_add_bounds;
|
unsigned m_nla_add_bounds = 0;
|
||||||
unsigned m_nla_propagate_bounds;
|
unsigned m_nla_propagate_bounds = 0;
|
||||||
unsigned m_nla_propagate_eq;
|
unsigned m_nla_propagate_eq = 0;
|
||||||
unsigned m_nla_lemmas;
|
unsigned m_nla_lemmas = 0;
|
||||||
unsigned m_nra_calls;
|
unsigned m_nra_calls = 0;
|
||||||
unsigned m_nla_bounds_improvements;
|
unsigned m_nla_bounds_improvements = 0;
|
||||||
unsigned m_horner_calls;
|
unsigned m_horner_calls = 0;
|
||||||
unsigned m_horner_conflicts;
|
unsigned m_horner_conflicts = 0;
|
||||||
unsigned m_cross_nested_forms;
|
unsigned m_cross_nested_forms = 0;
|
||||||
unsigned m_grobner_calls;
|
unsigned m_grobner_calls = 0;
|
||||||
unsigned m_grobner_conflicts;
|
unsigned m_grobner_conflicts = 0;
|
||||||
unsigned m_offset_eqs;
|
unsigned m_offset_eqs = 0;
|
||||||
unsigned m_fixed_eqs;
|
unsigned m_fixed_eqs = 0;
|
||||||
::statistics m_st;
|
::statistics m_st = {};
|
||||||
statistics() { reset(); }
|
|
||||||
void reset() {
|
void reset() {
|
||||||
memset(this, 0, sizeof(*this));
|
*this = statistics{};
|
||||||
m_st.reset();
|
|
||||||
}
|
}
|
||||||
void collect_statistics(::statistics& st) const {
|
void collect_statistics(::statistics& st) const {
|
||||||
st.update("arith-factorizations", m_num_factorizations);
|
st.update("arith-factorizations", m_num_factorizations);
|
||||||
|
|
|
@ -79,7 +79,7 @@ public:
|
||||||
ref(static_matrix & m, unsigned row, unsigned col):m_matrix(m), m_row(row), m_col(col) {}
|
ref(static_matrix & m, unsigned row, unsigned col):m_matrix(m), m_row(row), m_col(col) {}
|
||||||
ref & operator=(T const & v) { m_matrix.set( m_row, m_col, v); return *this; }
|
ref & operator=(T const & v) { m_matrix.set( m_row, m_col, v); return *this; }
|
||||||
|
|
||||||
ref operator=(ref & v) { m_matrix.set(m_row, m_col, v.m_matrix.get(v.m_row, v.m_col)); return *this; }
|
ref operator=(ref & v) { m_matrix.set(m_row, m_col, v.m_matrix.get_elem(v.m_row, v.m_col)); return *this; }
|
||||||
|
|
||||||
operator T () const { return m_matrix.get_elem(m_row, m_col); }
|
operator T () const { return m_matrix.get_elem(m_row, m_col); }
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,7 +92,7 @@ static_matrix<T, X>::static_matrix(static_matrix const &A, unsigned * /* basis *
|
||||||
init_row_columns(m, m);
|
init_row_columns(m, m);
|
||||||
for (; m-- > 0; )
|
for (; m-- > 0; )
|
||||||
for (auto & col : A.m_columns[m])
|
for (auto & col : A.m_columns[m])
|
||||||
set(col.var(), m, A.get_value_of_column_cell(col));
|
set(col.var(), m, A.get_column_cell(col));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename X> void static_matrix<T, X>::clear() {
|
template <typename T, typename X> void static_matrix<T, X>::clear() {
|
||||||
|
|
|
@ -141,6 +141,8 @@ namespace nlsat {
|
||||||
auto& a = *to_ineq_atom(a1);
|
auto& a = *to_ineq_atom(a1);
|
||||||
if (a.size() != 2)
|
if (a.size() != 2)
|
||||||
continue;
|
continue;
|
||||||
|
if (a.is_root_atom())
|
||||||
|
continue;
|
||||||
|
|
||||||
auto* p = a.p(0);
|
auto* p = a.p(0);
|
||||||
auto* q = a.p(1);
|
auto* q = a.p(1);
|
||||||
|
@ -229,6 +231,10 @@ namespace nlsat {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
SASSERT(a.is_root_atom());
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
IF_VERBOSE(3,
|
IF_VERBOSE(3,
|
||||||
s.display(verbose_stream(), c) << " ->\n";
|
s.display(verbose_stream(), c) << " ->\n";
|
||||||
|
|
|
@ -101,7 +101,7 @@ struct mbp_basic_tg::impl {
|
||||||
bool is_or = m.is_or(term);
|
bool is_or = m.is_or(term);
|
||||||
app *c = to_app(term);
|
app *c = to_app(term);
|
||||||
bool t = is_or ? any_of(*c, is_true) : all_of(*c, is_true);
|
bool t = is_or ? any_of(*c, is_true) : all_of(*c, is_true);
|
||||||
bool f = is_or ? all_of(*c, is_false) : all_of(*c, is_false);
|
bool f = is_or ? all_of(*c, is_false) : any_of(*c, is_false);
|
||||||
if (t || f) {
|
if (t || f) {
|
||||||
mark_seen(term);
|
mark_seen(term);
|
||||||
progress = true;
|
progress = true;
|
||||||
|
|
|
@ -1,3 +1,20 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2024 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
tst_dlist.cpp
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Test dlist module
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Chuyue Sun 2024-07-18.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "util/dlist.h"
|
#include "util/dlist.h"
|
||||||
|
@ -160,10 +177,12 @@ void tst_dlist() {
|
||||||
test_pop();
|
test_pop();
|
||||||
test_insert_after();
|
test_insert_after();
|
||||||
test_insert_before();
|
test_insert_before();
|
||||||
|
#if 0
|
||||||
test_remove_from();
|
test_remove_from();
|
||||||
test_push_to_front();
|
test_push_to_front();
|
||||||
test_detach();
|
test_detach();
|
||||||
test_invariant();
|
test_invariant();
|
||||||
test_contains();
|
test_contains();
|
||||||
|
#endif
|
||||||
std::cout << "All tests passed." << std::endl;
|
std::cout << "All tests passed." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ Abstract:
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
Leonardo de Moura (leonardo) 2006-09-12.
|
Leonardo de Moura (leonardo) 2006-09-12.
|
||||||
|
Chuyue Sun (liviasun) 2024-07-18.
|
||||||
|
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
|
@ -20,7 +21,6 @@ Revision History:
|
||||||
#include<iostream>
|
#include<iostream>
|
||||||
#include<unordered_set>
|
#include<unordered_set>
|
||||||
#include<stdlib.h>
|
#include<stdlib.h>
|
||||||
|
|
||||||
#include "util/hashtable.h"
|
#include "util/hashtable.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -119,11 +119,126 @@ static void tst3() {
|
||||||
ENSURE(h2.size() == 2);
|
ENSURE(h2.size() == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom hash and equality functions for testing
|
||||||
|
struct my_hash {
|
||||||
|
unsigned operator()(int x) const { return x; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct my_eq {
|
||||||
|
bool operator()(int x, int y) const { return x == y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_hashtable_constructors() {
|
||||||
|
hashtable<int, my_hash, my_eq> ht;
|
||||||
|
VERIFY(ht.empty());
|
||||||
|
VERIFY(ht.size() == 0);
|
||||||
|
VERIFY(ht.capacity() == DEFAULT_HASHTABLE_INITIAL_CAPACITY);
|
||||||
|
|
||||||
|
// Copy constructor
|
||||||
|
hashtable<int, my_hash, my_eq> ht_copy(ht);
|
||||||
|
VERIFY(ht_copy.empty());
|
||||||
|
VERIFY(ht_copy.size() == 0);
|
||||||
|
VERIFY(ht_copy.capacity() == ht.capacity());
|
||||||
|
|
||||||
|
// Move constructor
|
||||||
|
hashtable<int, my_hash, my_eq> ht_move(std::move(ht));
|
||||||
|
VERIFY(ht_move.empty());
|
||||||
|
VERIFY(ht_move.size() == 0);
|
||||||
|
VERIFY(ht_move.capacity() == ht_copy.capacity());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_hashtable_insert() {
|
||||||
|
hashtable<int, my_hash, my_eq> ht;
|
||||||
|
ht.insert(1);
|
||||||
|
VERIFY(!ht.empty());
|
||||||
|
VERIFY(ht.size() == 1);
|
||||||
|
int value;
|
||||||
|
VERIFY(ht.find(1, value) && value == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_hashtable_remove() {
|
||||||
|
hashtable<int, my_hash, my_eq> ht;
|
||||||
|
ht.insert(1);
|
||||||
|
ht.remove(1);
|
||||||
|
VERIFY(ht.empty());
|
||||||
|
VERIFY(ht.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_hashtable_find() {
|
||||||
|
hashtable<int, my_hash, my_eq> ht;
|
||||||
|
ht.insert(1);
|
||||||
|
int value;
|
||||||
|
VERIFY(ht.find(1, value) && value == 1);
|
||||||
|
VERIFY(!ht.find(2, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_hashtable_contains() {
|
||||||
|
hashtable<int, my_hash, my_eq> ht;
|
||||||
|
ht.insert(1);
|
||||||
|
VERIFY(ht.contains(1));
|
||||||
|
VERIFY(!ht.contains(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_hashtable_reset() {
|
||||||
|
hashtable<int, my_hash, my_eq> ht;
|
||||||
|
ht.insert(1);
|
||||||
|
ht.reset();
|
||||||
|
VERIFY(ht.empty());
|
||||||
|
VERIFY(ht.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_hashtable_finalize() {
|
||||||
|
hashtable<int, my_hash, my_eq> ht;
|
||||||
|
ht.insert(1);
|
||||||
|
ht.finalize();
|
||||||
|
VERIFY(ht.empty());
|
||||||
|
VERIFY(ht.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_hashtable_iterators() {
|
||||||
|
hashtable<int, my_hash, my_eq> ht;
|
||||||
|
ht.insert(1);
|
||||||
|
ht.insert(2);
|
||||||
|
ht.insert(3);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for(auto it = ht.begin(); it != ht.end(); ++it) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
VERIFY(count == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_hashtable_operators() {
|
||||||
|
hashtable<int, my_hash, my_eq> ht1;
|
||||||
|
hashtable<int, my_hash, my_eq> ht2;
|
||||||
|
|
||||||
|
ht1.insert(1);
|
||||||
|
ht2.insert(2);
|
||||||
|
|
||||||
|
ht1 |= ht2;
|
||||||
|
VERIFY(ht1.contains(1));
|
||||||
|
VERIFY(ht1.contains(2));
|
||||||
|
|
||||||
|
ht1 &= ht2;
|
||||||
|
VERIFY(!ht1.contains(1));
|
||||||
|
VERIFY(ht1.contains(2));
|
||||||
|
}
|
||||||
|
|
||||||
void tst_hashtable() {
|
void tst_hashtable() {
|
||||||
tst3();
|
tst3();
|
||||||
for (int i = 0; i < 100; i++)
|
for (int i = 0; i < 100; i++)
|
||||||
tst2();
|
tst2();
|
||||||
tst1();
|
tst1();
|
||||||
|
test_hashtable_constructors();
|
||||||
|
test_hashtable_insert();
|
||||||
|
test_hashtable_remove();
|
||||||
|
test_hashtable_find();
|
||||||
|
test_hashtable_contains();
|
||||||
|
test_hashtable_reset();
|
||||||
|
test_hashtable_finalize();
|
||||||
|
test_hashtable_iterators();
|
||||||
|
test_hashtable_operators();
|
||||||
|
std::cout << "All tests passed!" << std::endl;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void tst_hashtable() {
|
void tst_hashtable() {
|
||||||
|
|
|
@ -155,23 +155,15 @@ public:
|
||||||
elem->init(elem);
|
elem->init(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool invariant() const {
|
bool invariant() const {
|
||||||
auto* e = this;
|
auto* e = this;
|
||||||
const T* slow = static_cast<const T*>(this);
|
do {
|
||||||
const T* fast = m_next;
|
if (e->m_next->m_prev != e)
|
||||||
bool looped = false;
|
return false;
|
||||||
// m_next of each node should point back to m_prev of the following node,
|
e = e->m_next;
|
||||||
// and m_prev of each node should point forward to m_next of the preceding node.
|
}
|
||||||
while (slow != fast) {
|
while (e != this);
|
||||||
if (fast->m_prev->m_next != fast || fast->m_next->m_prev != fast)
|
return true;
|
||||||
return false;
|
|
||||||
fast = fast->m_next;
|
|
||||||
looped = looped || (fast == static_cast<const T*>(this));
|
|
||||||
if (!looped && fast == m_next)
|
|
||||||
// We should be able to traverse back to the starting node.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool contains(T const* list, T const* elem) {
|
static bool contains(T const* list, T const* elem) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ Abstract:
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
Leonardo de Moura (leonardo) 2006-09-11.
|
Leonardo de Moura (leonardo) 2006-09-11.
|
||||||
|
Chuyue Sun (liviasun) 2024-07-18.
|
||||||
|
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
|
@ -639,6 +640,19 @@ public:
|
||||||
|
|
||||||
#ifdef Z3DEBUG
|
#ifdef Z3DEBUG
|
||||||
bool check_invariant() {
|
bool check_invariant() {
|
||||||
|
// The capacity must always be a power of two.
|
||||||
|
if (!is_power_of_two(m_capacity))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// The number of deleted plus the size must not exceed the capacity.
|
||||||
|
if (m_num_deleted + m_size > m_capacity)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Checking that m_num_deleted is less than or equal to m_size.
|
||||||
|
if (m_num_deleted > m_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
entry * curr = m_table;
|
entry * curr = m_table;
|
||||||
entry * end = m_table + m_capacity;
|
entry * end = m_table + m_capacity;
|
||||||
unsigned num_deleted = 0;
|
unsigned num_deleted = 0;
|
||||||
|
|
|
@ -36,6 +36,7 @@ void permutation::swap(unsigned i, unsigned j) noexcept {
|
||||||
unsigned j_prime = m_p[j];
|
unsigned j_prime = m_p[j];
|
||||||
std::swap(m_p[i], m_p[j]);
|
std::swap(m_p[i], m_p[j]);
|
||||||
std::swap(m_inv_p[i_prime], m_inv_p[j_prime]);
|
std::swap(m_inv_p[i_prime], m_inv_p[j_prime]);
|
||||||
|
SASSERT(check_invariant());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,11 +67,19 @@ void permutation::display(std::ostream & out) const {
|
||||||
bool permutation::check_invariant() const {
|
bool permutation::check_invariant() const {
|
||||||
SASSERT(m_p.size() == m_inv_p.size());
|
SASSERT(m_p.size() == m_inv_p.size());
|
||||||
unsigned n = m_p.size();
|
unsigned n = m_p.size();
|
||||||
|
bool_vector check_vector(n, false); // To check for duplicate and out-of-range values
|
||||||
for (unsigned i = 0; i < n; i++) {
|
for (unsigned i = 0; i < n; i++) {
|
||||||
|
unsigned pi = m_p[i];
|
||||||
SASSERT(m_p[i] < n);
|
SASSERT(m_p[i] < n);
|
||||||
SASSERT(m_inv_p[i] < n);
|
SASSERT(m_inv_p[i] < n);
|
||||||
SASSERT(m_p[m_inv_p[i]] == i);
|
SASSERT(m_p[m_inv_p[i]] == i);
|
||||||
SASSERT(m_inv_p[m_p[i]] == i);
|
SASSERT(m_inv_p[m_p[i]] == i);
|
||||||
|
// Check the inversion hasn't been checked yet
|
||||||
|
if (check_vector[pi]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Mark this value as checked
|
||||||
|
check_vector[pi] = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue