From b2b3bab246840f077b21f4b0c5a6e667acb8bdc4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jun 2024 09:15:55 -0700 Subject: [PATCH 001/187] Bump docker/build-push-action from 6.0.0 to 6.1.0 (#7265) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.0.0 to 6.1.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.0.0...v6.1.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index fe4d7c6e6..d778bed3b 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -41,7 +41,7 @@ jobs: type=edge type=sha,prefix=ubuntu-20.04-bare-z3-sha- - name: Build and push Bare Z3 Docker Image - uses: docker/build-push-action@v6.0.0 + uses: docker/build-push-action@v6.1.0 with: context: . push: true From 8de2544abb559b57c0406c9198a9b046a97c35ee Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 30 Jun 2024 16:06:44 -0700 Subject: [PATCH 002/187] set clean shutdown for local search and re-enable local search when it parallelizes with PB solver Signed-off-by: Nikolaj Bjorner --- src/sat/sat_local_search.cpp | 7 ++++--- src/sat/sat_parallel.cpp | 6 ++++++ src/sat/sat_parallel.h | 2 ++ src/sat/sat_solver.cpp | 18 ++++++++++++------ 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/sat/sat_local_search.cpp b/src/sat/sat_local_search.cpp index c3cb0fb37..6e5d3fae3 100644 --- a/src/sat/sat_local_search.cpp +++ b/src/sat/sat_local_search.cpp @@ -362,7 +362,7 @@ namespace sat { set_phase(i, phase[i]); } - void local_search::import(solver const& s, bool _init) { + void local_search::import(solver const& s, bool _init) { flet linit(m_initializing, true); m_is_pb = false; m_vars.reset(); @@ -412,9 +412,10 @@ namespace sat { [&](unsigned sz, literal const* c, unsigned k) { add_cardinality(sz, c, k); }; std::function pb = [&](unsigned sz, literal const* c, unsigned const* coeffs, unsigned k) { add_pb(sz, c, coeffs, k); }; - if (ext && (!ext->is_pb() || !ext->extract_pb(card, pb))) + if (ext && (!ext->is_pb() || !ext->extract_pb(card, pb))) { + IF_VERBOSE(0, verbose_stream() << (ext) << " is-pb " << (!ext && ext->is_pb()) << "\n"); throw default_exception("local search is incomplete with extensions beyond PB"); - + } if (_init) init(); } diff --git a/src/sat/sat_parallel.cpp b/src/sat/sat_parallel.cpp index f7b54b998..7d5c022ff 100644 --- a/src/sat/sat_parallel.cpp +++ b/src/sat/sat_parallel.cpp @@ -87,9 +87,15 @@ namespace sat { parallel::parallel(solver& s): m_num_clauses(0), m_consumer_ready(false), m_scoped_rlimit(s.rlimit()) {} parallel::~parallel() { + reset(); + } + + void parallel::reset() { m_limits.reset(); + m_scoped_rlimit.reset(); for (auto* s : m_solvers) dealloc(s); + m_solvers.reset(); } void parallel::init_solvers(solver& s, unsigned num_extra_solvers) { diff --git a/src/sat/sat_parallel.h b/src/sat/sat_parallel.h index 65ae09183..0fbf4f05d 100644 --- a/src/sat/sat_parallel.h +++ b/src/sat/sat_parallel.h @@ -78,6 +78,8 @@ namespace sat { ~parallel(); + void reset(); + void init_solvers(solver& s, unsigned num_extra_solvers); void push_child(reslimit& rl); diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index 1cd0c1400..2589c51b8 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -1243,8 +1243,11 @@ namespace sat { m_cleaner(true); return do_local_search(num_lits, lits); } - if ((m_config.m_num_threads > 1 || m_config.m_local_search_threads > 0 || - m_config.m_ddfw_threads > 0) && !m_par && !m_ext) { + if ((m_config.m_num_threads > 1 || m_config.m_ddfw_threads > 0) && !m_par && !m_ext) { + SASSERT(scope_lvl() == 0); + return check_par(num_lits, lits); + } + if (m_config.m_local_search_threads > 0 && !m_par && (!m_ext || m_ext->is_pb())) { SASSERT(scope_lvl() == 0); return check_par(num_lits, lits); } @@ -1460,15 +1463,17 @@ namespace sat { if (!rlimit().inc()) { return l_undef; } - if (m_ext) + if (m_ext && !m_ext->is_pb()) return l_undef; - scoped_ptr_vector ls; - scoped_ptr_vector uw; + int num_extra_solvers = m_config.m_num_threads - 1; int num_local_search = static_cast(m_config.m_local_search_threads); int num_ddfw = m_ext ? 0 : static_cast(m_config.m_ddfw_threads); int num_threads = num_extra_solvers + 1 + num_local_search + num_ddfw; + vector lims(num_ddfw); + scoped_ptr_vector ls; + scoped_ptr_vector uw; for (int i = 0; i < num_local_search; ++i) { local_search* l = alloc(local_search); l->updt_params(m_params); @@ -1477,7 +1482,7 @@ namespace sat { ls.push_back(l); } - vector lims(num_ddfw); + // set up ddfw search for (int i = 0; i < num_ddfw; ++i) { ddfw* d = alloc(ddfw); @@ -1593,6 +1598,7 @@ namespace sat { if (!canceled) { rlimit().reset_cancel(); } + par.reset(); set_par(nullptr, 0); ls.reset(); uw.reset(); From facc7d8de2725ba7e231442ed0866d2c0bf4d4cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:43:36 -0700 Subject: [PATCH 003/187] Bump docker/build-push-action from 6.1.0 to 6.2.0 (#7269) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.1.0 to 6.2.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.1.0...v6.2.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index d778bed3b..4f34fb3d7 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -41,7 +41,7 @@ jobs: type=edge type=sha,prefix=ubuntu-20.04-bare-z3-sha- - name: Build and push Bare Z3 Docker Image - uses: docker/build-push-action@v6.1.0 + uses: docker/build-push-action@v6.2.0 with: context: . push: true From 1da132005a473a8a2e4f10cd9f90daf9563c496a Mon Sep 17 00:00:00 2001 From: Sergey Bronnikov Date: Tue, 2 Jul 2024 17:09:33 +0300 Subject: [PATCH 004/187] Fix a comment for Z3_solver_from_string (#7271) Z3_solver_from_string accepts a string buffer with solver assertions, not a string buffer with filename. --- src/api/z3_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index dacf4b578..1f0daf8b5 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -7018,7 +7018,7 @@ extern "C" { def_API('Z3_solver_from_string', VOID, (_in(CONTEXT), _in(SOLVER), _in(STRING))) */ - void Z3_API Z3_solver_from_string(Z3_context c, Z3_solver s, Z3_string file_name); + void Z3_API Z3_solver_from_string(Z3_context c, Z3_solver s, Z3_string str); /** \brief Return the set of asserted formulas on the solver. From 18b6087b72d934bef29f06f3649411debeeb1ed1 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 8 Jul 2024 11:43:24 -0700 Subject: [PATCH 005/187] trigger the build with a comment change Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_solver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index 26c2f617b..bb169a05e 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -7,7 +7,7 @@ Module Name: Abstract: - Nonlinear arithmetic satisfiability procedure. The procedure is + Nonlinear arithmetic satisfiability procedure. The procedure is complete for nonlinear real arithmetic, but it also has limited support for integers. From 6e069c1f4126d7a5721cfedf106a0ff298f33ee3 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 8 Jul 2024 13:56:23 -0700 Subject: [PATCH 006/187] remove macro distinction #7270 --- src/cmd_context/cmd_context.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index e883d0e9d..231c78bc2 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -1070,9 +1070,11 @@ void cmd_context::insert_rec_fun(func_decl* f, expr_ref_vector const& binding, s } func_decl * cmd_context::find_func_decl(symbol const & s) const { +#if 0 if (contains_macro(s)) { throw cmd_exception("invalid function declaration reference, named expressions (aka macros) cannot be referenced ", s); } +#endif func_decls fs; if (m_func_decls.find(s, fs)) { if (fs.more_than_one()) From af1f0e318422f7030f24e20acd057f84b7b53f16 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 8 Jul 2024 14:50:38 -0700 Subject: [PATCH 007/187] fix #7268 --- src/model/model.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/model/model.cpp b/src/model/model.cpp index c89ff59a2..362907e46 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -248,6 +248,7 @@ void model::compress(bool force_inline) { // by substituting in auxiliary definitions that can be eliminated. func_decl_ref_vector pinned(m); + ptr_vector sorted_decls; while (true) { top_sort ts(m); collect_deps(ts); @@ -259,6 +260,7 @@ void model::compress(bool force_inline) { ts.m_occur_count.reset(); for (func_decl * f : ts.top_sorted()) collect_occs(ts, f); + sorted_decls.reset(); // remove auxiliary declarations that are not used. for (func_decl * f : ts.top_sorted()) { @@ -267,11 +269,13 @@ void model::compress(bool force_inline) { unregister_decl(f); removed.insert(f); } + else + sorted_decls.push_back(f); } + std::swap(m_decls, sorted_decls); if (removed.empty()) break; TRACE("model", tout << "remove\n"; for (func_decl* f : removed) tout << f->get_name() << "\n";); - remove_decls(m_decls, removed); remove_decls(m_func_decls, removed); remove_decls(m_const_decls, removed); } From 374609bd46d481801ae7905c87592a7aff273e0e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 8 Jul 2024 16:54:09 -0700 Subject: [PATCH 008/187] kludge to address #7232, probably superseeded by planned revision to setup/pypi Signed-off-by: Nikolaj Bjorner --- src/api/python/setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/python/setup.py b/src/api/python/setup.py index 5faf5aad1..c7af0e646 100644 --- a/src/api/python/setup.py +++ b/src/api/python/setup.py @@ -277,7 +277,7 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv: # linux builds should be built in the centos 5 vm for maximum compatibility # see https://github.com/pypa/manylinux # see also https://github.com/angr/angr-dev/blob/master/admin/bdist.py - plat_name = 'manylinux2014_' + platform.machine() + plat_name = 'manylinux_2_28_' + platform.machine() elif 'mingw' in name: if platform.architecture()[0] == '64bit': plat_name = 'win_amd64' @@ -296,7 +296,7 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv: ) elif distos == 'glibc': if arch == 'x64': - plat_name = 'manylinux2014_x86_64' + plat_name = 'manylinux_2_28_x86_64' elif arch == 'arm64' or arch == 'aarch64': # context on why are we match on arm64 # but use aarch64 on the plat_name is @@ -305,9 +305,9 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv: # so using the currently supported arm64 # build and simply rename it to aarch64 # see full context on #7148 - plat_name = 'manylinux2014_aarch64' + plat_name = 'manylinux_2_28_aarch64' else: - plat_name = 'manylinux2014_i686' + plat_name = 'manylinux_2_28_i686' elif distos == 'linux' and os_id == 'alpine': if arch == 'x64': plat_name = 'musllinux_1_1_x86_64' From b0069010f86dcc071fa6863a433a04d38126cfb5 Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Mon, 15 Jul 2024 13:07:12 -0700 Subject: [PATCH 009/187] add new ema invariant (#7288) --- src/util/ema.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/ema.h b/src/util/ema.h index 9e18fb98f..99491bc72 100644 --- a/src/util/ema.h +++ b/src/util/ema.h @@ -23,7 +23,7 @@ Revision History: class ema { double m_alpha, m_beta, m_value; unsigned m_period, m_wait; - bool invariant() const { return 0 <= m_alpha && m_alpha <= m_beta && m_beta <= 1; } + bool invariant() const { return 0 <= m_alpha && m_alpha <= m_beta && m_beta <= 1 && m_wait <= m_period; } public: ema(): m_alpha(0), m_beta(1), m_value(0), m_period(0), m_wait(0) { SASSERT(invariant()); From a2c3ce5c8b7105f9379bf2aa52efc9dc4b14c670 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 13:07:37 -0700 Subject: [PATCH 010/187] Bump docker/build-push-action from 6.2.0 to 6.3.0 (#7280) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.2.0 to 6.3.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.2.0...v6.3.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 4f34fb3d7..9665dec7a 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -41,7 +41,7 @@ jobs: type=edge type=sha,prefix=ubuntu-20.04-bare-z3-sha- - name: Build and push Bare Z3 Docker Image - uses: docker/build-push-action@v6.2.0 + uses: docker/build-push-action@v6.3.0 with: context: . push: true From 9073da4ee63abd4ea069a4444db6d1d66da57ed0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 16:54:27 -0700 Subject: [PATCH 011/187] Bump docker/build-push-action from 6.3.0 to 6.4.0 (#7289) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.3.0 to 6.4.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.3.0...v6.4.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 9665dec7a..3c02e2c2b 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -41,7 +41,7 @@ jobs: type=edge type=sha,prefix=ubuntu-20.04-bare-z3-sha- - name: Build and push Bare Z3 Docker Image - uses: docker/build-push-action@v6.3.0 + uses: docker/build-push-action@v6.4.0 with: context: . push: true From cf4d0e74a53428192d5c4cb8d5a033431828deb2 Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Thu, 18 Jul 2024 10:06:58 -0700 Subject: [PATCH 012/187] New invariant for dlist (#7294) * unit tests for dlist.h * new invariant for dlist: should be circular. avoid infinite loop * remove dlist test commit * format * format * Update dlist.h --------- Co-authored-by: Nikolaj Bjorner --- src/util/dlist.h | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/util/dlist.h b/src/util/dlist.h index 4c0e51e58..52cb25548 100644 --- a/src/util/dlist.h +++ b/src/util/dlist.h @@ -155,15 +155,23 @@ public: elem->init(elem); } - bool invariant() const { - auto* e = this; - do { - if (e->m_next->m_prev != e) - return false; - e = e->m_next; - } - while (e != this); - return true; + bool invariant() const { + auto* e = this; + const T* slow = static_cast(this); + const T* fast = m_next; + bool looped = false; + // m_next of each node should point back to m_prev of the following node, + // and m_prev of each node should point forward to m_next of the preceding node. + while (slow != fast) { + if (fast->m_prev->m_next != fast || fast->m_next->m_prev != fast) + return false; + fast = fast->m_next; + looped = looped || (fast == static_cast(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) { From 9803e9ef6e35e4087182c02f151c317360ab2e09 Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Thu, 18 Jul 2024 10:08:41 -0700 Subject: [PATCH 013/187] unit tests for dlist.h (#7293) --- src/test/CMakeLists.txt | 1 + src/test/dlist.cpp | 170 ++++++++++++++++++++++++++++++++++++++++ src/test/main.cpp | 1 + 3 files changed, 172 insertions(+) create mode 100644 src/test/dlist.cpp diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 4ddc1b8cb..a273d4e77 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -37,6 +37,7 @@ add_executable(test-z3 dl_table.cpp dl_util.cpp doc.cpp + dlist.cpp egraph.cpp escaped.cpp euf_bv_plugin.cpp diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp new file mode 100644 index 000000000..81689699f --- /dev/null +++ b/src/test/dlist.cpp @@ -0,0 +1,170 @@ +#include +#include +#include "util/dlist.h" + +class TestNode : public dll_base { +public: + int value; + TestNode(int val) : value(val) { + init(this); + } +}; + +// Test the prev() method +void test_prev() { + TestNode node(1); + assert(node.prev() == &node); + std::cout << "test_prev passed." << std::endl; +} + +// Test the next() method +void test_next() { + TestNode node(1); + assert(node.next() == &node); + std::cout << "test_next passed." << std::endl; +} + +// Test the const prev() method +void test_const_prev() { + const TestNode node(1); + assert(node.prev() == &node); + std::cout << "test_const_prev passed." << std::endl; +} + +// Test the const next() method +void test_const_next() { + const TestNode node(1); + assert(node.next() == &node); + std::cout << "test_const_next passed." << std::endl; +} + +// Test the init() method +void test_init() { + TestNode node(1); + node.init(&node); + assert(node.next() == &node); + assert(node.prev() == &node); + assert(node.invariant()); + std::cout << "test_init passed." << std::endl; +} + +// Test the pop() method +void test_pop() { + TestNode* list = nullptr; + TestNode node1(1); + TestNode::push_to_front(list, &node1); + TestNode* popped = TestNode::pop(list); + assert(popped == &node1); + assert(list == nullptr); + assert(popped->next() == popped); + assert(popped->prev() == popped); + std::cout << "test_pop passed." << std::endl; +} + +// Test the insert_after() method +void test_insert_after() { + TestNode node1(1); + TestNode node2(2); + node1.insert_after(&node2); + assert(node1.next() == &node2); + assert(node2.prev() == &node1); + assert(node1.prev() == &node2); + assert(node2.next() == &node1); + assert(node1.invariant()); + assert(node2.invariant()); + std::cout << "test_insert_after passed." << std::endl; +} + +// Test the insert_before() method +void test_insert_before() { + TestNode node1(1); + TestNode node2(2); + node1.insert_before(&node2); + assert(node1.prev() == &node2); + assert(node2.next() == &node1); + assert(node1.next() == &node2); + assert(node2.prev() == &node1); + assert(node1.invariant()); + assert(node2.invariant()); + std::cout << "test_insert_before passed." << std::endl; +} + +// Test the remove_from() method +void test_remove_from() { + TestNode* list = nullptr; + TestNode node1(1); + TestNode node2(2); + TestNode::push_to_front(list, &node1); + TestNode::push_to_front(list, &node2); + TestNode::remove_from(list, &node1); + assert(list == &node2); + assert(node2.next() == &node2); + assert(node2.prev() == &node2); + assert(node1.next() == &node1); + assert(node1.prev() == &node1); + std::cout << "test_remove_from passed." << std::endl; +} + +// Test the push_to_front() method +void test_push_to_front() { + TestNode* list = nullptr; + TestNode node1(1); + TestNode::push_to_front(list, &node1); + assert(list == &node1); + assert(node1.next() == &node1); + assert(node1.prev() == &node1); + std::cout << "test_push_to_front passed." << std::endl; +} + +// Test the detach() method +void test_detach() { + TestNode node(1); + TestNode::detach(&node); + assert(node.next() == &node); + assert(node.prev() == &node); + assert(node.invariant()); + std::cout << "test_detach passed." << std::endl; +} + +// Test the invariant() method +void test_invariant() { + TestNode node1(1); + assert(node1.invariant()); + TestNode node2(2); + node1.insert_after(&node2); + assert(node1.invariant()); + assert(node2.invariant()); + std::cout << "test_invariant passed." << std::endl; +} + +// Test the contains() method +void test_contains() { + TestNode* list = nullptr; + TestNode node1(1); + TestNode node2(2); + TestNode::push_to_front(list, &node1); + TestNode::push_to_front(list, &node2); + assert(TestNode::contains(list, &node1)); + assert(TestNode::contains(list, &node2)); + TestNode node3(3); + assert(!TestNode::contains(list, &node3)); + std::cout << "test_contains passed." << std::endl; +} + +int tst_dlist() { + test_prev(); + test_next(); + test_const_prev(); + test_const_next(); + test_init(); + test_pop(); + test_insert_after(); + test_insert_before(); + test_remove_from(); + test_push_to_front(); + test_detach(); + test_invariant(); + test_contains(); + std::cout << "All tests passed." << std::endl; + return 0; +} diff --git a/src/test/main.cpp b/src/test/main.cpp index 0c3d0e01a..0d3679529 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -188,6 +188,7 @@ int main(int argc, char ** argv) { TST(total_order); TST(dl_table); TST(dl_context); + TST(dlist); TST(dl_util); TST(dl_product_relation); TST(dl_relation); From 458d8b033abc60682dd1efbed06b5ad119821ac3 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 18 Jul 2024 10:07:35 -0700 Subject: [PATCH 014/187] remove wsp Signed-off-by: Nikolaj Bjorner --- src/sat/smt/euf_solver.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sat/smt/euf_solver.h b/src/sat/smt/euf_solver.h index 22e68d2da..1b13d5137 100644 --- a/src/sat/smt/euf_solver.h +++ b/src/sat/smt/euf_solver.h @@ -237,8 +237,6 @@ namespace euf { eq_proof_hint* mk_hint(symbol const& th, literal lit); - - void init_proof(); void on_clause(unsigned n, literal const* lits, sat::status st) override; void on_lemma(unsigned n, literal const* lits, sat::status st); From 08b6338061b73dd940ece4e0d61a949ab5420c0e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 18 Jul 2024 10:19:57 -0700 Subject: [PATCH 015/187] fix signature Signed-off-by: Nikolaj Bjorner --- src/test/CMakeLists.txt | 2 +- src/test/dlist.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index a273d4e77..8464cedf9 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -36,7 +36,7 @@ add_executable(test-z3 dl_relation.cpp dl_table.cpp dl_util.cpp - doc.cpp + doc.cpp dlist.cpp egraph.cpp escaped.cpp diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp index 81689699f..dfc1138b7 100644 --- a/src/test/dlist.cpp +++ b/src/test/dlist.cpp @@ -151,7 +151,7 @@ void test_contains() { std::cout << "test_contains passed." << std::endl; } -int tst_dlist() { +void tst_dlist() { test_prev(); test_next(); test_const_prev(); @@ -166,5 +166,4 @@ int tst_dlist() { test_invariant(); test_contains(); std::cout << "All tests passed." << std::endl; - return 0; } From bc636d7ee00b7ead1de4e9537930fce9d85a958d Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:01:42 -0700 Subject: [PATCH 016/187] new hashtable.h invariants (#7296) * add copyright for dlist unit test * new hashtable invariants * add copyright --- src/test/dlist.cpp | 17 +++++++++++++++++ src/util/hashtable.h | 14 ++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp index dfc1138b7..200a0a329 100644 --- a/src/test/dlist.cpp +++ b/src/test/dlist.cpp @@ -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 #include #include "util/dlist.h" diff --git a/src/util/hashtable.h b/src/util/hashtable.h index b59a2e7d8..acbe2a818 100644 --- a/src/util/hashtable.h +++ b/src/util/hashtable.h @@ -12,6 +12,7 @@ Abstract: Author: Leonardo de Moura (leonardo) 2006-09-11. + Chuyue Sun (liviasun) 2024-07-18. Revision History: @@ -639,6 +640,19 @@ public: #ifdef Z3DEBUG 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 * end = m_table + m_capacity; unsigned num_deleted = 0; From 80ac7b34387cddb88f2286b0716dd44ede982b78 Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:03:21 -0700 Subject: [PATCH 017/187] new heap invariants (#7298) * new heap invariants * change ENSURE to SASSERT for unit test heap * change SASSERT to VERIFY --- src/test/heap.cpp | 24 +++++++++++++----------- src/util/heap.h | 13 +++++++++++++ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/test/heap.cpp b/src/test/heap.cpp index 6a5bc7b9f..f30f45c32 100644 --- a/src/test/heap.cpp +++ b/src/test/heap.cpp @@ -38,7 +38,7 @@ static void tst1() { for (int i = 0; i < N * 3; i++) { int val = heap_rand() % N; if (!h.contains(val)) { - ENSURE(!t.contains(val)); + VERIFY(!t.contains(val)); h.insert(val); t.insert(val); } @@ -46,26 +46,26 @@ static void tst1() { if (!t.contains(val)) { for (int v : t) std::cout << v << "\n"; } - ENSURE(t.contains(val)); + VERIFY(t.contains(val)); } } - ENSURE(h.check_invariant()); + VERIFY(h.check_invariant()); for (int v : t) { - ENSURE(h.contains(v)); + VERIFY(h.contains(v)); } while (!h.empty()) { int m1 = h.min_value(); int m2 = h.erase_min(); (void)m1; (void)m2; - ENSURE(m1 == m2); - ENSURE(-1 < m2); + VERIFY(m1 == m2); + VERIFY(-1 < m2); } } int g_value[N]; -struct lt_proc2 { bool operator()(int v1, int v2) const { ENSURE(v1 < N && v2 < N); return g_value[v1] < g_value[v2]; } }; +struct lt_proc2 { bool operator()(int v1, int v2) const { VERIFY(v1 < N && v2 < N); return g_value[v1] < g_value[v2]; } }; typedef heap int_heap2; static void init_values() { @@ -98,7 +98,7 @@ static void tst2() { TRACE("heap", tout << "inserting: " << val << "\n";); h.insert(val); TRACE("heap", dump_heap(h, tout);); - ENSURE(h.contains(val)); + VERIFY(h.contains(val)); } } else if (cmd <= 6) { @@ -107,7 +107,7 @@ static void tst2() { TRACE("heap", tout << "removing: " << val << "\n";); h.erase(val); TRACE("heap", dump_heap(h, tout);); - ENSURE(!h.contains(val)); + VERIFY(!h.contains(val)); } } else if (cmd <= 8) { @@ -128,10 +128,12 @@ static void tst2() { } } else { - ENSURE(h.check_invariant()); + VERIFY(h.check_invariant()); } } - ENSURE(h.check_invariant()); + VERIFY(h.check_invariant()); + h.reset(); + VERIFY(h.check_invariant()); } void tst_heap() { diff --git a/src/util/heap.h b/src/util/heap.h index c080c6ebd..3bee2fe9f 100644 --- a/src/util/heap.h +++ b/src/util/heap.h @@ -55,6 +55,19 @@ class heap : private LT { } bool check_invariant_core(int idx) const { + + // Check that m_values starts with a dummy value at index 0. + if (m_values.empty() || m_values[0] != -1) { + return false; + } + + // All indices in m_value2indices that are not used in m_values should be 0 + for (int val = 0; val < static_cast(m_value2indices.size()); ++val) { + if (std::find(m_values.begin(), m_values.end(), val) == m_values.end() && m_value2indices[val] != 0) { + return false; // Unused indices should have a 0 value + } + } + if (idx < static_cast(m_values.size())) { SASSERT(m_value2indices[m_values[idx]] == idx); SASSERT(parent(idx) == 0 || !less_than(m_values[idx], m_values[parent(idx)])); From 5003d41cdbc392eacea5d73d1065259ec9a0dadf Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 19 Jul 2024 19:11:54 -0700 Subject: [PATCH 018/187] Revert "New invariant for dlist (#7294)" (#7301) This reverts commit cf4d0e74a53428192d5c4cb8d5a033431828deb2. --- src/util/dlist.h | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/util/dlist.h b/src/util/dlist.h index 52cb25548..4c0e51e58 100644 --- a/src/util/dlist.h +++ b/src/util/dlist.h @@ -155,23 +155,15 @@ public: elem->init(elem); } - bool invariant() const { - auto* e = this; - const T* slow = static_cast(this); - const T* fast = m_next; - bool looped = false; - // m_next of each node should point back to m_prev of the following node, - // and m_prev of each node should point forward to m_next of the preceding node. - while (slow != fast) { - if (fast->m_prev->m_next != fast || fast->m_next->m_prev != fast) - return false; - fast = fast->m_next; - looped = looped || (fast == static_cast(this)); - if (!looped && fast == m_next) - // We should be able to traverse back to the starting node. - return false; - } - return true; + bool invariant() const { + auto* e = this; + do { + if (e->m_next->m_prev != e) + return false; + e = e->m_next; + } + while (e != this); + return true; } static bool contains(T const* list, T const* elem) { From 49dc1bb721519601b36e3922f1f793e3ca71a7d5 Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Fri, 19 Jul 2024 19:27:23 -0700 Subject: [PATCH 019/187] add new permutation class invariant (#7299) * new heap invariants * change ENSURE to SASSERT for unit test heap * change SASSERT to VERIFY * new permutation invariant * remove heap changes * use bool_vector --- src/util/permutation.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/util/permutation.cpp b/src/util/permutation.cpp index 8b7adedf3..47b9d85a1 100644 --- a/src/util/permutation.cpp +++ b/src/util/permutation.cpp @@ -36,6 +36,7 @@ void permutation::swap(unsigned i, unsigned j) noexcept { unsigned j_prime = m_p[j]; std::swap(m_p[i], m_p[j]); 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 { SASSERT(m_p.size() == m_inv_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++) { + unsigned pi = m_p[i]; SASSERT(m_p[i] < n); SASSERT(m_inv_p[i] < n); SASSERT(m_p[m_inv_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; } From 3d014f8b335a3ed88fbdae0265d46bae9b196399 Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Fri, 19 Jul 2024 20:34:29 -0700 Subject: [PATCH 020/187] add new hashtable unit tests (#7297) * add new hashtable unit tests * add copyright * use VERIFY instead of assert --- src/test/hashtable.cpp | 117 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/src/test/hashtable.cpp b/src/test/hashtable.cpp index fb8042dc7..e26fbd5d8 100644 --- a/src/test/hashtable.cpp +++ b/src/test/hashtable.cpp @@ -12,6 +12,7 @@ Abstract: Author: Leonardo de Moura (leonardo) 2006-09-12. + Chuyue Sun (liviasun) 2024-07-18. Revision History: @@ -20,7 +21,6 @@ Revision History: #include #include #include - #include "util/hashtable.h" @@ -119,11 +119,126 @@ static void tst3() { 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 ht; + VERIFY(ht.empty()); + VERIFY(ht.size() == 0); + VERIFY(ht.capacity() == DEFAULT_HASHTABLE_INITIAL_CAPACITY); + + // Copy constructor + hashtable ht_copy(ht); + VERIFY(ht_copy.empty()); + VERIFY(ht_copy.size() == 0); + VERIFY(ht_copy.capacity() == ht.capacity()); + + // Move constructor + hashtable 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 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 ht; + ht.insert(1); + ht.remove(1); + VERIFY(ht.empty()); + VERIFY(ht.size() == 0); +} + +void test_hashtable_find() { + hashtable ht; + ht.insert(1); + int value; + VERIFY(ht.find(1, value) && value == 1); + VERIFY(!ht.find(2, value)); +} + +void test_hashtable_contains() { + hashtable ht; + ht.insert(1); + VERIFY(ht.contains(1)); + VERIFY(!ht.contains(2)); +} + +void test_hashtable_reset() { + hashtable ht; + ht.insert(1); + ht.reset(); + VERIFY(ht.empty()); + VERIFY(ht.size() == 0); +} + +void test_hashtable_finalize() { + hashtable ht; + ht.insert(1); + ht.finalize(); + VERIFY(ht.empty()); + VERIFY(ht.size() == 0); +} + +void test_hashtable_iterators() { + hashtable 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 ht1; + hashtable 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() { tst3(); for (int i = 0; i < 100; i++) tst2(); 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 void tst_hashtable() { From 966c9a3764dd760efc079b1ee3a5732210c4a8ac Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 21 Jul 2024 21:07:09 -0700 Subject: [PATCH 021/187] Revert "new heap invariants (#7298)" (#7303) This reverts commit 80ac7b34387cddb88f2286b0716dd44ede982b78. --- src/test/heap.cpp | 24 +++++++++++------------- src/util/heap.h | 13 ------------- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/src/test/heap.cpp b/src/test/heap.cpp index f30f45c32..6a5bc7b9f 100644 --- a/src/test/heap.cpp +++ b/src/test/heap.cpp @@ -38,7 +38,7 @@ static void tst1() { for (int i = 0; i < N * 3; i++) { int val = heap_rand() % N; if (!h.contains(val)) { - VERIFY(!t.contains(val)); + ENSURE(!t.contains(val)); h.insert(val); t.insert(val); } @@ -46,26 +46,26 @@ static void tst1() { if (!t.contains(val)) { for (int v : t) std::cout << v << "\n"; } - VERIFY(t.contains(val)); + ENSURE(t.contains(val)); } } - VERIFY(h.check_invariant()); + ENSURE(h.check_invariant()); for (int v : t) { - VERIFY(h.contains(v)); + ENSURE(h.contains(v)); } while (!h.empty()) { int m1 = h.min_value(); int m2 = h.erase_min(); (void)m1; (void)m2; - VERIFY(m1 == m2); - VERIFY(-1 < m2); + ENSURE(m1 == m2); + ENSURE(-1 < m2); } } int g_value[N]; -struct lt_proc2 { bool operator()(int v1, int v2) const { VERIFY(v1 < N && v2 < N); return g_value[v1] < g_value[v2]; } }; +struct lt_proc2 { bool operator()(int v1, int v2) const { ENSURE(v1 < N && v2 < N); return g_value[v1] < g_value[v2]; } }; typedef heap int_heap2; static void init_values() { @@ -98,7 +98,7 @@ static void tst2() { TRACE("heap", tout << "inserting: " << val << "\n";); h.insert(val); TRACE("heap", dump_heap(h, tout);); - VERIFY(h.contains(val)); + ENSURE(h.contains(val)); } } else if (cmd <= 6) { @@ -107,7 +107,7 @@ static void tst2() { TRACE("heap", tout << "removing: " << val << "\n";); h.erase(val); TRACE("heap", dump_heap(h, tout);); - VERIFY(!h.contains(val)); + ENSURE(!h.contains(val)); } } else if (cmd <= 8) { @@ -128,12 +128,10 @@ static void tst2() { } } else { - VERIFY(h.check_invariant()); + ENSURE(h.check_invariant()); } } - VERIFY(h.check_invariant()); - h.reset(); - VERIFY(h.check_invariant()); + ENSURE(h.check_invariant()); } void tst_heap() { diff --git a/src/util/heap.h b/src/util/heap.h index 3bee2fe9f..c080c6ebd 100644 --- a/src/util/heap.h +++ b/src/util/heap.h @@ -55,19 +55,6 @@ class heap : private LT { } bool check_invariant_core(int idx) const { - - // Check that m_values starts with a dummy value at index 0. - if (m_values.empty() || m_values[0] != -1) { - return false; - } - - // All indices in m_value2indices that are not used in m_values should be 0 - for (int val = 0; val < static_cast(m_value2indices.size()); ++val) { - if (std::find(m_values.begin(), m_values.end(), val) == m_values.end() && m_value2indices[val] != 0) { - return false; // Unused indices should have a 0 value - } - } - if (idx < static_cast(m_values.size())) { SASSERT(m_value2indices[m_values[idx]] == idx); SASSERT(parent(idx) == 0 || !less_than(m_values[idx], m_values[parent(idx)])); From 2013cd13b20ba1f9a36e41872ccd4f696657ec58 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 21 Jul 2024 21:08:53 -0700 Subject: [PATCH 022/187] Update coverage.yml run code coverage on pull requests --- .github/workflows/coverage.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 679eeee3a..b371a03b5 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -3,6 +3,8 @@ name: Code Coverage on: push: branches: [ master ] + pull_request: + branches: [ master ] schedule: - cron: "0 11 * * *" From b535509cca09f6c5593d5755c251d74daba4de50 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 22 Jul 2024 08:43:22 -0700 Subject: [PATCH 023/187] remove crashing test Signed-off-by: Nikolaj Bjorner --- src/test/dlist.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp index 200a0a329..1bf3f17ef 100644 --- a/src/test/dlist.cpp +++ b/src/test/dlist.cpp @@ -177,10 +177,12 @@ void tst_dlist() { test_pop(); test_insert_after(); test_insert_before(); +#if 0 test_remove_from(); test_push_to_front(); test_detach(); test_invariant(); test_contains(); +#endif std::cout << "All tests passed." << std::endl; } From 1e6b13741c6368a1bc66c06c1497891da1c95b7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:42:40 -0700 Subject: [PATCH 024/187] Bump docker/build-push-action from 6.4.0 to 6.5.0 (#7304) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.4.0 to 6.5.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.4.0...v6.5.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 3c02e2c2b..931ed071e 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -41,7 +41,7 @@ jobs: type=edge type=sha,prefix=ubuntu-20.04-bare-z3-sha- - 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: context: . push: true From 5f6bb3db3e3fd054f42ee1382bab1152f4b86a5c Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 27 Jul 2024 08:26:42 +0200 Subject: [PATCH 025/187] fix #7311 Signed-off-by: Nikolaj Bjorner --- src/nlsat/nlsat_simplify.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/nlsat/nlsat_simplify.cpp b/src/nlsat/nlsat_simplify.cpp index 8148d721f..2901d22c2 100644 --- a/src/nlsat/nlsat_simplify.cpp +++ b/src/nlsat/nlsat_simplify.cpp @@ -141,6 +141,8 @@ namespace nlsat { auto& a = *to_ineq_atom(a1); if (a.size() != 2) continue; + if (a.is_root_atom()) + continue; auto* p = a.p(0); auto* q = a.p(1); @@ -229,6 +231,10 @@ namespace nlsat { } break; } + default: + SASSERT(a.is_root_atom()); + UNREACHABLE(); + break; } IF_VERBOSE(3, s.display(verbose_stream(), c) << " ->\n"; From f94500c3cad3e8a1ac855bcf205a6bc38e84bc69 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 28 Jul 2024 13:18:08 +0200 Subject: [PATCH 026/187] fix #7309 --- src/ast/datatype_decl_plugin.cpp | 103 +++++++++++++++++-------------- src/ast/datatype_decl_plugin.h | 41 +++++++----- 2 files changed, 79 insertions(+), 65 deletions(-) diff --git a/src/ast/datatype_decl_plugin.cpp b/src/ast/datatype_decl_plugin.cpp index a4ddbdaed..c39b09d5e 100644 --- a/src/ast/datatype_decl_plugin.cpp +++ b/src/ast/datatype_decl_plugin.cpp @@ -231,6 +231,24 @@ namespace datatype { } m_defs.reset(); m_util = nullptr; // force deletion + dealloc(m_asts); + std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc >()); + } + + 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 >()); + m_vectors.reset(); + dealloc(m_asts); + m_asts = nullptr; + ++m_start; } util & plugin::u() const { @@ -578,6 +596,7 @@ namespace datatype { if (m_defs.find(s, d)) dealloc(d); m_defs.remove(s); + reset(); } bool plugin::is_value_visit(bool unique, expr * arg, ptr_buffer & todo) const { @@ -799,7 +818,7 @@ namespace datatype { for (unsigned i = 0; i < n; ++i) { sort* ps = get_datatype_parameter_sort(s, i); sz = get_sort_size(params, ps); - m_refs.push_back(sz); + plugin().m_refs.push_back(sz); S.insert(d.params().get(i), sz); } auto ss = d.sort_size(); @@ -896,7 +915,7 @@ namespace datatype { } TRACE("datatype", tout << "set sort size " << s << "\n";); d.set_sort_size(param_size::size::mk_plus(s_add)); - m_refs.reset(); + plugin().m_refs.reset(); } } @@ -1008,9 +1027,7 @@ namespace datatype { util::util(ast_manager & m): m(m), m_family_id(null_family_id), - m_plugin(nullptr), - m_asts(m), - m_start(0) { + m_plugin(nullptr) { } @@ -1027,24 +1044,24 @@ namespace datatype { util::~util() { - std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc >()); + } ptr_vector const * util::get_datatype_constructors(sort * ty) { SASSERT(is_datatype(ty)); ptr_vector * r = nullptr; - if (m_datatype2constructors.find(ty, r)) + if (plugin().m_datatype2constructors.find(ty, r)) return r; r = alloc(ptr_vector); - m_asts.push_back(ty); - m_vectors.push_back(r); - m_datatype2constructors.insert(ty, r); + plugin().add_ast(ty); + plugin().m_vectors.push_back(r); + plugin().m_datatype2constructors.insert(ty, r); if (!is_declared(ty)) m.raise_exception("datatype constructors have not been created"); def const& d = get_def(ty); for (constructor const* c : d) { func_decl_ref f = c->instantiate(ty); - m_asts.push_back(f); + plugin().add_ast(f); r->push_back(f); } return r; @@ -1053,13 +1070,13 @@ namespace datatype { ptr_vector const * util::get_constructor_accessors(func_decl * con) { SASSERT(is_constructor(con)); ptr_vector * res = nullptr; - if (m_constructor2accessors.find(con, res)) { + if (plugin().m_constructor2accessors.find(con, res)) { return res; } res = alloc(ptr_vector); - m_asts.push_back(con); - m_vectors.push_back(res); - m_constructor2accessors.insert(con, res); + plugin().add_ast(con); + plugin().m_vectors.push_back(res); + plugin().m_constructor2accessors.insert(con, res); sort * datatype = con->get_range(); def const& d = get_def(datatype); for (constructor const* c : d) { @@ -1067,7 +1084,7 @@ namespace datatype { for (accessor const* a : *c) { func_decl_ref fn = a->instantiate(datatype); res->push_back(fn); - m_asts.push_back(fn); + plugin().add_ast(fn); } break; } @@ -1086,7 +1103,7 @@ namespace datatype { func_decl * util::get_constructor_recognizer(func_decl * con) { SASSERT(is_constructor(con)); func_decl * d = nullptr; - if (m_constructor2recognizer.find(con, d)) + if (plugin().m_constructor2recognizer.find(con, d)) return d; sort * datatype = con->get_range(); def const& dd = get_def(datatype); @@ -1097,9 +1114,9 @@ namespace datatype { parameter ps[2] = { parameter(con), parameter(r) }; d = m.mk_func_decl(fid(), OP_DT_RECOGNISER, 2, ps, 1, &datatype); SASSERT(d); - m_asts.push_back(con); - m_asts.push_back(d); - m_constructor2recognizer.insert(con, d); + plugin().add_ast(con); + plugin().add_ast(d); + plugin().m_constructor2recognizer.insert(con, d); return d; } @@ -1120,10 +1137,10 @@ namespace datatype { bool util::is_recursive(sort * ty) { SASSERT(is_datatype(ty)); bool r = false; - if (!m_is_recursive.find(ty, r)) { + if (!plugin().m_is_recursive.find(ty, r)) { r = is_recursive_core(ty); - m_is_recursive.insert(ty, r); - m_asts.push_back(ty); + plugin().m_is_recursive.insert(ty, r); + plugin().add_ast(ty); } return r; } @@ -1147,21 +1164,21 @@ namespace datatype { if (!is_datatype(s)) return false; bool r = false; - if (m_is_enum.find(s, r)) + if (plugin().m_is_enum.find(s, r)) return r; ptr_vector const& cnstrs = *get_datatype_constructors(s); r = true; for (unsigned i = 0; r && i < cnstrs.size(); ++i) r = cnstrs[i]->get_arity() == 0; - m_is_enum.insert(s, r); - m_asts.push_back(s); + plugin().m_is_enum.insert(s, r); + plugin().add_ast(s); return r; } func_decl * util::get_accessor_constructor(func_decl * accessor) { SASSERT(is_accessor(accessor)); func_decl * r = nullptr; - if (m_accessor2constructor.find(accessor, r)) + if (plugin().m_accessor2constructor.find(accessor, r)) return r; sort * datatype = accessor->get_domain(0); symbol c_id = accessor->get_parameter(1).get_symbol(); @@ -1174,26 +1191,15 @@ namespace datatype { } } r = fn; - m_accessor2constructor.insert(accessor, r); - m_asts.push_back(accessor); - m_asts.push_back(r); + plugin().m_accessor2constructor.insert(accessor, r); + plugin().add_ast(accessor); + plugin().add_ast(r); return r; } void util::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 >()); - m_vectors.reset(); - m_asts.reset(); - ++m_start; + plugin().reset(); } @@ -1205,7 +1211,7 @@ namespace datatype { func_decl * util::get_non_rec_constructor(sort * ty) { SASSERT(is_datatype(ty)); cnstr_depth cd; - if (m_datatype2nonrec_constructor.find(ty, cd)) + if (plugin().m_datatype2nonrec_constructor.find(ty, cd)) return cd.first; ptr_vector forbidden_set; forbidden_set.push_back(ty); @@ -1222,7 +1228,7 @@ namespace datatype { 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 }) */ - util::cnstr_depth util::get_non_rec_constructor_core(sort * ty, ptr_vector & forbidden_set) { + cnstr_depth util::get_non_rec_constructor_core(sort * ty, ptr_vector & forbidden_set) { // We must select a constructor c(T_1, ..., T_n):T such that // 1) T_i's are not recursive // If there is no such constructor, then we select one that @@ -1231,7 +1237,7 @@ namespace datatype { ptr_vector const& constructors = *get_datatype_constructors(ty); array_util autil(m); cnstr_depth result(nullptr, 0); - if (m_datatype2nonrec_constructor.find(ty, result)) + if (plugin().m_datatype2nonrec_constructor.find(ty, result)) return result; TRACE("util_bug", tout << "get-non-rec constructor: " << sort_ref(ty, m) << "\n"; tout << "forbidden: "; @@ -1273,9 +1279,9 @@ namespace datatype { } } if (result.first) { - m_asts.push_back(result.first); - m_asts.push_back(ty); - m_datatype2nonrec_constructor.insert(ty, result); + plugin().add_ast(result.first); + plugin().add_ast(ty); + plugin().m_datatype2nonrec_constructor.insert(ty, result); } return result; } @@ -1291,6 +1297,7 @@ namespace datatype { IF_VERBOSE(0, verbose_stream() << f->get_name() << "\n"); for (constructor* c : d) IF_VERBOSE(0, verbose_stream() << "!= " << c->name() << "\n"); + return UINT_MAX; SASSERT(false); UNREACHABLE(); return 0; diff --git a/src/ast/datatype_decl_plugin.h b/src/ast/datatype_decl_plugin.h index 341f3669b..f68dcfbdd 100644 --- a/src/ast/datatype_decl_plugin.h +++ b/src/ast/datatype_decl_plugin.h @@ -198,6 +198,8 @@ namespace datatype { def* translate(ast_translation& tr, util& u); }; + typedef std::pair cnstr_depth; + namespace decl { class plugin : public decl_plugin { @@ -213,6 +215,24 @@ namespace datatype { void log_axiom_definitions(symbol const& s, sort * new_sort); + + friend class util; + obj_map*> m_datatype2constructors; + obj_map m_datatype2nonrec_constructor; + obj_map*> m_constructor2accessors; + obj_map m_constructor2recognizer; + obj_map m_recognizer2constructor; + obj_map m_accessor2constructor; + obj_map m_is_recursive; + obj_map m_is_enum; + mutable obj_map m_is_fully_interp; + mutable ast_ref_vector * m_asts = nullptr; + sref_vector m_refs; + ptr_vector > m_vectors; + unsigned m_start = 0; + mutable ptr_vector 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); } + public: plugin(): m_id_counter(0), m_class_id(0), m_has_nested_rec(false) {} ~plugin() override; @@ -259,6 +279,8 @@ namespace datatype { bool has_nested_rec() const { return m_has_nested_rec; } + void reset(); + private: bool is_value_visit(bool unique, expr * arg, ptr_buffer & todo) const; bool is_value_aux(bool unique, app * arg) const; @@ -295,25 +317,10 @@ namespace datatype { ast_manager & m; mutable family_id m_family_id; mutable decl::plugin* m_plugin; - typedef std::pair cnstr_depth; + family_id fid() const; - - obj_map *> m_datatype2constructors; - obj_map m_datatype2nonrec_constructor; - obj_map *> m_constructor2accessors; - obj_map m_constructor2recognizer; - obj_map m_recognizer2constructor; - obj_map m_accessor2constructor; - obj_map m_is_recursive; - obj_map m_is_enum; - mutable obj_map m_is_fully_interp; - mutable ast_ref_vector m_asts; - sref_vector m_refs; - ptr_vector > m_vectors; - unsigned m_start; - mutable ptr_vector m_fully_interp_trail; - + cnstr_depth get_non_rec_constructor_core(sort * ty, ptr_vector & forbidden_set); friend class decl::plugin; From ac7014a68b26363676a09badc1249bf9637316fd Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 29 Jul 2024 03:18:20 +0200 Subject: [PATCH 027/187] expose public Signed-off-by: Nikolaj Bjorner --- src/ast/datatype_decl_plugin.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/ast/datatype_decl_plugin.h b/src/ast/datatype_decl_plugin.h index f68dcfbdd..ca33b48c1 100644 --- a/src/ast/datatype_decl_plugin.h +++ b/src/ast/datatype_decl_plugin.h @@ -216,23 +216,6 @@ namespace datatype { void log_axiom_definitions(symbol const& s, sort * new_sort); - friend class util; - obj_map*> m_datatype2constructors; - obj_map m_datatype2nonrec_constructor; - obj_map*> m_constructor2accessors; - obj_map m_constructor2recognizer; - obj_map m_recognizer2constructor; - obj_map m_accessor2constructor; - obj_map m_is_recursive; - obj_map m_is_enum; - mutable obj_map m_is_fully_interp; - mutable ast_ref_vector * m_asts = nullptr; - sref_vector m_refs; - ptr_vector > m_vectors; - unsigned m_start = 0; - mutable ptr_vector 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); } - public: plugin(): m_id_counter(0), m_class_id(0), m_has_nested_rec(false) {} ~plugin() override; @@ -281,6 +264,23 @@ namespace datatype { void reset(); + + obj_map*> m_datatype2constructors; + obj_map m_datatype2nonrec_constructor; + obj_map*> m_constructor2accessors; + obj_map m_constructor2recognizer; + obj_map m_recognizer2constructor; + obj_map m_accessor2constructor; + obj_map m_is_recursive; + obj_map m_is_enum; + mutable obj_map m_is_fully_interp; + mutable ast_ref_vector* m_asts = nullptr; + sref_vector m_refs; + ptr_vector > m_vectors; + unsigned m_start = 0; + mutable ptr_vector 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: bool is_value_visit(bool unique, expr * arg, ptr_buffer & todo) const; bool is_value_aux(bool unique, app * arg) const; From 25e683e4e195609c8f6e728305aa9517f7d5fe61 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 28 Jul 2024 19:10:30 -0700 Subject: [PATCH 028/187] fix finalize method Signed-off-by: Nikolaj Bjorner --- src/ast/datatype_decl_plugin.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ast/datatype_decl_plugin.cpp b/src/ast/datatype_decl_plugin.cpp index c39b09d5e..cc5c6eb75 100644 --- a/src/ast/datatype_decl_plugin.cpp +++ b/src/ast/datatype_decl_plugin.cpp @@ -220,19 +220,17 @@ namespace datatype { } namespace decl { - + plugin::~plugin() { finalize(); } void plugin::finalize() { - for (auto& kv : m_defs) { - dealloc(kv.m_value); - } + for (auto& kv : m_defs) + dealloc(kv.m_value); m_defs.reset(); m_util = nullptr; // force deletion - dealloc(m_asts); - std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc >()); + reset(); } void plugin::reset() { From 2ce89e5f491fa817d02d8fdce8c62798beab258b Mon Sep 17 00:00:00 2001 From: David Seifert <16636962+SoapGentoo@users.noreply.github.com> Date: Mon, 29 Jul 2024 20:07:10 +0200 Subject: [PATCH 029/187] Gcc 15 two phase (#7313) * Fix `-Wclass-memaccess` * Fix for GCC 15 two-phase lookup * GCC 15 is more aggressive about checking dependent names: https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=r15-2117-g313afcfdabeab3 Bug: https://bugs.gentoo.org/936634 --- src/math/lp/lp_settings.h | 69 ++++++++++++++++----------------- src/math/lp/static_matrix.h | 2 +- src/math/lp/static_matrix_def.h | 2 +- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/math/lp/lp_settings.h b/src/math/lp/lp_settings.h index d1a4be21c..0d47877c7 100644 --- a/src/math/lp/lp_settings.h +++ b/src/math/lp/lp_settings.h @@ -97,42 +97,41 @@ public: }; struct statistics { - unsigned m_make_feasible; - unsigned m_total_iterations; - unsigned m_iters_with_no_cost_growing; - unsigned m_num_factorizations; - unsigned m_num_of_implied_bounds; - unsigned m_need_to_solve_inf; - unsigned m_max_cols; - unsigned m_max_rows; - unsigned m_gcd_calls; - unsigned m_gcd_conflicts; - unsigned m_cube_calls; - unsigned m_cube_success; - unsigned m_patches; - unsigned m_patches_success; - unsigned m_hnf_cutter_calls; - unsigned m_hnf_cuts; - unsigned m_nla_calls; - unsigned m_gomory_cuts; - unsigned m_nla_add_bounds; - unsigned m_nla_propagate_bounds; - unsigned m_nla_propagate_eq; - unsigned m_nla_lemmas; - unsigned m_nra_calls; - unsigned m_nla_bounds_improvements; - unsigned m_horner_calls; - unsigned m_horner_conflicts; - unsigned m_cross_nested_forms; - unsigned m_grobner_calls; - unsigned m_grobner_conflicts; - unsigned m_offset_eqs; - unsigned m_fixed_eqs; - ::statistics m_st; - statistics() { reset(); } + unsigned m_make_feasible = 0; + unsigned m_total_iterations = 0; + unsigned m_iters_with_no_cost_growing = 0; + unsigned m_num_factorizations = 0; + unsigned m_num_of_implied_bounds = 0; + unsigned m_need_to_solve_inf = 0; + unsigned m_max_cols = 0; + unsigned m_max_rows = 0; + unsigned m_gcd_calls = 0; + unsigned m_gcd_conflicts = 0; + unsigned m_cube_calls = 0; + unsigned m_cube_success = 0; + unsigned m_patches = 0; + unsigned m_patches_success = 0; + unsigned m_hnf_cutter_calls = 0; + unsigned m_hnf_cuts = 0; + unsigned m_nla_calls = 0; + unsigned m_gomory_cuts = 0; + unsigned m_nla_add_bounds = 0; + unsigned m_nla_propagate_bounds = 0; + unsigned m_nla_propagate_eq = 0; + unsigned m_nla_lemmas = 0; + unsigned m_nra_calls = 0; + unsigned m_nla_bounds_improvements = 0; + unsigned m_horner_calls = 0; + unsigned m_horner_conflicts = 0; + unsigned m_cross_nested_forms = 0; + unsigned m_grobner_calls = 0; + unsigned m_grobner_conflicts = 0; + unsigned m_offset_eqs = 0; + unsigned m_fixed_eqs = 0; + ::statistics m_st = {}; + void reset() { - memset(this, 0, sizeof(*this)); - m_st.reset(); + *this = statistics{}; } void collect_statistics(::statistics& st) const { st.update("arith-factorizations", m_num_factorizations); diff --git a/src/math/lp/static_matrix.h b/src/math/lp/static_matrix.h index 9d6bb8599..42dd476b5 100644 --- a/src/math/lp/static_matrix.h +++ b/src/math/lp/static_matrix.h @@ -79,7 +79,7 @@ public: 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=(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); } }; diff --git a/src/math/lp/static_matrix_def.h b/src/math/lp/static_matrix_def.h index 0370ee899..c3b2fc168 100644 --- a/src/math/lp/static_matrix_def.h +++ b/src/math/lp/static_matrix_def.h @@ -92,7 +92,7 @@ static_matrix::static_matrix(static_matrix const &A, unsigned * /* basis * init_row_columns(m, m); for (; m-- > 0; ) 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 void static_matrix::clear() { From 2ae3d87b21c99184951f7ec0380675a5e00ba778 Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:08:54 -0700 Subject: [PATCH 030/187] add scoped vector unit test (#7307) * add scoped vector unit test * fix dlist tests * add new scoped vector invariants --- src/test/CMakeLists.txt | 1 + src/test/dlist.cpp | 79 +++++++++++++++--------------- src/test/main.cpp | 1 + src/test/scoped_vector.cpp | 99 ++++++++++++++++++++++++++++++++++++++ src/util/scoped_vector.h | 44 +++++++++++++++-- 5 files changed, 180 insertions(+), 44 deletions(-) create mode 100644 src/test/scoped_vector.cpp diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 8464cedf9..658647ea6 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -106,6 +106,7 @@ add_executable(test-z3 sat_lookahead.cpp sat_user_scope.cpp scoped_timer.cpp + scoped_vector.cpp simple_parser.cpp simplex.cpp simplifier.cpp diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp index 1bf3f17ef..14991c9ac 100644 --- a/src/test/dlist.cpp +++ b/src/test/dlist.cpp @@ -15,7 +15,6 @@ Author: --*/ -#include #include #include "util/dlist.h" @@ -30,28 +29,28 @@ public: // Test the prev() method void test_prev() { TestNode node(1); - assert(node.prev() == &node); + SASSERT(node.prev() == &node); std::cout << "test_prev passed." << std::endl; } // Test the next() method void test_next() { TestNode node(1); - assert(node.next() == &node); + SASSERT(node.next() == &node); std::cout << "test_next passed." << std::endl; } // Test the const prev() method void test_const_prev() { const TestNode node(1); - assert(node.prev() == &node); + SASSERT(node.prev() == &node); std::cout << "test_const_prev passed." << std::endl; } // Test the const next() method void test_const_next() { const TestNode node(1); - assert(node.next() == &node); + SASSERT(node.next() == &node); std::cout << "test_const_next passed." << std::endl; } @@ -59,9 +58,9 @@ void test_const_next() { void test_init() { TestNode node(1); node.init(&node); - assert(node.next() == &node); - assert(node.prev() == &node); - assert(node.invariant()); + SASSERT(node.next() == &node); + SASSERT(node.prev() == &node); + SASSERT(node.invariant()); std::cout << "test_init passed." << std::endl; } @@ -71,10 +70,10 @@ void test_pop() { TestNode node1(1); TestNode::push_to_front(list, &node1); TestNode* popped = TestNode::pop(list); - assert(popped == &node1); - assert(list == nullptr); - assert(popped->next() == popped); - assert(popped->prev() == popped); + SASSERT(popped == &node1); + SASSERT(list == nullptr); + SASSERT(popped->next() == popped); + SASSERT(popped->prev() == popped); std::cout << "test_pop passed." << std::endl; } @@ -83,12 +82,12 @@ void test_insert_after() { TestNode node1(1); TestNode node2(2); node1.insert_after(&node2); - assert(node1.next() == &node2); - assert(node2.prev() == &node1); - assert(node1.prev() == &node2); - assert(node2.next() == &node1); - assert(node1.invariant()); - assert(node2.invariant()); + SASSERT(node1.next() == &node2); + SASSERT(node2.prev() == &node1); + SASSERT(node1.prev() == &node2); + SASSERT(node2.next() == &node1); + SASSERT(node1.invariant()); + SASSERT(node2.invariant()); std::cout << "test_insert_after passed." << std::endl; } @@ -97,12 +96,12 @@ void test_insert_before() { TestNode node1(1); TestNode node2(2); node1.insert_before(&node2); - assert(node1.prev() == &node2); - assert(node2.next() == &node1); - assert(node1.next() == &node2); - assert(node2.prev() == &node1); - assert(node1.invariant()); - assert(node2.invariant()); + SASSERT(node1.prev() == &node2); + SASSERT(node2.next() == &node1); + SASSERT(node1.next() == &node2); + SASSERT(node2.prev() == &node1); + SASSERT(node1.invariant()); + SASSERT(node2.invariant()); std::cout << "test_insert_before passed." << std::endl; } @@ -114,11 +113,9 @@ void test_remove_from() { TestNode::push_to_front(list, &node1); TestNode::push_to_front(list, &node2); TestNode::remove_from(list, &node1); - assert(list == &node2); - assert(node2.next() == &node2); - assert(node2.prev() == &node2); - assert(node1.next() == &node1); - assert(node1.prev() == &node1); + SASSERT(list == &node2); + SASSERT(node2.next() == &node2); + SASSERT(node2.prev() == &node2); std::cout << "test_remove_from passed." << std::endl; } @@ -127,9 +124,9 @@ void test_push_to_front() { TestNode* list = nullptr; TestNode node1(1); TestNode::push_to_front(list, &node1); - assert(list == &node1); - assert(node1.next() == &node1); - assert(node1.prev() == &node1); + SASSERT(list == &node1); + SASSERT(node1.next() == &node1); + SASSERT(node1.prev() == &node1); std::cout << "test_push_to_front passed." << std::endl; } @@ -137,20 +134,20 @@ void test_push_to_front() { void test_detach() { TestNode node(1); TestNode::detach(&node); - assert(node.next() == &node); - assert(node.prev() == &node); - assert(node.invariant()); + SASSERT(node.next() == &node); + SASSERT(node.prev() == &node); + SASSERT(node.invariant()); std::cout << "test_detach passed." << std::endl; } // Test the invariant() method void test_invariant() { TestNode node1(1); - assert(node1.invariant()); + SASSERT(node1.invariant()); TestNode node2(2); node1.insert_after(&node2); - assert(node1.invariant()); - assert(node2.invariant()); + SASSERT(node1.invariant()); + SASSERT(node2.invariant()); std::cout << "test_invariant passed." << std::endl; } @@ -161,10 +158,10 @@ void test_contains() { TestNode node2(2); TestNode::push_to_front(list, &node1); TestNode::push_to_front(list, &node2); - assert(TestNode::contains(list, &node1)); - assert(TestNode::contains(list, &node2)); + SASSERT(TestNode::contains(list, &node1)); + SASSERT(TestNode::contains(list, &node2)); TestNode node3(3); - assert(!TestNode::contains(list, &node3)); + SASSERT(!TestNode::contains(list, &node3)); std::cout << "test_contains passed." << std::endl; } diff --git a/src/test/main.cpp b/src/test/main.cpp index 0d3679529..f028d6ceb 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -269,4 +269,5 @@ int main(int argc, char ** argv) { TST(euf_bv_plugin); TST(euf_arith_plugin); TST(sls_test); + TST(scoped_vector); } diff --git a/src/test/scoped_vector.cpp b/src/test/scoped_vector.cpp new file mode 100644 index 000000000..05d98fcf1 --- /dev/null +++ b/src/test/scoped_vector.cpp @@ -0,0 +1,99 @@ +#include +#include "util/scoped_vector.h" + +void test_push_back_and_access() { + scoped_vector sv; + sv.push_back(10); + + sv.push_back(20); + + SASSERT(sv.size() == 2); + SASSERT(sv[0] == 10); + SASSERT(sv[1] == 20); + + std::cout << "test_push_back_and_access passed." << std::endl; +} + +void test_scopes() { + scoped_vector sv; + sv.push_back(10); + sv.push_back(20); + + sv.push_scope(); + sv.push_back(30); + sv.push_back(40); + + SASSERT(sv.size() == 4); + SASSERT(sv[2] == 30); + SASSERT(sv[3] == 40); + + sv.pop_scope(1); + + std::cout << "test_scopes passed." << std::endl; + SASSERT(sv.size() == 2); + SASSERT(sv[0] == 10); + SASSERT(sv[1] == 20); + + std::cout << "test_scopes passed." << std::endl; +} + +void test_set() { + scoped_vector sv; + sv.push_back(10); + sv.push_back(20); + + sv.set(0, 30); + sv.set(1, 40); + + SASSERT(sv.size() == 2); + SASSERT(sv[0] == 30); + SASSERT(sv[1] == 40); + + sv.push_scope(); + sv.set(0, 50); + SASSERT(sv[0] == 50); + sv.pop_scope(1); + SASSERT(sv[0] == 30); + + std::cout << "test_set passed." << std::endl; +} + +void test_pop_back() { + scoped_vector sv; + sv.push_back(10); + sv.push_back(20); + + SASSERT(sv.size() == 2); + sv.pop_back(); + SASSERT(sv.size() == 1); + SASSERT(sv[0] == 10); + sv.pop_back(); + SASSERT(sv.size() == 0); + + std::cout << "test_pop_back passed." << std::endl; +} + +void test_erase_and_swap() { + scoped_vector sv; + sv.push_back(10); + sv.push_back(20); + sv.push_back(30); + + sv.erase_and_swap(1); + + SASSERT(sv.size() == 2); + SASSERT(sv[0] == 10); + SASSERT(sv[1] == 30); + + std::cout << "test_erase_and_swap passed." << std::endl; +} + +void tst_scoped_vector() { + test_push_back_and_access(); + test_scopes(); + test_set(); + test_pop_back(); + test_erase_and_swap(); + + std::cout << "All tests passed." << std::endl; +} diff --git a/src/util/scoped_vector.h b/src/util/scoped_vector.h index 2c6cfaa21..b5945fb44 100644 --- a/src/util/scoped_vector.h +++ b/src/util/scoped_vector.h @@ -176,8 +176,46 @@ private: } bool invariant() const { - return - m_size <= m_elems.size() && - m_elems_start <= m_elems.size(); + + + if (!(m_size <= m_elems.size() && m_elems_start <= m_elems.size())) + return false; + + // Check that source and destination trails have the same length. + if (m_src.size() != m_dst.size()) + return false; + // The size of m_src, m_dst, and m_src_lim should be consistent with the scope stack. + if (m_src_lim.size() != m_sizes.size() || m_src.size() != m_dst.size()) + return false; + + // m_elems_lim stores the past sizes of m_elems for each scope. Each element in m_elems_lim should be + // within bounds and in non-decreasing order. + for (unsigned i = 1; i < m_elems_lim.size(); ++i) { + if (m_elems_lim[i - 1] > m_elems_lim[i]) return false; + } + + + // m_sizes tracks the size of the vector at each scope level. + // Each element in m_sizes should be non-decreasing and within the size of m_elems. + for (unsigned i = 1; i < m_sizes.size(); ++i) { + if (m_sizes[i - 1] > m_sizes[i]) + return false; + } + + // The m_src and m_dst vectors should have the same size and should contain valid indices. + if (m_src.size() != m_dst.size()) return false; + for (unsigned i = 0; i < m_src.size(); ++i) { + if (m_src[i] >= m_index.size() || m_dst[i] >= m_elems.size()) return false; + } + + + // The size of m_src_lim should be less than or equal to the size of m_sizes and store valid indices. + if (m_src_lim.size() > m_sizes.size()) return false; + for (unsigned elem : m_src_lim) { + if (elem > m_src.size()) return false; + } + + return true; + } }; From 5fcc50f60635fd2a0a77e3c5dfc2c6234cb8a81a Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 30 Jul 2024 11:34:02 -0700 Subject: [PATCH 031/187] Revert "add scoped vector unit test (#7307)" (#7317) This reverts commit 2ae3d87b21c99184951f7ec0380675a5e00ba778. --- src/test/CMakeLists.txt | 1 - src/test/dlist.cpp | 79 +++++++++++++++--------------- src/test/main.cpp | 1 - src/test/scoped_vector.cpp | 99 -------------------------------------- src/util/scoped_vector.h | 44 ++--------------- 5 files changed, 44 insertions(+), 180 deletions(-) delete mode 100644 src/test/scoped_vector.cpp diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 658647ea6..8464cedf9 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -106,7 +106,6 @@ add_executable(test-z3 sat_lookahead.cpp sat_user_scope.cpp scoped_timer.cpp - scoped_vector.cpp simple_parser.cpp simplex.cpp simplifier.cpp diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp index 14991c9ac..1bf3f17ef 100644 --- a/src/test/dlist.cpp +++ b/src/test/dlist.cpp @@ -15,6 +15,7 @@ Author: --*/ +#include #include #include "util/dlist.h" @@ -29,28 +30,28 @@ public: // Test the prev() method void test_prev() { TestNode node(1); - SASSERT(node.prev() == &node); + assert(node.prev() == &node); std::cout << "test_prev passed." << std::endl; } // Test the next() method void test_next() { TestNode node(1); - SASSERT(node.next() == &node); + assert(node.next() == &node); std::cout << "test_next passed." << std::endl; } // Test the const prev() method void test_const_prev() { const TestNode node(1); - SASSERT(node.prev() == &node); + assert(node.prev() == &node); std::cout << "test_const_prev passed." << std::endl; } // Test the const next() method void test_const_next() { const TestNode node(1); - SASSERT(node.next() == &node); + assert(node.next() == &node); std::cout << "test_const_next passed." << std::endl; } @@ -58,9 +59,9 @@ void test_const_next() { void test_init() { TestNode node(1); node.init(&node); - SASSERT(node.next() == &node); - SASSERT(node.prev() == &node); - SASSERT(node.invariant()); + assert(node.next() == &node); + assert(node.prev() == &node); + assert(node.invariant()); std::cout << "test_init passed." << std::endl; } @@ -70,10 +71,10 @@ void test_pop() { TestNode node1(1); TestNode::push_to_front(list, &node1); TestNode* popped = TestNode::pop(list); - SASSERT(popped == &node1); - SASSERT(list == nullptr); - SASSERT(popped->next() == popped); - SASSERT(popped->prev() == popped); + assert(popped == &node1); + assert(list == nullptr); + assert(popped->next() == popped); + assert(popped->prev() == popped); std::cout << "test_pop passed." << std::endl; } @@ -82,12 +83,12 @@ void test_insert_after() { TestNode node1(1); TestNode node2(2); node1.insert_after(&node2); - SASSERT(node1.next() == &node2); - SASSERT(node2.prev() == &node1); - SASSERT(node1.prev() == &node2); - SASSERT(node2.next() == &node1); - SASSERT(node1.invariant()); - SASSERT(node2.invariant()); + assert(node1.next() == &node2); + assert(node2.prev() == &node1); + assert(node1.prev() == &node2); + assert(node2.next() == &node1); + assert(node1.invariant()); + assert(node2.invariant()); std::cout << "test_insert_after passed." << std::endl; } @@ -96,12 +97,12 @@ void test_insert_before() { TestNode node1(1); TestNode node2(2); node1.insert_before(&node2); - SASSERT(node1.prev() == &node2); - SASSERT(node2.next() == &node1); - SASSERT(node1.next() == &node2); - SASSERT(node2.prev() == &node1); - SASSERT(node1.invariant()); - SASSERT(node2.invariant()); + assert(node1.prev() == &node2); + assert(node2.next() == &node1); + assert(node1.next() == &node2); + assert(node2.prev() == &node1); + assert(node1.invariant()); + assert(node2.invariant()); std::cout << "test_insert_before passed." << std::endl; } @@ -113,9 +114,11 @@ void test_remove_from() { TestNode::push_to_front(list, &node1); TestNode::push_to_front(list, &node2); TestNode::remove_from(list, &node1); - SASSERT(list == &node2); - SASSERT(node2.next() == &node2); - SASSERT(node2.prev() == &node2); + assert(list == &node2); + assert(node2.next() == &node2); + assert(node2.prev() == &node2); + assert(node1.next() == &node1); + assert(node1.prev() == &node1); std::cout << "test_remove_from passed." << std::endl; } @@ -124,9 +127,9 @@ void test_push_to_front() { TestNode* list = nullptr; TestNode node1(1); TestNode::push_to_front(list, &node1); - SASSERT(list == &node1); - SASSERT(node1.next() == &node1); - SASSERT(node1.prev() == &node1); + assert(list == &node1); + assert(node1.next() == &node1); + assert(node1.prev() == &node1); std::cout << "test_push_to_front passed." << std::endl; } @@ -134,20 +137,20 @@ void test_push_to_front() { void test_detach() { TestNode node(1); TestNode::detach(&node); - SASSERT(node.next() == &node); - SASSERT(node.prev() == &node); - SASSERT(node.invariant()); + assert(node.next() == &node); + assert(node.prev() == &node); + assert(node.invariant()); std::cout << "test_detach passed." << std::endl; } // Test the invariant() method void test_invariant() { TestNode node1(1); - SASSERT(node1.invariant()); + assert(node1.invariant()); TestNode node2(2); node1.insert_after(&node2); - SASSERT(node1.invariant()); - SASSERT(node2.invariant()); + assert(node1.invariant()); + assert(node2.invariant()); std::cout << "test_invariant passed." << std::endl; } @@ -158,10 +161,10 @@ void test_contains() { TestNode node2(2); TestNode::push_to_front(list, &node1); TestNode::push_to_front(list, &node2); - SASSERT(TestNode::contains(list, &node1)); - SASSERT(TestNode::contains(list, &node2)); + assert(TestNode::contains(list, &node1)); + assert(TestNode::contains(list, &node2)); TestNode node3(3); - SASSERT(!TestNode::contains(list, &node3)); + assert(!TestNode::contains(list, &node3)); std::cout << "test_contains passed." << std::endl; } diff --git a/src/test/main.cpp b/src/test/main.cpp index f028d6ceb..0d3679529 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -269,5 +269,4 @@ int main(int argc, char ** argv) { TST(euf_bv_plugin); TST(euf_arith_plugin); TST(sls_test); - TST(scoped_vector); } diff --git a/src/test/scoped_vector.cpp b/src/test/scoped_vector.cpp deleted file mode 100644 index 05d98fcf1..000000000 --- a/src/test/scoped_vector.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include "util/scoped_vector.h" - -void test_push_back_and_access() { - scoped_vector sv; - sv.push_back(10); - - sv.push_back(20); - - SASSERT(sv.size() == 2); - SASSERT(sv[0] == 10); - SASSERT(sv[1] == 20); - - std::cout << "test_push_back_and_access passed." << std::endl; -} - -void test_scopes() { - scoped_vector sv; - sv.push_back(10); - sv.push_back(20); - - sv.push_scope(); - sv.push_back(30); - sv.push_back(40); - - SASSERT(sv.size() == 4); - SASSERT(sv[2] == 30); - SASSERT(sv[3] == 40); - - sv.pop_scope(1); - - std::cout << "test_scopes passed." << std::endl; - SASSERT(sv.size() == 2); - SASSERT(sv[0] == 10); - SASSERT(sv[1] == 20); - - std::cout << "test_scopes passed." << std::endl; -} - -void test_set() { - scoped_vector sv; - sv.push_back(10); - sv.push_back(20); - - sv.set(0, 30); - sv.set(1, 40); - - SASSERT(sv.size() == 2); - SASSERT(sv[0] == 30); - SASSERT(sv[1] == 40); - - sv.push_scope(); - sv.set(0, 50); - SASSERT(sv[0] == 50); - sv.pop_scope(1); - SASSERT(sv[0] == 30); - - std::cout << "test_set passed." << std::endl; -} - -void test_pop_back() { - scoped_vector sv; - sv.push_back(10); - sv.push_back(20); - - SASSERT(sv.size() == 2); - sv.pop_back(); - SASSERT(sv.size() == 1); - SASSERT(sv[0] == 10); - sv.pop_back(); - SASSERT(sv.size() == 0); - - std::cout << "test_pop_back passed." << std::endl; -} - -void test_erase_and_swap() { - scoped_vector sv; - sv.push_back(10); - sv.push_back(20); - sv.push_back(30); - - sv.erase_and_swap(1); - - SASSERT(sv.size() == 2); - SASSERT(sv[0] == 10); - SASSERT(sv[1] == 30); - - std::cout << "test_erase_and_swap passed." << std::endl; -} - -void tst_scoped_vector() { - test_push_back_and_access(); - test_scopes(); - test_set(); - test_pop_back(); - test_erase_and_swap(); - - std::cout << "All tests passed." << std::endl; -} diff --git a/src/util/scoped_vector.h b/src/util/scoped_vector.h index b5945fb44..2c6cfaa21 100644 --- a/src/util/scoped_vector.h +++ b/src/util/scoped_vector.h @@ -176,46 +176,8 @@ private: } bool invariant() const { - - - if (!(m_size <= m_elems.size() && m_elems_start <= m_elems.size())) - return false; - - // Check that source and destination trails have the same length. - if (m_src.size() != m_dst.size()) - return false; - // The size of m_src, m_dst, and m_src_lim should be consistent with the scope stack. - if (m_src_lim.size() != m_sizes.size() || m_src.size() != m_dst.size()) - return false; - - // m_elems_lim stores the past sizes of m_elems for each scope. Each element in m_elems_lim should be - // within bounds and in non-decreasing order. - for (unsigned i = 1; i < m_elems_lim.size(); ++i) { - if (m_elems_lim[i - 1] > m_elems_lim[i]) return false; - } - - - // m_sizes tracks the size of the vector at each scope level. - // Each element in m_sizes should be non-decreasing and within the size of m_elems. - for (unsigned i = 1; i < m_sizes.size(); ++i) { - if (m_sizes[i - 1] > m_sizes[i]) - return false; - } - - // The m_src and m_dst vectors should have the same size and should contain valid indices. - if (m_src.size() != m_dst.size()) return false; - for (unsigned i = 0; i < m_src.size(); ++i) { - if (m_src[i] >= m_index.size() || m_dst[i] >= m_elems.size()) return false; - } - - - // The size of m_src_lim should be less than or equal to the size of m_sizes and store valid indices. - if (m_src_lim.size() > m_sizes.size()) return false; - for (unsigned elem : m_src_lim) { - if (elem > m_src.size()) return false; - } - - return true; - + return + m_size <= m_elems.size() && + m_elems_start <= m_elems.size(); } }; From 0c16d34eb0eb9eb2627606431c631d896d547f6f Mon Sep 17 00:00:00 2001 From: Hari Govind V K Date: Tue, 30 Jul 2024 14:35:33 -0400 Subject: [PATCH 032/187] fix #7292 (#7316) --- src/qe/mbp/mbp_basic_tg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qe/mbp/mbp_basic_tg.cpp b/src/qe/mbp/mbp_basic_tg.cpp index ce5e99eb1..693624871 100644 --- a/src/qe/mbp/mbp_basic_tg.cpp +++ b/src/qe/mbp/mbp_basic_tg.cpp @@ -101,7 +101,7 @@ struct mbp_basic_tg::impl { bool is_or = m.is_or(term); app *c = to_app(term); 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) { mark_seen(term); progress = true; From e7382d6ff9322e21aef87118dc6bf448f56d41f2 Mon Sep 17 00:00:00 2001 From: Philip Zucker Date: Wed, 31 Jul 2024 11:14:16 -0400 Subject: [PATCH 033/187] Added "λ" pretty printing to python (#7320) --- src/api/python/z3/z3printer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/api/python/z3/z3printer.py b/src/api/python/z3/z3printer.py index 2da5f89da..d7ee17f4a 100644 --- a/src/api/python/z3/z3printer.py +++ b/src/api/python/z3/z3printer.py @@ -1412,8 +1412,10 @@ class HTMLFormatter(Formatter): ys_pp = group(seq(ys)) if a.is_forall(): header = "∀" - else: + elif a.is_exists(): header = "∃" + else: + header = "λ" return group(compose(to_format(header, 1), indent(1, compose(ys_pp, to_format(" :"), line_break(), body_pp)))) From 6ba25b888bf7da8ee8edd8d294400aadbadf4e64 Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:56:26 -0700 Subject: [PATCH 034/187] add permutation unit tests (#7300) * add permutation unit tests * update test * update * Update permutation.cpp fix macos build --------- Co-authored-by: Nikolaj Bjorner --- src/test/permutation.cpp | 163 +++++++++++++++++++++------------------ src/util/permutation.h | 2 + 2 files changed, 92 insertions(+), 73 deletions(-) diff --git a/src/test/permutation.cpp b/src/test/permutation.cpp index 74b97a365..31b83b9d1 100644 --- a/src/test/permutation.cpp +++ b/src/test/permutation.cpp @@ -1,84 +1,101 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - permutation.cpp - -Abstract: - - Simple abstraction for managing permutations. - -Author: - - Leonardo de Moura (leonardo) 2012-01-04 - -Revision History: - ---*/ +#include +#include #include "util/permutation.h" #include "util/util.h" -#include "util/vector.h" -void apply_permutation_copy(unsigned sz, unsigned const * src, unsigned const * p, unsigned * target) { - for (unsigned i = 0; i < sz; i++) { - target[i] = src[p[i]]; +void swap(unsigned m1, unsigned m2) noexcept { std::swap(m1, m2); } + +void test_constructor() { + permutation p(5); + for (unsigned i = 0; i < 5; ++i) { + SASSERT(p(i) == i); + SASSERT(p.inv(i) == i); } } -static void tst1(unsigned sz, unsigned num_tries, unsigned max = UINT_MAX) { -#if 0 - unsigned_vector data; - unsigned_vector p; - unsigned_vector new_data; - data.resize(sz); - p.resize(sz); - new_data.resize(sz); - random_gen g; - for (unsigned i = 0; i < sz; i++) - p[i] = i; - // fill data with random numbers - for (unsigned i = 0; i < sz; i++) - data[i] = g() % max; - for (unsigned k = 0; k < num_tries; k ++) { - shuffle(p.size(), p.c_ptr(), g); - // std::cout << "p: "; display(std::cout, p.begin(), p.end()); std::cout << "\n"; - // std::cout << "data: "; display(std::cout, data.begin(), data.end()); std::cout << "\n"; - apply_permutation_copy(sz, data.c_ptr(), p.c_ptr(), new_data.c_ptr()); - apply_permutation(sz, data.c_ptr(), p.c_ptr()); - // std::cout << "data: "; display(std::cout, data.begin(), data.end()); std::cout << "\n"; - for (unsigned i = 0; i < 0; i++) - ENSURE(data[i] == new_data[i]); +void test_reset() { + permutation p(3); + p.swap(0, 2); + p.reset(3); + for (unsigned i = 0; i < 3; ++i) { + SASSERT(p(i) == i); + SASSERT(p.inv(i) == i); } -#endif +} + +void test_swap() { + permutation p(4); + p.swap(1, 3); + SASSERT(p(1) == 3); + SASSERT(p(3) == 1); + SASSERT(p.inv(1) == 3); + SASSERT(p.inv(3) == 1); +} + +void test_move_after() { + permutation p(5); + p.move_after(1, 3); + SASSERT(p(0) == 0); + SASSERT(p(1) == 2); + SASSERT(p(2) == 3); + SASSERT(p(3) == 1); + SASSERT(p(4) == 4); +} + +void test_apply_permutation() { + permutation p(4); + int data[] = {10, 20, 30, 40}; + unsigned perm[] = {2, 1, 0, 3}; + apply_permutation(4, data, perm); + std::cout << "000 " << data[0] << std::endl; + std::cout << "222 " << data[2] << std::endl; + + SASSERT(data[0] == 10); + SASSERT(data[1] == 20); + SASSERT(data[2] == 30); + SASSERT(data[3] == 40); +} + +void test_apply_permutation_core() +{ + permutation p(4); + int data[] = {10, 20, 30, 40}; + unsigned perm[] = {2, 1, 0, 3}; + apply_permutation_core(4, data, perm); + std::cout << "000 " << data[0] << std::endl; + std::cout << "222 " << data[2] << std::endl; + + SASSERT(data[0] == 10); + SASSERT(data[1] == 20); + SASSERT(data[2] == 30); + SASSERT(data[3] == 40); +} + +void test_check_invariant() { + permutation p(4); + SASSERT(p.check_invariant()); + p.swap(0, 2); + SASSERT(p.check_invariant()); + p.move_after(1, 3); + SASSERT(p.check_invariant()); +} + +void test_display() { + permutation p(4); + std::ostringstream out; + p.display(out); + SASSERT(out.str() == "0:0 1:1 2:2 3:3"); } void tst_permutation() { - tst1(10, 1000, 5); - tst1(10, 1000, 1000); - tst1(10, 1000, UINT_MAX); - tst1(100, 1000, 33); - tst1(100, 1000, 1000); - tst1(100, 1000, UINT_MAX); - tst1(1000, 1000, 121); - tst1(1000, 1000, 1000); - tst1(1000, 1000, UINT_MAX); - tst1(33, 1000, 121); - tst1(33, 1000, 1000); - tst1(33, 1000, UINT_MAX); - tst1(121, 1000, 121); - tst1(121, 1000, 1000); - tst1(121, 1000, UINT_MAX); - for (unsigned i = 0; i < 1000; i++) { - tst1(1000, 2, 333); - tst1(1000, 2, 10000); - tst1(1000, 2, UINT_MAX); - } - random_gen g; - for (unsigned i = 0; i < 100000; i++) { - unsigned sz = (g() % 131) + 1; - tst1(sz, 1, sz*2); - tst1(sz, 1, UINT_MAX); - tst1(sz, 1, sz/2 + 1); - } + test_constructor(); + test_reset(); + test_swap(); + test_move_after(); + // test_apply_permutation(); + // test_apply_permutation_core(); + test_check_invariant(); + test_display(); + + std::cout << "All tests passed!" << std::endl; } diff --git a/src/util/permutation.h b/src/util/permutation.h index dfc52b370..0d4399f7e 100644 --- a/src/util/permutation.h +++ b/src/util/permutation.h @@ -38,6 +38,8 @@ public: bool check_invariant() const; }; +void swap(unsigned i, unsigned j) noexcept; + inline std::ostream & operator<<(std::ostream & out, permutation const & p) { p.display(out); return out; From fe594618e6c7fddb33d0c2062d667990ba9bba5c Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:56:54 -0700 Subject: [PATCH 035/187] fix dlist tests (#7323) --- src/test/dlist.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp index 1bf3f17ef..fe72c917a 100644 --- a/src/test/dlist.cpp +++ b/src/test/dlist.cpp @@ -106,21 +106,6 @@ void test_insert_before() { std::cout << "test_insert_before passed." << std::endl; } -// Test the remove_from() method -void test_remove_from() { - TestNode* list = nullptr; - TestNode node1(1); - TestNode node2(2); - TestNode::push_to_front(list, &node1); - TestNode::push_to_front(list, &node2); - TestNode::remove_from(list, &node1); - assert(list == &node2); - assert(node2.next() == &node2); - assert(node2.prev() == &node2); - assert(node1.next() == &node1); - assert(node1.prev() == &node1); - std::cout << "test_remove_from passed." << std::endl; -} // Test the push_to_front() method void test_push_to_front() { @@ -177,12 +162,9 @@ void tst_dlist() { test_pop(); test_insert_after(); test_insert_before(); -#if 0 - test_remove_from(); test_push_to_front(); test_detach(); test_invariant(); test_contains(); -#endif std::cout << "All tests passed." << std::endl; } From 23e7dc03563169b62719c3d23bd1de32647b6784 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 2 Aug 2024 11:35:06 -0700 Subject: [PATCH 036/187] assert -> SASSERT Signed-off-by: Nikolaj Bjorner --- src/test/dlist.cpp | 85 +++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp index fe72c917a..dd1b6609d 100644 --- a/src/test/dlist.cpp +++ b/src/test/dlist.cpp @@ -30,28 +30,28 @@ public: // Test the prev() method void test_prev() { TestNode node(1); - assert(node.prev() == &node); + SASSERT(node.prev() == &node); std::cout << "test_prev passed." << std::endl; } // Test the next() method void test_next() { TestNode node(1); - assert(node.next() == &node); + SASSERT(node.next() == &node); std::cout << "test_next passed." << std::endl; } // Test the const prev() method void test_const_prev() { const TestNode node(1); - assert(node.prev() == &node); + SASSERT(node.prev() == &node); std::cout << "test_const_prev passed." << std::endl; } // Test the const next() method void test_const_next() { const TestNode node(1); - assert(node.next() == &node); + SASSERT(node.next() == &node); std::cout << "test_const_next passed." << std::endl; } @@ -59,9 +59,9 @@ void test_const_next() { void test_init() { TestNode node(1); node.init(&node); - assert(node.next() == &node); - assert(node.prev() == &node); - assert(node.invariant()); + SASSERT(node.next() == &node); + SASSERT(node.prev() == &node); + SASSERT(node.invariant()); std::cout << "test_init passed." << std::endl; } @@ -71,10 +71,10 @@ void test_pop() { TestNode node1(1); TestNode::push_to_front(list, &node1); TestNode* popped = TestNode::pop(list); - assert(popped == &node1); - assert(list == nullptr); - assert(popped->next() == popped); - assert(popped->prev() == popped); + SASSERT(popped == &node1); + SASSERT(list == nullptr); + SASSERT(popped->next() == popped); + SASSERT(popped->prev() == popped); std::cout << "test_pop passed." << std::endl; } @@ -83,12 +83,12 @@ void test_insert_after() { TestNode node1(1); TestNode node2(2); node1.insert_after(&node2); - assert(node1.next() == &node2); - assert(node2.prev() == &node1); - assert(node1.prev() == &node2); - assert(node2.next() == &node1); - assert(node1.invariant()); - assert(node2.invariant()); + SASSERT(node1.next() == &node2); + SASSERT(node2.prev() == &node1); + SASSERT(node1.prev() == &node2); + SASSERT(node2.next() == &node1); + SASSERT(node1.invariant()); + SASSERT(node2.invariant()); std::cout << "test_insert_after passed." << std::endl; } @@ -97,24 +97,39 @@ void test_insert_before() { TestNode node1(1); TestNode node2(2); node1.insert_before(&node2); - assert(node1.prev() == &node2); - assert(node2.next() == &node1); - assert(node1.next() == &node2); - assert(node2.prev() == &node1); - assert(node1.invariant()); - assert(node2.invariant()); + SASSERT(node1.prev() == &node2); + SASSERT(node2.next() == &node1); + SASSERT(node1.next() == &node2); + SASSERT(node2.prev() == &node1); + SASSERT(node1.invariant()); + SASSERT(node2.invariant()); std::cout << "test_insert_before passed." << std::endl; } +// Test the remove_from() method +void test_remove_from() { + TestNode* list = nullptr; + TestNode node1(1); + TestNode node2(2); + TestNode::push_to_front(list, &node1); + TestNode::push_to_front(list, &node2); + TestNode::remove_from(list, &node1); + SASSERT(list == &node2); + SASSERT(node2.next() == &node2); + SASSERT(node2.prev() == &node2); + SASSERT(node1.next() == &node1); + SASSERT(node1.prev() == &node1); + std::cout << "test_remove_from passed." << std::endl; +} // Test the push_to_front() method void test_push_to_front() { TestNode* list = nullptr; TestNode node1(1); TestNode::push_to_front(list, &node1); - assert(list == &node1); - assert(node1.next() == &node1); - assert(node1.prev() == &node1); + SASSERT(list == &node1); + SASSERT(node1.next() == &node1); + SASSERT(node1.prev() == &node1); std::cout << "test_push_to_front passed." << std::endl; } @@ -122,20 +137,20 @@ void test_push_to_front() { void test_detach() { TestNode node(1); TestNode::detach(&node); - assert(node.next() == &node); - assert(node.prev() == &node); - assert(node.invariant()); + SASSERT(node.next() == &node); + SASSERT(node.prev() == &node); + SASSERT(node.invariant()); std::cout << "test_detach passed." << std::endl; } // Test the invariant() method void test_invariant() { TestNode node1(1); - assert(node1.invariant()); + SASSERT(node1.invariant()); TestNode node2(2); node1.insert_after(&node2); - assert(node1.invariant()); - assert(node2.invariant()); + SASSERT(node1.invariant()); + SASSERT(node2.invariant()); std::cout << "test_invariant passed." << std::endl; } @@ -146,10 +161,10 @@ void test_contains() { TestNode node2(2); TestNode::push_to_front(list, &node1); TestNode::push_to_front(list, &node2); - assert(TestNode::contains(list, &node1)); - assert(TestNode::contains(list, &node2)); + SASSERT(TestNode::contains(list, &node1)); + SASSERT(TestNode::contains(list, &node2)); TestNode node3(3); - assert(!TestNode::contains(list, &node3)); + SASSERT(!TestNode::contains(list, &node3)); std::cout << "test_contains passed." << std::endl; } From ea9fa17f8634f6f91d8d033dd92244bd992e00be Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 2 Aug 2024 11:38:03 -0700 Subject: [PATCH 037/187] add static Signed-off-by: Nikolaj Bjorner --- src/test/dlist.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp index dd1b6609d..bf404631b 100644 --- a/src/test/dlist.cpp +++ b/src/test/dlist.cpp @@ -35,28 +35,28 @@ void test_prev() { } // Test the next() method -void test_next() { +static void test_next() { TestNode node(1); SASSERT(node.next() == &node); std::cout << "test_next passed." << std::endl; } // Test the const prev() method -void test_const_prev() { +static void test_const_prev() { const TestNode node(1); SASSERT(node.prev() == &node); std::cout << "test_const_prev passed." << std::endl; } // Test the const next() method -void test_const_next() { +static void test_const_next() { const TestNode node(1); SASSERT(node.next() == &node); std::cout << "test_const_next passed." << std::endl; } // Test the init() method -void test_init() { +static void test_init() { TestNode node(1); node.init(&node); SASSERT(node.next() == &node); @@ -66,7 +66,7 @@ void test_init() { } // Test the pop() method -void test_pop() { +static void test_pop() { TestNode* list = nullptr; TestNode node1(1); TestNode::push_to_front(list, &node1); @@ -79,7 +79,7 @@ void test_pop() { } // Test the insert_after() method -void test_insert_after() { +static void test_insert_after() { TestNode node1(1); TestNode node2(2); node1.insert_after(&node2); @@ -93,7 +93,7 @@ void test_insert_after() { } // Test the insert_before() method -void test_insert_before() { +static void test_insert_before() { TestNode node1(1); TestNode node2(2); node1.insert_before(&node2); @@ -107,7 +107,7 @@ void test_insert_before() { } // Test the remove_from() method -void test_remove_from() { +static void test_remove_from() { TestNode* list = nullptr; TestNode node1(1); TestNode node2(2); @@ -123,7 +123,7 @@ void test_remove_from() { } // Test the push_to_front() method -void test_push_to_front() { +static void test_push_to_front() { TestNode* list = nullptr; TestNode node1(1); TestNode::push_to_front(list, &node1); @@ -134,7 +134,7 @@ void test_push_to_front() { } // Test the detach() method -void test_detach() { +static void test_detach() { TestNode node(1); TestNode::detach(&node); SASSERT(node.next() == &node); @@ -144,7 +144,7 @@ void test_detach() { } // Test the invariant() method -void test_invariant() { +static void test_invariant() { TestNode node1(1); SASSERT(node1.invariant()); TestNode node2(2); @@ -155,7 +155,7 @@ void test_invariant() { } // Test the contains() method -void test_contains() { +static void test_contains() { TestNode* list = nullptr; TestNode node1(1); TestNode node2(2); From fce4b36dad6582f3eb233e2f3b0002e64cba22c0 Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Fri, 2 Aug 2024 18:29:33 -0700 Subject: [PATCH 038/187] add apply_permutation tests (#7322) * add permutation unit tests * update test * update * Update permutation.cpp fix macos build * add apply_permutation tests * update test * Update permutation.cpp * fix permutation tests --------- Co-authored-by: Nikolaj Bjorner --- src/test/permutation.cpp | 84 +++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/src/test/permutation.cpp b/src/test/permutation.cpp index 31b83b9d1..aeaa5a235 100644 --- a/src/test/permutation.cpp +++ b/src/test/permutation.cpp @@ -2,10 +2,11 @@ #include #include "util/permutation.h" #include "util/util.h" +#include "util/debug.h" -void swap(unsigned m1, unsigned m2) noexcept { std::swap(m1, m2); } + void swap(unsigned m1, unsigned m2) noexcept { std::swap(m1, m2); } -void test_constructor() { +static void test_constructor() { permutation p(5); for (unsigned i = 0; i < 5; ++i) { SASSERT(p(i) == i); @@ -13,7 +14,7 @@ void test_constructor() { } } -void test_reset() { +static void test_reset() { permutation p(3); p.swap(0, 2); p.reset(3); @@ -23,7 +24,7 @@ void test_reset() { } } -void test_swap() { +static void test_swap() { permutation p(4); p.swap(1, 3); SASSERT(p(1) == 3); @@ -32,7 +33,7 @@ void test_swap() { SASSERT(p.inv(3) == 1); } -void test_move_after() { +static void test_move_after() { permutation p(5); p.move_after(1, 3); SASSERT(p(0) == 0); @@ -42,36 +43,36 @@ void test_move_after() { SASSERT(p(4) == 4); } -void test_apply_permutation() { - permutation p(4); - int data[] = {10, 20, 30, 40}; - unsigned perm[] = {2, 1, 0, 3}; - apply_permutation(4, data, perm); - std::cout << "000 " << data[0] << std::endl; - std::cout << "222 " << data[2] << std::endl; - - SASSERT(data[0] == 10); - SASSERT(data[1] == 20); - SASSERT(data[2] == 30); - SASSERT(data[3] == 40); +void apply_permutation_copy(unsigned sz, unsigned const * src, unsigned const * p, unsigned * target) { + for (unsigned i = 0; i < sz; i++) { + target[i] = src[p[i]]; + } } -void test_apply_permutation_core() -{ - permutation p(4); - int data[] = {10, 20, 30, 40}; - unsigned perm[] = {2, 1, 0, 3}; - apply_permutation_core(4, data, perm); - std::cout << "000 " << data[0] << std::endl; - std::cout << "222 " << data[2] << std::endl; - - SASSERT(data[0] == 10); - SASSERT(data[1] == 20); - SASSERT(data[2] == 30); - SASSERT(data[3] == 40); +static void test_apply_permutation(unsigned sz, unsigned num_tries, unsigned max = UINT_MAX) { + unsigned_vector data; + unsigned_vector p; + unsigned_vector new_data; + data.resize(sz); + p.resize(sz); + new_data.resize(sz); + random_gen g; + for (unsigned i = 0; i < sz; i++) + p[i] = i; + // fill data with random numbers + for (unsigned i = 0; i < sz; i++) + data[i] = g() % max; + for (unsigned k = 0; k < num_tries; k ++) { + shuffle(p.size(), p.data(), g); + apply_permutation_copy(sz, data.data(), p.data(), new_data.data()); + apply_permutation(sz, data.data(), p.data()); + for (unsigned i = 0; i < 0; i++) + ENSURE(data[i] == new_data[i]); + } } -void test_check_invariant() { + +static void test_check_invariant() { permutation p(4); SASSERT(p.check_invariant()); p.swap(0, 2); @@ -80,7 +81,7 @@ void test_check_invariant() { SASSERT(p.check_invariant()); } -void test_display() { +static void test_display() { permutation p(4); std::ostringstream out; p.display(out); @@ -92,10 +93,23 @@ void tst_permutation() { test_reset(); test_swap(); test_move_after(); - // test_apply_permutation(); - // test_apply_permutation_core(); test_check_invariant(); test_display(); - + test_apply_permutation(10, 1000, 5); + test_apply_permutation(10, 1000, 1000); + test_apply_permutation(10, 1000, UINT_MAX); + test_apply_permutation(100, 1000, 33); + test_apply_permutation(100, 1000, 1000); + test_apply_permutation(100, 1000, UINT_MAX); + test_apply_permutation(1000, 1000, 121); + test_apply_permutation(1000, 1000, 1000); + test_apply_permutation(1000, 1000, UINT_MAX); + test_apply_permutation(33, 1000, 121); + test_apply_permutation(33, 1000, 1000); + test_apply_permutation(33, 1000, UINT_MAX); + test_apply_permutation(121, 1000, 121); + test_apply_permutation(121, 1000, 1000); + test_apply_permutation(121, 1000, UINT_MAX); + std::cout << "All tests passed!" << std::endl; } From d2fc085b8cee03bf2bfc89ecdc90c1c3c743e12b Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Fri, 2 Aug 2024 18:29:50 -0700 Subject: [PATCH 039/187] update heap unit tests (#7324) * new heap invariants * change ENSURE to SASSERT for unit test heap * change SASSERT to VERIFY * update heap tests * update * remove one invariant --- src/test/heap.cpp | 3 +-- src/util/heap.h | 13 +++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/test/heap.cpp b/src/test/heap.cpp index 6a5bc7b9f..25a509dc8 100644 --- a/src/test/heap.cpp +++ b/src/test/heap.cpp @@ -27,7 +27,7 @@ struct lt_proc { bool operator()(int v1, int v2) const { return v1 < v2; } }; //struct int_hash_proc { unsigned operator()(int v) const { std::cout << "hash " << v << "\n"; VERIFY(v >= 0); return v; }}; //typedef int_hashtable > int_set; typedef heap int_heap; -#define N 10000 +#define N 100 static random_gen heap_rand(1); @@ -146,4 +146,3 @@ void tst_heap() { tst2(); } } - diff --git a/src/util/heap.h b/src/util/heap.h index c080c6ebd..71cafeeb8 100644 --- a/src/util/heap.h +++ b/src/util/heap.h @@ -55,6 +55,19 @@ class heap : private LT { } bool check_invariant_core(int idx) const { + + // Check that m_values starts with a dummy value at index 0. + if (m_values.empty() || m_values[0] != -1) { + return false; + } + + // // All indices in m_value2indices that are not used in m_values should be 0 + // for (int val = 0; val < static_cast(m_value2indices.size()); ++val) { + // if (std::find(m_values.begin(), m_values.end(), val) == m_values.end() && m_value2indices[val] != 0) { + // return false; // Unused indices should have a 0 value + // } + // } + if (idx < static_cast(m_values.size())) { SASSERT(m_value2indices[m_values[idx]] == idx); SASSERT(parent(idx) == 0 || !less_than(m_values[idx], m_values[parent(idx)])); From 7c30cbfe48f65f9aa27a954c7ad5845863a6ea94 Mon Sep 17 00:00:00 2001 From: LiviaSun <33578456+ChuyueSun@users.noreply.github.com> Date: Fri, 2 Aug 2024 19:21:40 -0700 Subject: [PATCH 040/187] add scoped_vector invariants and unit tests (#7327) * add scoped vector unit test * fix dlist tests * add new scoped vector invariants * remove all loop invariants --- src/test/CMakeLists.txt | 1 + src/test/dlist.cpp | 2 - src/test/main.cpp | 1 + src/test/scoped_vector.cpp | 99 ++++++++++++++++++++++++++++++++++++++ src/util/scoped_vector.h | 44 +++++++++++++++-- 5 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 src/test/scoped_vector.cpp diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 8464cedf9..658647ea6 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -106,6 +106,7 @@ add_executable(test-z3 sat_lookahead.cpp sat_user_scope.cpp scoped_timer.cpp + scoped_vector.cpp simple_parser.cpp simplex.cpp simplifier.cpp diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp index bf404631b..32a54f9ff 100644 --- a/src/test/dlist.cpp +++ b/src/test/dlist.cpp @@ -117,8 +117,6 @@ static void test_remove_from() { SASSERT(list == &node2); SASSERT(node2.next() == &node2); SASSERT(node2.prev() == &node2); - SASSERT(node1.next() == &node1); - SASSERT(node1.prev() == &node1); std::cout << "test_remove_from passed." << std::endl; } diff --git a/src/test/main.cpp b/src/test/main.cpp index 0d3679529..f028d6ceb 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -269,4 +269,5 @@ int main(int argc, char ** argv) { TST(euf_bv_plugin); TST(euf_arith_plugin); TST(sls_test); + TST(scoped_vector); } diff --git a/src/test/scoped_vector.cpp b/src/test/scoped_vector.cpp new file mode 100644 index 000000000..05d98fcf1 --- /dev/null +++ b/src/test/scoped_vector.cpp @@ -0,0 +1,99 @@ +#include +#include "util/scoped_vector.h" + +void test_push_back_and_access() { + scoped_vector sv; + sv.push_back(10); + + sv.push_back(20); + + SASSERT(sv.size() == 2); + SASSERT(sv[0] == 10); + SASSERT(sv[1] == 20); + + std::cout << "test_push_back_and_access passed." << std::endl; +} + +void test_scopes() { + scoped_vector sv; + sv.push_back(10); + sv.push_back(20); + + sv.push_scope(); + sv.push_back(30); + sv.push_back(40); + + SASSERT(sv.size() == 4); + SASSERT(sv[2] == 30); + SASSERT(sv[3] == 40); + + sv.pop_scope(1); + + std::cout << "test_scopes passed." << std::endl; + SASSERT(sv.size() == 2); + SASSERT(sv[0] == 10); + SASSERT(sv[1] == 20); + + std::cout << "test_scopes passed." << std::endl; +} + +void test_set() { + scoped_vector sv; + sv.push_back(10); + sv.push_back(20); + + sv.set(0, 30); + sv.set(1, 40); + + SASSERT(sv.size() == 2); + SASSERT(sv[0] == 30); + SASSERT(sv[1] == 40); + + sv.push_scope(); + sv.set(0, 50); + SASSERT(sv[0] == 50); + sv.pop_scope(1); + SASSERT(sv[0] == 30); + + std::cout << "test_set passed." << std::endl; +} + +void test_pop_back() { + scoped_vector sv; + sv.push_back(10); + sv.push_back(20); + + SASSERT(sv.size() == 2); + sv.pop_back(); + SASSERT(sv.size() == 1); + SASSERT(sv[0] == 10); + sv.pop_back(); + SASSERT(sv.size() == 0); + + std::cout << "test_pop_back passed." << std::endl; +} + +void test_erase_and_swap() { + scoped_vector sv; + sv.push_back(10); + sv.push_back(20); + sv.push_back(30); + + sv.erase_and_swap(1); + + SASSERT(sv.size() == 2); + SASSERT(sv[0] == 10); + SASSERT(sv[1] == 30); + + std::cout << "test_erase_and_swap passed." << std::endl; +} + +void tst_scoped_vector() { + test_push_back_and_access(); + test_scopes(); + test_set(); + test_pop_back(); + test_erase_and_swap(); + + std::cout << "All tests passed." << std::endl; +} diff --git a/src/util/scoped_vector.h b/src/util/scoped_vector.h index 2c6cfaa21..7d0cec472 100644 --- a/src/util/scoped_vector.h +++ b/src/util/scoped_vector.h @@ -176,8 +176,46 @@ private: } bool invariant() const { - return - m_size <= m_elems.size() && - m_elems_start <= m_elems.size(); + + + if (!(m_size <= m_elems.size() && m_elems_start <= m_elems.size())) + return false; + + // Check that source and destination trails have the same length. + if (m_src.size() != m_dst.size()) + return false; + // The size of m_src, m_dst, and m_src_lim should be consistent with the scope stack. + if (m_src_lim.size() != m_sizes.size() || m_src.size() != m_dst.size()) + return false; + + // // m_elems_lim stores the past sizes of m_elems for each scope. Each element in m_elems_lim should be + // // within bounds and in non-decreasing order. + // for (unsigned i = 1; i < m_elems_lim.size(); ++i) { + // if (m_elems_lim[i - 1] > m_elems_lim[i]) return false; + // } + + + // // m_sizes tracks the size of the vector at each scope level. + // // Each element in m_sizes should be non-decreasing and within the size of m_elems. + // for (unsigned i = 1; i < m_sizes.size(); ++i) { + // if (m_sizes[i - 1] > m_sizes[i]) + // return false; + // } + + // // The m_src and m_dst vectors should have the same size and should contain valid indices. + // if (m_src.size() != m_dst.size()) return false; + // for (unsigned i = 0; i < m_src.size(); ++i) { + // if (m_src[i] >= m_index.size() || m_dst[i] >= m_elems.size()) return false; + // } + + + // // The size of m_src_lim should be less than or equal to the size of m_sizes and store valid indices. + // if (m_src_lim.size() > m_sizes.size()) return false; + // for (unsigned elem : m_src_lim) { + // if (elem > m_src.size()) return false; + // } + + return true; + } }; From 51fcb10b2ff0e4496a3c0c2ed7c32f0876c9ee49 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 2 Aug 2024 20:00:45 -0700 Subject: [PATCH 041/187] shave some overhead from fingerprint hash function #7281 --- src/smt/fingerprints.cpp | 28 ++++++++++++++++++++++++++-- src/smt/fingerprints.h | 8 +------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/smt/fingerprints.cpp b/src/smt/fingerprints.cpp index 447c2b2a1..ac13999d0 100644 --- a/src/smt/fingerprints.cpp +++ b/src/smt/fingerprints.cpp @@ -63,6 +63,26 @@ namespace smt { fingerprint * fingerprint_set::insert(void * data, unsigned data_hash, unsigned num_args, enode * const * args, expr* def) { + + struct arg_data { + unsigned data_hash; + enode* const* args; + }; + struct khash { + unsigned operator()(arg_data const& d) const { + return d.data_hash; + } + }; + struct arghash { + unsigned operator()(arg_data const& d, unsigned i) const { + return d.args[i]->hash(); + } + }; + arg_data arg_data({ data_hash, args }); + khash kh; + arghash ah; + data_hash = get_composite_hash(arg_data, num_args, kh, ah); + fingerprint * d = mk_dummy(data, data_hash, num_args, args); if (m_set.contains(d)) return nullptr; @@ -107,8 +127,12 @@ namespace smt { unsigned new_lvl = lvl - num_scopes; unsigned old_size = m_scopes[new_lvl]; unsigned size = m_fingerprints.size(); - for (unsigned i = old_size; i < size; i++) - m_set.erase(m_fingerprints[i]); + if (old_size == 0 && size > 0) + m_set.reset(); + else { + for (unsigned i = old_size; i < size; i++) + m_set.erase(m_fingerprints[i]); + } m_fingerprints.shrink(old_size); m_defs.shrink(old_size); m_scopes.shrink(new_lvl); diff --git a/src/smt/fingerprints.h b/src/smt/fingerprints.h index b1904a4ee..a602f25cd 100644 --- a/src/smt/fingerprints.h +++ b/src/smt/fingerprints.h @@ -48,15 +48,9 @@ namespace smt { class fingerprint_set { - struct fingerprint_khasher { - unsigned operator()(fingerprint const * f) const { return f->get_data_hash(); } - }; - struct fingerprint_chasher { - unsigned operator()(fingerprint const * f, unsigned idx) const { return f->get_arg(idx)->hash(); } - }; struct fingerprint_hash_proc { unsigned operator()(fingerprint const * f) const { - return get_composite_hash(const_cast(f), f->get_num_args()); + return f->get_data_hash(); } }; struct fingerprint_eq_proc { bool operator()(fingerprint const * f1, fingerprint const * f2) const; }; From d6040ee5ab07da9c84e30754f232a0f75f4c0a3d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 3 Aug 2024 09:29:11 -0700 Subject: [PATCH 042/187] do not copy artifacts from CI pipeline Signed-off-by: Nikolaj Bjorner --- azure-pipelines.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b3bc0f226..48dcf094a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -66,15 +66,6 @@ jobs: scriptPath: scripts/mk_unix_dist.py arguments: --nodotnet --nojava --arch=arm64 pythonInterpreter: $(python) - - task: CopyFiles@2 - inputs: - sourceFolder: dist - contents: '*.zip' - targetFolder: $(Build.ArtifactStagingDirectory) - - task: PublishPipelineArtifact@0 - inputs: - artifactName: 'ManyLinuxBuildArm64' - targetPath: $(Build.ArtifactStagingDirectory) - job: "Ubuntu20OCaml" displayName: "Ubuntu 20 with OCaml" From bc8fa67afc9bb37c4b646d4b99efc0b0ec7d23d7 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 3 Aug 2024 09:37:14 -0700 Subject: [PATCH 043/187] #7255 #7328 Signed-off-by: Nikolaj Bjorner --- src/smt/smt_context.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 62c7c8ddd..a01a655f3 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -1117,6 +1117,8 @@ namespace smt { */ bool context::is_diseq(enode * n1, enode * n2) const { SASSERT(n1->get_sort() == n2->get_sort()); + if (m.are_distinct(n1->get_expr(), n2->get_expr())) + return true; context * _this = const_cast(this); if (!m_is_diseq_tmp) { app * eq = m.mk_eq(n1->get_expr(), n2->get_expr()); From 52f8eb21fb995465f2deaf138ba75f74108e1fc3 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 3 Aug 2024 09:39:19 -0700 Subject: [PATCH 044/187] #7255 #7328 Signed-off-by: Nikolaj Bjorner --- src/smt/smt_context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index a01a655f3..428460801 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -1117,7 +1117,7 @@ namespace smt { */ bool context::is_diseq(enode * n1, enode * n2) const { SASSERT(n1->get_sort() == n2->get_sort()); - if (m.are_distinct(n1->get_expr(), n2->get_expr())) + if (m.are_distinct(n1->get_root()->get_expr(), n2->get_root()->get_expr())) return true; context * _this = const_cast(this); if (!m_is_diseq_tmp) { From 26b8d634a318b3aa0bacbcbaadbf8e5234d21034 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 3 Aug 2024 11:34:28 -0700 Subject: [PATCH 045/187] add max conflict throttle to SAT based QFNIA tactic #7329 Signed-off-by: Nikolaj Bjorner --- src/tactic/smtlogics/qfnia_tactic.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tactic/smtlogics/qfnia_tactic.cpp b/src/tactic/smtlogics/qfnia_tactic.cpp index 0dad56a19..25dc34d9c 100644 --- a/src/tactic/smtlogics/qfnia_tactic.cpp +++ b/src/tactic/smtlogics/qfnia_tactic.cpp @@ -45,6 +45,7 @@ static tactic * mk_qfnia_bv_solver(ast_manager & m, params_ref const & p_ref) { params_ref mem_p = p; mem_p.set_uint("max_memory", 100); + mem_p.set_uint("max_conflicts", 500); tactic * r = using_params(and_then(mk_simplify_tactic(m), @@ -52,7 +53,7 @@ static tactic * mk_qfnia_bv_solver(ast_manager & m, params_ref const & p_ref) { using_params(mk_simplify_tactic(m), simp2_p), mk_max_bv_sharing_tactic(m), using_params(mk_bit_blaster_tactic(m), mem_p), - mk_sat_tactic(m)), + mk_sat_tactic(m, mem_p)), p); return r; } From 3e518b9e8b387f1bb664a619e0aec45f4b62dfba Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 6 Aug 2024 03:54:25 -0700 Subject: [PATCH 046/187] fix #7331 --- src/ast/ast_smt_pp.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/ast/ast_smt_pp.cpp b/src/ast/ast_smt_pp.cpp index 0da4f1c12..68936ac49 100644 --- a/src/ast/ast_smt_pp.cpp +++ b/src/ast/ast_smt_pp.cpp @@ -31,6 +31,7 @@ Revision History: #include "ast/datatype_decl_plugin.h" #include "ast/seq_decl_plugin.h" #include "ast/fpa_decl_plugin.h" +#include "ast/recfun_decl_plugin.h" #include "ast/for_each_ast.h" #include "ast/decl_collector.h" #include "math/polynomial/algebraic_numbers.h" @@ -1000,6 +1001,18 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) { } } + vector> recfuns; + recfun::util u(m); + for (auto f : decls.get_rec_decls()) + recfuns.push_back({f, u.get_def(f).get_rhs()}); + + + if (!recfuns.empty()) { + smt2_pp_environment_dbg env(m); + ast_smt2_pp_recdefs(strm, recfuns, env); + } + + #endif for (expr* a : m_assumptions) { From 6ce0fcd3eff26caedac3c27091629319d8c101c9 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Fri, 2 Aug 2024 06:28:11 -1000 Subject: [PATCH 047/187] port sample cell projection Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_explain.cpp | 299 +++++++++++++++++++++++++++++++++--- src/nlsat/nlsat_explain.h | 3 +- src/nlsat/nlsat_params.pyg | 3 +- src/nlsat/nlsat_solver.cpp | 2 +- 4 files changed, 285 insertions(+), 22 deletions(-) diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp index 618394ac1..c7d072232 100644 --- a/src/nlsat/nlsat_explain.cpp +++ b/src/nlsat/nlsat_explain.cpp @@ -45,6 +45,8 @@ namespace nlsat { bool m_minimize_cores; bool m_factor; bool m_signed_project; + bool m_cell_sample; + struct todo_set { polynomial::cache & m_cache; @@ -130,7 +132,7 @@ namespace nlsat { evaluator & m_evaluator; imp(solver & s, assignment const & x2v, polynomial::cache & u, atom_vector const & atoms, atom_vector const & x2eq, - evaluator & ev): + evaluator & ev, bool is_sample): m_solver(s), m_assignment(x2v), m_atoms(atoms), @@ -148,6 +150,9 @@ namespace nlsat { m_core1(s), m_core2(s), m_result(nullptr), + + m_cell_sample(is_sample), + m_evaluator(ev) { m_simplify_cores = false; m_full_dimensional = false; @@ -646,6 +651,51 @@ namespace nlsat { m_todo.insert(p); } } + + void add_sample_coeff(polynomial_ref_vector &ps, var x){ + polynomial_ref p(m_pm); + polynomial_ref lc(m_pm); + unsigned sz = ps.size(); + for (unsigned i = 0; i < sz; i++){ + p = ps.get(i); + unsigned k = degree(p, x); + SASSERT(k > 0); + TRACE("nlsat_explain", tout << "add_lc, x: "; display_var(tout, x); tout << "\nk: " << k << "\n"; display(tout, p); tout << "\n";); + for(; k > 0; k--){ + lc = m_pm.coeff(p, x, k); + add_factors(lc); + if (m_pm.nonzero_const_coeff(p, x, k)){ + TRACE("nlsat_explain", tout << "constant coefficient, skipping...\n";); + break; + } + } + SASSERT(sign(lc) != 0); + SASSERT(!is_const(lc)); + } + } + + void psc_resultant_sample(polynomial_ref_vector &ps, var x, polynomial_ref_vector & samples){ + polynomial_ref p(m_pm); + polynomial_ref q(m_pm); + + + // polynomial_ref_vector samples(m_pm); + // samples.reset(); + // sample_poly(ps, x, samples); + + SASSERT(samples.size() <= 2); + + for (unsigned i = 0; i < ps.size(); i++){ + p = ps.get(i); + for (unsigned j = 0; j < samples.size(); j++){ + q = samples.get(j); + if (!m_pm.eq(p, q)) { + psc(p, q, x); + } + } + } + } + /** \brief Add leading coefficients of the polynomials in ps. @@ -973,6 +1023,116 @@ namespace nlsat { add_simple_assumption(k, p, lsign); } + void cac_add_cell_lits(polynomial_ref_vector & ps, var y, polynomial_ref_vector & res) { + res.reset(); + SASSERT(m_assignment.is_assigned(y)); + bool lower_inf = true; + bool upper_inf = true; + scoped_anum_vector & roots = m_roots_tmp; + scoped_anum lower(m_am); + scoped_anum upper(m_am); + anum const & y_val = m_assignment.value(y); + TRACE("nlsat_explain", tout << "adding literals for "; display_var(tout, y); tout << " -> "; + m_am.display_decimal(tout, y_val); tout << "\n";); + polynomial_ref p_lower(m_pm); + unsigned i_lower = UINT_MAX; + polynomial_ref p_upper(m_pm); + unsigned i_upper = UINT_MAX; + polynomial_ref p(m_pm); + unsigned sz = ps.size(); + for (unsigned k = 0; k < sz; k++) { + p = ps.get(k); + if (max_var(p) != y) + continue; + roots.reset(); + // Variable y is assigned in m_assignment. We must temporarily unassign it. + // Otherwise, the isolate_roots procedure will assume p is a constant polynomial. + m_am.isolate_roots(p, undef_var_assignment(m_assignment, y), roots); + unsigned num_roots = roots.size(); +//#linxi begin add_cell_lits faster + bool all_lt = true; + for (unsigned i = 0; i < num_roots; i++) { + int s = m_am.compare(y_val, roots[i]); + TRACE("nlsat_explain", + m_am.display_decimal(tout << "comparing root: ", roots[i]); tout << "\n"; + m_am.display_decimal(tout << "with y_val:", y_val); + tout << "\nsign " << s << "\n"; + tout << "poly: " << p << "\n"; + ); + if (s == 0) { + // y_val == roots[i] + // add literal + // ! (y = root_i(p)) + add_root_literal(atom::ROOT_EQ, y, i+1, p); + res.push_back(p); + return; + } + else if (s < 0) { + // y_val < roots[i] + if (i > 0) { + // y_val > roots[j] + int j = i - 1; + if (lower_inf || m_am.lt(lower, roots[j])) { + lower_inf = false; + m_am.set(lower, roots[j]); + p_lower = p; + i_lower = j + 1; + } + } + if (upper_inf || m_am.lt(roots[i], upper)) { + upper_inf = false; + m_am.set(upper, roots[i]); + p_upper = p; + i_upper = i + 1; + } + all_lt = false; + break; + } + // else if (s < 0) { + // // y_val < roots[i] + + // // check if roots[i] is a better upper bound + // if (upper_inf || m_am.lt(roots[i], upper)) { + // upper_inf = false; + // m_am.set(upper, roots[i]); + // p_upper = p; + // i_upper = i+1; + // } + // } + // else if (s > 0) { + // // roots[i] < y_val + + // // check if roots[i] is a better lower bound + // if (lower_inf || m_am.lt(lower, roots[i])) { + // lower_inf = false; + // m_am.set(lower, roots[i]); + // p_lower = p; + // i_lower = i+1; + // } + // } + } + if (all_lt && num_roots > 0) { + int j = num_roots - 1; + if (lower_inf || m_am.lt(lower, roots[j])) { + lower_inf = false; + m_am.set(lower, roots[j]); + p_lower = p; + i_lower = j + 1; + } + } +//#linxi end add_cell_lits faster + } + + if (!lower_inf) { + res.push_back(p_lower); + add_root_literal(m_full_dimensional ? atom::ROOT_GE : atom::ROOT_GT, y, i_lower, p_lower); + } + if (!upper_inf) { + res.push_back(p_upper); + add_root_literal(m_full_dimensional ? atom::ROOT_LE : atom::ROOT_LT, y, i_upper, p_upper); + } + } + /** Add one or two literals that specify in which cell of variable y the current interpretation is. One literal is added for the cases: @@ -1016,6 +1176,8 @@ namespace nlsat { // Otherwise, the isolate_roots procedure will assume p is a constant polynomial. m_am.isolate_roots(p, undef_var_assignment(m_assignment, y), roots); unsigned num_roots = roots.size(); +//#linxi begin add_cell_lits faster + bool all_lt = true; for (unsigned i = 0; i < num_roots; i++) { int s = m_am.compare(y_val, roots[i]); TRACE("nlsat_explain", @@ -1033,27 +1195,58 @@ namespace nlsat { } else if (s < 0) { // y_val < roots[i] - - // check if roots[i] is a better upper bound + if (i > 0) { + // y_val > roots[j] + int j = i - 1; + if (lower_inf || m_am.lt(lower, roots[j])) { + lower_inf = false; + m_am.set(lower, roots[j]); + p_lower = p; + i_lower = j + 1; + } + } if (upper_inf || m_am.lt(roots[i], upper)) { upper_inf = false; m_am.set(upper, roots[i]); p_upper = p; - i_upper = i+1; + i_upper = i + 1; } + all_lt = false; + break; } - else if (s > 0) { - // roots[i] < y_val + // else if (s < 0) { + // // y_val < roots[i] + + // // check if roots[i] is a better upper bound + // if (upper_inf || m_am.lt(roots[i], upper)) { + // upper_inf = false; + // m_am.set(upper, roots[i]); + // p_upper = p; + // i_upper = i+1; + // } + // } + // else if (s > 0) { + // // roots[i] < y_val - // check if roots[i] is a better lower bound - if (lower_inf || m_am.lt(lower, roots[i])) { - lower_inf = false; - m_am.set(lower, roots[i]); - p_lower = p; - i_lower = i+1; - } + // // check if roots[i] is a better lower bound + // if (lower_inf || m_am.lt(lower, roots[i])) { + // lower_inf = false; + // m_am.set(lower, roots[i]); + // p_lower = p; + // i_lower = i+1; + // } + // } + } + if (all_lt && num_roots > 0) { + int j = num_roots - 1; + if (lower_inf || m_am.lt(lower, roots[j])) { + lower_inf = false; + m_am.set(lower, roots[j]); + p_lower = p; + i_lower = j + 1; } } +//#linxi end add_cell_lits faster } if (!lower_inf) { @@ -1064,6 +1257,7 @@ namespace nlsat { } } + /** \brief Return true if all polynomials in ps are univariate in x. */ @@ -1082,7 +1276,8 @@ namespace nlsat { /** \brief Apply model-based projection operation defined in our paper. */ - void project(polynomial_ref_vector & ps, var max_x) { + + void project_original(polynomial_ref_vector & ps, var max_x) { if (ps.empty()) return; m_todo.reset(); @@ -1094,12 +1289,12 @@ namespace nlsat { if (x < max_x) add_cell_lits(ps, x); while (true) { - TRACE("nlsat_explain", tout << "project loop, processing var "; display_var(tout, x); tout << "\npolynomials\n"; - display(tout, ps); tout << "\n";); if (all_univ(ps, x) && m_todo.empty()) { m_todo.reset(); break; } + TRACE("nlsat_explain", tout << "project loop, processing var "; display_var(tout, x); tout << "\npolynomials\n"; + display(tout, ps); tout << "\n";); add_lc(ps, x); psc_discriminant(ps, x); psc_resultant(ps, x); @@ -1109,6 +1304,72 @@ namespace nlsat { add_cell_lits(ps, x); } } + void project_cdcac(polynomial_ref_vector & ps, var max_x) { + // whz + bool first = true; + + + if (ps.empty()) + return; + m_todo.reset(); + for (poly* p : ps) { + m_todo.insert(p); + } + var x = m_todo.remove_max_polys(ps); + // Remark: after vanishing coefficients are eliminated, ps may not contain max_x anymore + + polynomial_ref_vector samples(m_pm); + + + if (x < max_x){ + cac_add_cell_lits(ps, x, samples); + } + + while (true) { + if (all_univ(ps, x) && m_todo.empty()) { + m_todo.reset(); + break; + } + TRACE("nlsat_explain", tout << "project loop, processing var "; display_var(tout, x); tout << "\npolynomials\n"; + display(tout, ps); tout << "\n";); + + + /** + * Sample Projection + * Reference: + * Haokun Li and Bican Xia. + * "Solving Satisfiability of Polynomial Formulas By Sample - Cell Projection" + * https://arxiv.org/abs/2003.00409 + */ + + if (first) { + add_lc(ps, x); + psc_discriminant(ps, x); + psc_resultant(ps, x); + first = false; + } + + else { + add_lc(ps, x); + // add_sample_coeff(ps, x); + psc_discriminant(ps, x); + psc_resultant_sample(ps, x, samples); + } + + if (m_todo.empty()) + break; + x = m_todo.remove_max_polys(ps); + cac_add_cell_lits(ps, x, samples); + } + } + void project(polynomial_ref_vector & ps, var max_x) { + if (m_cell_sample) { + project_cdcac(ps, max_x); + } + else { + project_original(ps, max_x); + } + } bool check_already_added() const { for (bool b : m_already_added_literal) { @@ -1474,7 +1735,7 @@ namespace nlsat { var max_x = max_var(m_ps); TRACE("nlsat_explain", tout << "polynomials in the conflict:\n"; display(tout, m_ps); tout << "\n";); elim_vanishing(m_ps); - TRACE("nlsat_explain", tout << "elim vanishing x" << max_x << "\n"; display(tout, m_ps); tout << "\n";); + TRACE("nlsat_explain", tout << "elim vanishing\n"; display(tout, m_ps); tout << "\n";); project(m_ps, max_x); TRACE("nlsat_explain", tout << "after projection\n"; display(tout, m_ps); tout << "\n";); } @@ -1936,8 +2197,8 @@ namespace nlsat { }; explain::explain(solver & s, assignment const & x2v, polynomial::cache & u, - atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev) { - m_imp = alloc(imp, s, x2v, u, atoms, x2eq, ev); + atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev, bool is_sample) { + m_imp = alloc(imp, s, x2v, u, atoms, x2eq, ev, is_sample); } explain::~explain() { diff --git a/src/nlsat/nlsat_explain.h b/src/nlsat/nlsat_explain.h index 20322a680..a19fe3982 100644 --- a/src/nlsat/nlsat_explain.h +++ b/src/nlsat/nlsat_explain.h @@ -34,7 +34,8 @@ namespace nlsat { imp * m_imp; public: explain(solver & s, assignment const & x2v, polynomial::cache & u, - atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev); + atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev, bool is_sample); + ~explain(); void reset(); diff --git a/src/nlsat/nlsat_params.pyg b/src/nlsat/nlsat_params.pyg index cac33fe87..dec3fac94 100644 --- a/src/nlsat/nlsat_params.pyg +++ b/src/nlsat/nlsat_params.pyg @@ -14,6 +14,7 @@ def_module_params('nlsat', ('shuffle_vars', BOOL, False, "use a random variable order."), ('inline_vars', BOOL, False, "inline variables that can be isolated from equations (not supported in incremental mode)"), ('seed', UINT, 0, "random seed."), - ('factor', BOOL, True, "factor polynomials produced during conflict resolution.") + ('factor', BOOL, True, "factor polynomials produced during conflict resolution."), + ('cell_sample', BOOL, True, "cell sample projection"), )) diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index bb169a05e..3d38d7a5e 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -253,7 +253,7 @@ namespace nlsat { m_simplify(s, m_atoms, m_clauses, m_learned, m_pm), m_display_var(m_perm), m_display_assumption(nullptr), - m_explain(s, m_assignment, m_cache, m_atoms, m_var2eq, m_evaluator), + m_explain(s, m_assignment, m_cache, m_atoms, m_var2eq, m_evaluator, nlsat_params(c.m_params).cell_sample()), m_scope_lvl(0), m_lemma(s), m_lazy_clause(s), From a09e412cf033e5c5dca7330314084fb85388ba7f Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Tue, 6 Aug 2024 08:16:31 -1000 Subject: [PATCH 048/187] cleaning up Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_explain.cpp | 58 +++---------------------------------- src/nlsat/nlsat_explain.h | 2 +- 2 files changed, 5 insertions(+), 55 deletions(-) diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp index c7d072232..6efbf4e7f 100644 --- a/src/nlsat/nlsat_explain.cpp +++ b/src/nlsat/nlsat_explain.cpp @@ -45,7 +45,7 @@ namespace nlsat { bool m_minimize_cores; bool m_factor; bool m_signed_project; - bool m_cell_sample; + bool m_cell_sample; struct todo_set { @@ -677,12 +677,6 @@ namespace nlsat { void psc_resultant_sample(polynomial_ref_vector &ps, var x, polynomial_ref_vector & samples){ polynomial_ref p(m_pm); polynomial_ref q(m_pm); - - - // polynomial_ref_vector samples(m_pm); - // samples.reset(); - // sample_poly(ps, x, samples); - SASSERT(samples.size() <= 2); for (unsigned i = 0; i < ps.size(); i++){ @@ -1088,28 +1082,6 @@ namespace nlsat { all_lt = false; break; } - // else if (s < 0) { - // // y_val < roots[i] - - // // check if roots[i] is a better upper bound - // if (upper_inf || m_am.lt(roots[i], upper)) { - // upper_inf = false; - // m_am.set(upper, roots[i]); - // p_upper = p; - // i_upper = i+1; - // } - // } - // else if (s > 0) { - // // roots[i] < y_val - - // // check if roots[i] is a better lower bound - // if (lower_inf || m_am.lt(lower, roots[i])) { - // lower_inf = false; - // m_am.set(lower, roots[i]); - // p_lower = p; - // i_lower = i+1; - // } - // } } if (all_lt && num_roots > 0) { int j = num_roots - 1; @@ -1214,28 +1186,6 @@ namespace nlsat { all_lt = false; break; } - // else if (s < 0) { - // // y_val < roots[i] - - // // check if roots[i] is a better upper bound - // if (upper_inf || m_am.lt(roots[i], upper)) { - // upper_inf = false; - // m_am.set(upper, roots[i]); - // p_upper = p; - // i_upper = i+1; - // } - // } - // else if (s > 0) { - // // roots[i] < y_val - - // // check if roots[i] is a better lower bound - // if (lower_inf || m_am.lt(lower, roots[i])) { - // lower_inf = false; - // m_am.set(lower, roots[i]); - // p_lower = p; - // i_lower = i+1; - // } - // } } if (all_lt && num_roots > 0) { int j = num_roots - 1; @@ -1305,7 +1255,6 @@ namespace nlsat { } } void project_cdcac(polynomial_ref_vector & ps, var max_x) { - // whz bool first = true; @@ -1362,6 +1311,7 @@ namespace nlsat { cac_add_cell_lits(ps, x, samples); } } + void project(polynomial_ref_vector & ps, var max_x) { if (m_cell_sample) { project_cdcac(ps, max_x); @@ -2197,8 +2147,8 @@ namespace nlsat { }; explain::explain(solver & s, assignment const & x2v, polynomial::cache & u, - atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev, bool is_sample) { - m_imp = alloc(imp, s, x2v, u, atoms, x2eq, ev, is_sample); + atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev, bool use_cell_sample) { + m_imp = alloc(imp, s, x2v, u, atoms, x2eq, ev, use_cell_sample); } explain::~explain() { diff --git a/src/nlsat/nlsat_explain.h b/src/nlsat/nlsat_explain.h index a19fe3982..2fdb76b11 100644 --- a/src/nlsat/nlsat_explain.h +++ b/src/nlsat/nlsat_explain.h @@ -34,7 +34,7 @@ namespace nlsat { imp * m_imp; public: explain(solver & s, assignment const & x2v, polynomial::cache & u, - atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev, bool is_sample); + atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev, bool use_cell_sample_proj); ~explain(); From 0306eff6928cbb2bdb9983a80e105abd35d78a85 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Tue, 6 Aug 2024 18:25:31 -1000 Subject: [PATCH 049/187] port look for 0 witness Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_interval_set.cpp | 70 ++++++++++++++++++++++---------- src/nlsat/nlsat_interval_set.h | 5 ++- src/nlsat/nlsat_params.pyg | 6 ++- src/nlsat/nlsat_solver.cpp | 4 +- 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/nlsat/nlsat_interval_set.cpp b/src/nlsat/nlsat_interval_set.cpp index f928fd5b6..0c15d580b 100644 --- a/src/nlsat/nlsat_interval_set.cpp +++ b/src/nlsat/nlsat_interval_set.cpp @@ -684,33 +684,50 @@ namespace nlsat { return new_set; } - void interval_set_manager::peek_in_complement(interval_set const * s, bool is_int, anum & w, bool randomize) { + int compare_interval_with_zero(const interval &now, const scoped_anum &zero, anum_manager & m) { + if (!now.m_upper_inf) { + int sgn = m.compare(now.m_upper, zero); + if (sgn < 0) + return -1; + if (sgn == 0 && now.m_upper_open) + return -1; + } + if (!now.m_lower_inf) { + int sgn = m.compare(now.m_lower, zero); + if (sgn > 0) + return 1; + if (sgn == 0 && now.m_lower_open) + return 1; + } + return 0; + } + + + void interval_set_manager::pick_in_complement(interval_set const * s, bool is_int, anum & w, bool randomize, bool look_for_zero) { SASSERT(!is_full(s)); if (s == nullptr) { - if (randomize) { - int num = m_rand() % 2 == 0 ? 1 : -1; -#define MAX_RANDOM_DEN_K 4 - int den_k = (m_rand() % MAX_RANDOM_DEN_K); - int den = is_int ? 1 : (1 << den_k); - scoped_mpq _w(m_am.qm()); - m_am.qm().set(_w, num, den); - m_am.set(w, _w); - } - else { - m_am.set(w, 0); - } + m_am.set(w, 0); return; } - unsigned n = 0; - unsigned num = num_intervals(s); - if (!s->m_intervals[0].m_lower_inf) { - // lower is not -oo - n++; - m_am.int_lt(s->m_intervals[0].m_lower, w); - if (!randomize) - return; + if (look_for_zero) { + scoped_anum zero(m_am); + m_am.set(zero, 0); + bool available = true; + for (unsigned i = 0; i < num; ++i) { + int sgn = compare_interval_with_zero(s->m_intervals[i], zero, m_am); + if (sgn == 0) { + available = false; + break; + } + if (sgn > 0) + break; + } + if (available) { + m_am.set(w, 0); + return ; + } } if (!s->m_intervals[num-1].m_upper_inf) { // upper is not oo @@ -720,6 +737,16 @@ namespace nlsat { if (!randomize) return; } + + if (!s->m_intervals[0].m_lower_inf) { + // lower is not -oo + n++; + m_am.int_lt(s->m_intervals[0].m_lower, w); + if (!randomize) + return; + } + + // Try to find a gap that is not an unit. for (unsigned i = 1; i < num; i++) { @@ -770,5 +797,4 @@ namespace nlsat { out << "*"; return out; } - }; diff --git a/src/nlsat/nlsat_interval_set.h b/src/nlsat/nlsat_interval_set.h index f1055118f..33b741ebd 100644 --- a/src/nlsat/nlsat_interval_set.h +++ b/src/nlsat/nlsat_interval_set.h @@ -21,7 +21,7 @@ Revision History: #include "nlsat/nlsat_types.h" namespace nlsat { - + class interval_set; class interval_set_manager { @@ -29,6 +29,7 @@ namespace nlsat { small_object_allocator & m_allocator; svector m_already_visited; random_gen m_rand; + void del(interval_set * s); public: interval_set_manager(anum_manager & m, small_object_allocator & a); @@ -107,7 +108,7 @@ namespace nlsat { \pre !is_full(s) */ - void peek_in_complement(interval_set const * s, bool is_int, anum & w, bool randomize); + void pick_in_complement(interval_set const * s, bool is_int, anum & w, bool randomize, bool look_for_zero); }; typedef obj_ref interval_set_ref; diff --git a/src/nlsat/nlsat_params.pyg b/src/nlsat/nlsat_params.pyg index dec3fac94..7a9aa864c 100644 --- a/src/nlsat/nlsat_params.pyg +++ b/src/nlsat/nlsat_params.pyg @@ -3,6 +3,9 @@ def_module_params('nlsat', description='nonlinear solver', export=True, params=(max_memory_param(), + ('cell_sample', BOOL, True, "cell sample projection"), + ('look_for_zero_witness', BOOL, True, "look for 0 witness"), + ('lazy', UINT, 0, "how lazy the solver is."), ('reorder', BOOL, True, "reorder variables."), ('log_lemmas', BOOL, False, "display lemmas as self-contained SMT formulas"), @@ -14,7 +17,6 @@ def_module_params('nlsat', ('shuffle_vars', BOOL, False, "use a random variable order."), ('inline_vars', BOOL, False, "inline variables that can be isolated from equations (not supported in incremental mode)"), ('seed', UINT, 0, "random seed."), - ('factor', BOOL, True, "factor polynomials produced during conflict resolution."), - ('cell_sample', BOOL, True, "cell sample projection"), + ('factor', BOOL, True, "factor polynomials produced during conflict resolution.") )) diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index 3d38d7a5e..1ce6435b9 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -218,6 +218,7 @@ namespace nlsat { bool m_inline_vars; bool m_log_lemmas; bool m_check_lemmas; + bool m_look_for_0_witness; unsigned m_max_conflicts; unsigned m_lemma_count; @@ -289,6 +290,7 @@ namespace nlsat { m_inline_vars = p.inline_vars(); m_log_lemmas = p.log_lemmas(); m_check_lemmas = p.check_lemmas(); + m_look_for_0_witness = p.look_for_zero_witness(); m_ism.set_seed(m_random_seed); m_explain.set_simplify_cores(m_simplify_cores); m_explain.set_minimize_cores(min_cores); @@ -1518,7 +1520,7 @@ namespace nlsat { void select_witness() { scoped_anum w(m_am); SASSERT(!m_ism.is_full(m_infeasible[m_xk])); - m_ism.peek_in_complement(m_infeasible[m_xk], is_int(m_xk), w, m_randomize); + m_ism.pick_in_complement(m_infeasible[m_xk], is_int(m_xk), w, m_randomize, m_look_for_0_witness); TRACE("nlsat", tout << "infeasible intervals: "; m_ism.display(tout, m_infeasible[m_xk]); tout << "\n"; tout << "assigning "; m_display_var(tout, m_xk) << "(x" << m_xk << ") -> " << w << "\n";); From 839594ac12a05aa2038b34270f0cffc00460e286 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Wed, 7 Aug 2024 09:01:49 -1000 Subject: [PATCH 050/187] remove option look_for_0_witness Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_interval_set.cpp | 34 ++++++++++++++++---------------- src/nlsat/nlsat_interval_set.h | 2 +- src/nlsat/nlsat_params.pyg | 2 -- src/nlsat/nlsat_solver.cpp | 4 +--- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/nlsat/nlsat_interval_set.cpp b/src/nlsat/nlsat_interval_set.cpp index 0c15d580b..76a310f00 100644 --- a/src/nlsat/nlsat_interval_set.cpp +++ b/src/nlsat/nlsat_interval_set.cpp @@ -703,7 +703,7 @@ namespace nlsat { } - void interval_set_manager::pick_in_complement(interval_set const * s, bool is_int, anum & w, bool randomize, bool look_for_zero) { + void interval_set_manager::pick_in_complement(interval_set const * s, bool is_int, anum & w, bool randomize) { SASSERT(!is_full(s)); if (s == nullptr) { m_am.set(w, 0); @@ -711,24 +711,24 @@ namespace nlsat { } unsigned n = 0; unsigned num = num_intervals(s); - if (look_for_zero) { - scoped_anum zero(m_am); - m_am.set(zero, 0); - bool available = true; - for (unsigned i = 0; i < num; ++i) { - int sgn = compare_interval_with_zero(s->m_intervals[i], zero, m_am); - if (sgn == 0) { - available = false; - break; - } - if (sgn > 0) - break; - } - if (available) { - m_am.set(w, 0); - return ; + // try to assign w to zero first to simplify the polynomials + scoped_anum zero(m_am); + m_am.set(zero, 0); + bool available = true; + for (unsigned i = 0; i < num; ++i) { + int sgn = compare_interval_with_zero(s->m_intervals[i], zero, m_am); + if (sgn == 0) { + available = false; + break; } + if (sgn > 0) + break; } + if (available) { + m_am.set(w, 0); + return ; + } + // cannot assign w to zero if (!s->m_intervals[num-1].m_upper_inf) { // upper is not oo n++; diff --git a/src/nlsat/nlsat_interval_set.h b/src/nlsat/nlsat_interval_set.h index 33b741ebd..2e74f33c6 100644 --- a/src/nlsat/nlsat_interval_set.h +++ b/src/nlsat/nlsat_interval_set.h @@ -108,7 +108,7 @@ namespace nlsat { \pre !is_full(s) */ - void pick_in_complement(interval_set const * s, bool is_int, anum & w, bool randomize, bool look_for_zero); + void pick_in_complement(interval_set const * s, bool is_int, anum & w, bool randomize); }; typedef obj_ref interval_set_ref; diff --git a/src/nlsat/nlsat_params.pyg b/src/nlsat/nlsat_params.pyg index 7a9aa864c..62101e777 100644 --- a/src/nlsat/nlsat_params.pyg +++ b/src/nlsat/nlsat_params.pyg @@ -4,8 +4,6 @@ def_module_params('nlsat', export=True, params=(max_memory_param(), ('cell_sample', BOOL, True, "cell sample projection"), - ('look_for_zero_witness', BOOL, True, "look for 0 witness"), - ('lazy', UINT, 0, "how lazy the solver is."), ('reorder', BOOL, True, "reorder variables."), ('log_lemmas', BOOL, False, "display lemmas as self-contained SMT formulas"), diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index 1ce6435b9..9f43b7a78 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -218,7 +218,6 @@ namespace nlsat { bool m_inline_vars; bool m_log_lemmas; bool m_check_lemmas; - bool m_look_for_0_witness; unsigned m_max_conflicts; unsigned m_lemma_count; @@ -290,7 +289,6 @@ namespace nlsat { m_inline_vars = p.inline_vars(); m_log_lemmas = p.log_lemmas(); m_check_lemmas = p.check_lemmas(); - m_look_for_0_witness = p.look_for_zero_witness(); m_ism.set_seed(m_random_seed); m_explain.set_simplify_cores(m_simplify_cores); m_explain.set_minimize_cores(min_cores); @@ -1520,7 +1518,7 @@ namespace nlsat { void select_witness() { scoped_anum w(m_am); SASSERT(!m_ism.is_full(m_infeasible[m_xk])); - m_ism.pick_in_complement(m_infeasible[m_xk], is_int(m_xk), w, m_randomize, m_look_for_0_witness); + m_ism.pick_in_complement(m_infeasible[m_xk], is_int(m_xk), w, m_randomize); TRACE("nlsat", tout << "infeasible intervals: "; m_ism.display(tout, m_infeasible[m_xk]); tout << "\n"; tout << "assigning "; m_display_var(tout, m_xk) << "(x" << m_xk << ") -> " << w << "\n";); From 209366ba5584109a65554797b731a36a73c281c5 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Wed, 7 Aug 2024 09:22:08 -1000 Subject: [PATCH 051/187] cleanup porting comments Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_explain.cpp | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp index 6efbf4e7f..49842100d 100644 --- a/src/nlsat/nlsat_explain.cpp +++ b/src/nlsat/nlsat_explain.cpp @@ -733,7 +733,6 @@ namespace nlsat { bool have_zero = false; for (unsigned i = 0; i < num_factors; i++) { f = m_factors.get(i); - // std::cout << "f=";display(std::cout, f) << "\n"; if (coeffs_are_zeroes_in_factor(f)) { have_zero = true; break; @@ -1043,7 +1042,6 @@ namespace nlsat { // Otherwise, the isolate_roots procedure will assume p is a constant polynomial. m_am.isolate_roots(p, undef_var_assignment(m_assignment, y), roots); unsigned num_roots = roots.size(); -//#linxi begin add_cell_lits faster bool all_lt = true; for (unsigned i = 0; i < num_roots; i++) { int s = m_am.compare(y_val, roots[i]); @@ -1092,7 +1090,6 @@ namespace nlsat { i_lower = j + 1; } } -//#linxi end add_cell_lits faster } if (!lower_inf) { @@ -1148,7 +1145,6 @@ namespace nlsat { // Otherwise, the isolate_roots procedure will assume p is a constant polynomial. m_am.isolate_roots(p, undef_var_assignment(m_assignment, y), roots); unsigned num_roots = roots.size(); -//#linxi begin add_cell_lits faster bool all_lt = true; for (unsigned i = 0; i < num_roots; i++) { int s = m_am.compare(y_val, roots[i]); @@ -1196,7 +1192,6 @@ namespace nlsat { i_lower = j + 1; } } -//#linxi end add_cell_lits faster } if (!lower_inf) { @@ -1254,12 +1249,18 @@ namespace nlsat { add_cell_lits(ps, x); } } - void project_cdcac(polynomial_ref_vector & ps, var max_x) { - bool first = true; - + /** + * Sample Projection + * Reference: + * Haokun Li and Bican Xia. + * "Solving Satisfiability of Polynomial Formulas By Sample - Cell Projection" + * https://arxiv.org/abs/2003.00409 + */ + void project_cdcac(polynomial_ref_vector & ps, var max_x) { if (ps.empty()) return; + bool first = true; m_todo.reset(); for (poly* p : ps) { m_todo.insert(p); @@ -1282,22 +1283,12 @@ namespace nlsat { TRACE("nlsat_explain", tout << "project loop, processing var "; display_var(tout, x); tout << "\npolynomials\n"; display(tout, ps); tout << "\n";); - - /** - * Sample Projection - * Reference: - * Haokun Li and Bican Xia. - * "Solving Satisfiability of Polynomial Formulas By Sample - Cell Projection" - * https://arxiv.org/abs/2003.00409 - */ - if (first) { add_lc(ps, x); psc_discriminant(ps, x); psc_resultant(ps, x); first = false; } - else { add_lc(ps, x); // add_sample_coeff(ps, x); From 1a5bddb4f0f9d69934c87fe6d6069683f3d38d04 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 8 Aug 2024 12:14:33 -1000 Subject: [PATCH 052/187] port more from hybridSMT Signed-off-by: Lev Nachmanson --- src/nlsat/CMakeLists.txt | 5 +- src/nlsat/nlsat_params.pyg | 3 + src/nlsat/nlsat_simple_checker.cpp | 2062 +++++++++ src/nlsat/nlsat_simple_checker.h | 15 + src/nlsat/nlsat_solver.cpp | 4027 ----------------- src/nlsat/nlsat_symmetry_checker.cpp | 356 ++ src/nlsat/nlsat_symmetry_checker.h | 13 + .../nlsat_variable_ordering_strategy.cpp | 282 ++ src/nlsat/nlsat_variable_ordering_strategy.h | 27 + src/tactic/smtlogics/qfnra_tactic.cpp | 315 +- 10 files changed, 3061 insertions(+), 4044 deletions(-) create mode 100644 src/nlsat/nlsat_simple_checker.cpp create mode 100644 src/nlsat/nlsat_simple_checker.h delete mode 100644 src/nlsat/nlsat_solver.cpp create mode 100644 src/nlsat/nlsat_symmetry_checker.cpp create mode 100644 src/nlsat/nlsat_symmetry_checker.h create mode 100644 src/nlsat/nlsat_variable_ordering_strategy.cpp create mode 100644 src/nlsat/nlsat_variable_ordering_strategy.h diff --git a/src/nlsat/CMakeLists.txt b/src/nlsat/CMakeLists.txt index cd073f0d5..7aa1d83c5 100644 --- a/src/nlsat/CMakeLists.txt +++ b/src/nlsat/CMakeLists.txt @@ -7,7 +7,10 @@ z3_add_component(nlsat nlsat_simplify.cpp nlsat_solver.cpp nlsat_types.cpp - COMPONENT_DEPENDENCIES + nlsat_simple_checker.cpp + nlsat_variable_ordering_strategy.cpp + nlsat_symmetry_checker.cpp + COMPONENT_DEPENDENCIES polynomial sat PYG_FILES diff --git a/src/nlsat/nlsat_params.pyg b/src/nlsat/nlsat_params.pyg index 62101e777..73067d48b 100644 --- a/src/nlsat/nlsat_params.pyg +++ b/src/nlsat/nlsat_params.pyg @@ -3,7 +3,10 @@ def_module_params('nlsat', description='nonlinear solver', export=True, params=(max_memory_param(), + ('linxi_simple_check', BOOL, False, "linxi precheck about variables sign"), + ('linxi_variable_ordering_strategy', UINT, 0, "linxi Variable Ordering Strategy, 0 for none, 1 for BROWN, 2 for TRIANGULAR, 3 for ONLYPOLY"), ('cell_sample', BOOL, True, "cell sample projection"), + ('linxi_symmetry_check', BOOL, False, "linxi symmetry check and learning"), ('lazy', UINT, 0, "how lazy the solver is."), ('reorder', BOOL, True, "reorder variables."), ('log_lemmas', BOOL, False, "display lemmas as self-contained SMT formulas"), diff --git a/src/nlsat/nlsat_simple_checker.cpp b/src/nlsat/nlsat_simple_checker.cpp new file mode 100644 index 000000000..047b67e0e --- /dev/null +++ b/src/nlsat/nlsat_simple_checker.cpp @@ -0,0 +1,2062 @@ +#include "nlsat/nlsat_simple_checker.h" + +struct Debug_Tracer { + std::string tag_str; + Debug_Tracer(std::string _tag_str) { + tag_str = _tag_str; + TRACE("linxi_simple_checker", + tout << "Debug_Tracer begin\n"; + tout << tag_str << "\n"; + ); + } + ~Debug_Tracer() { + TRACE("linxi_simple_checker", + tout << "Debug_Tracer end\n"; + tout << tag_str << "\n"; + ); + } +}; + +// #define _LINXI_DEBUG + +#ifdef _LINXI_DEBUG +// #define LINXI_DEBUG std::stringstream DEBUG_ss; DEBUG_ss << __FUNCTION__ << " " << __FILE__ << ":" << __LINE__; Debug_Tracer DEBUG_dt(DEBUG_ss.str()); +// #define LINXI_HERE TRACE("linxi_simple_checker", tout << "here\n";); +#define LINXI_DEBUG { }((void) 0 ); +#define LINXI_HERE { }((void) 0 ); + +#else +#define LINXI_DEBUG { }((void) 0 ); +#define LINXI_HERE { }((void) 0 ); +#endif + + + +namespace nlsat { + struct Simple_Checker::imp { + // solver / + pmanager ± + anum_manager &am; + const clause_vector &clauses; + literal_vector &learned_unit; + const atom_vector &atoms; + const unsigned arith_var_num; + // unsigned all_var_num; + enum sign_kind { EQ = 0, LT, GT, NONE, LE, GE, NEQ}; + void display(std::ostream & out, const sign_kind &sk) { + if (sk == EQ) + out << "=="; + else if (sk == LT) + out << "<"; + else if (sk == GT) + out << ">"; + else if (sk == NONE) + out << "<=>"; + else if (sk == LE) + out << "<="; + else if (sk == GE) + out << ">="; + else if (sk == NEQ) + out << "!="; + else + UNREACHABLE(); + } + struct Endpoint { + anum_manager &m_am; + unsigned m_open:1; + unsigned m_inf:1; + unsigned m_is_lower:1; + scoped_anum m_val; + Endpoint(anum_manager &_am) : + m_am(_am), + m_open(1), + m_inf(1), + m_is_lower(1), + m_val(_am) { + } + Endpoint(anum_manager &_am, unsigned _open, unsigned _inf, unsigned _islower) : + m_am(_am), + m_open(_open), + m_inf(_inf), + m_is_lower(_islower), + m_val(_am) { + } + Endpoint(anum_manager &_am, unsigned _open, unsigned _inf, unsigned _islower, const scoped_anum &_val) : + m_am(_am), + m_open(_open), + m_inf(_inf), + m_is_lower(_islower), + m_val(_am) { + m_am.set(m_val, _val); + } + bool operator== (const Endpoint &rhs) const { + if (m_inf && rhs.m_inf && m_is_lower == rhs.m_is_lower) + return true; + if (!m_inf && !rhs.m_inf && m_open == rhs.m_open && m_val == rhs.m_val) { + if (!m_open) + return true; + if (m_is_lower == rhs.m_is_lower) + return true; + } + return false; + } + bool operator< (const Endpoint &rhs) const { + if (m_inf) { + if (m_is_lower) { + if (rhs.m_inf && rhs.m_is_lower) + return false; + else + return true; + } + else { + return false; + } + } + else { + if (rhs.m_inf) { + if (rhs.m_is_lower) + return false; + else + return true; + } + else { + if (m_val == rhs.m_val) { + if (!m_open && !rhs.m_open) { // {[, [} + // {[, [} {[, ]} {], [} {], ]} + return false; + } + else if (!m_open) { // {[, (} + // [ < (, [ > ), ] < (, ] > ) + if (rhs.m_is_lower) + return true; + else + return false; + } + else if (!rhs.m_open) { // {(, [} + if (m_is_lower) // x + EPS + return false; + else // x - EPS + return true; + } + else { // {(, (} + // ( == (, ( > ), ) < (, ) == ) + if (!m_is_lower && rhs.m_is_lower) + return true; + else + return false; + } + } + else { + return m_val < rhs.m_val; + } + } + } + } + void copy(const Endpoint &ep) { + m_inf = ep.m_inf; + m_open = ep.m_open; + m_is_lower = ep.m_is_lower; + if (!m_inf) + m_am.set(m_val, ep.m_val); + } + void set_num(const scoped_anum &num, unsigned is_lower) { + m_open = 0; + m_inf = 0; + m_is_lower = is_lower; + m_am.set(m_val, num); + } + void set_num(int num, unsigned is_lower) { + m_open = 0; + m_inf = 0; + m_is_lower = is_lower; + m_am.set(m_val, num); + } + bool is_neg() const { + if (m_inf) { + if (m_is_lower) + return true; + else + return false; + } + else { + if (m_am.is_zero(m_val)) { + if (m_open) { + if (m_is_lower) + return false; + else + return true; + } + else { + return false; + } + } + else { + return m_am.is_neg(m_val); + } + } + } + bool is_zero(unsigned is_open = 0) const { + return !m_inf && m_open == is_open && m_am.is_zero(m_val); + } + }; + struct Domain_Interval { + anum_manager &m_am; + Endpoint m_lower; + Endpoint m_upper; + Domain_Interval(anum_manager &_am) : + m_am(_am), + m_lower(_am, 1, 1, 1), + m_upper(_am, 1, 1, 0) { + // (-oo, +oo) + } + Domain_Interval(anum_manager &_am, + unsigned _lower_open, unsigned _lower_inf, + unsigned _upper_open, unsigned _upper_inf) : + m_am(_am), + m_lower(_am, _lower_open, _lower_inf, 1), + m_upper(_am, _upper_open, _upper_inf, 0) { + } + void copy(const Domain_Interval &di) { + m_lower.copy(di.m_lower); + m_upper.copy(di.m_upper); + } + void set_num(const scoped_anum &num) { + m_lower.set_num(num, 1); + m_upper.set_num(num, 0); + } + void set_num(int num) { + m_lower.set_num(num, 1); + m_upper.set_num(num, 0); + } + }; + + void display(std::ostream & out, anum_manager & am, Domain_Interval const & curr) { + if (curr.m_lower.m_inf) { + out << "(-oo, "; + } + else { + if (curr.m_lower.m_open) + out << "("; + else + out << "["; + am.display_decimal(out, curr.m_lower.m_val); + out << ", "; + } + if (curr.m_upper.m_inf) { + out << "oo)"; + } + else { + am.display_decimal(out, curr.m_upper.m_val); + if (curr.m_upper.m_open) + out << ")"; + else + out << "]"; + } + } + + struct Var_Domain { + Domain_Interval ori_val; // original, ext sign + Domain_Interval mag_val; // magnitude + Var_Domain(anum_manager &am) : + ori_val(am), + mag_val(am) { + mag_val.m_lower.set_num(0, 1); + } + void copy(const Var_Domain &vd) { + ori_val.copy(vd.ori_val); + mag_val.copy(vd.mag_val); + } + }; + vector vars_domain; + struct Clause_Visit_Tag { + bool visited; + bool_vector literal_visited; + Clause_Visit_Tag() : visited(false) {} + }; + vector clauses_visited; + bool improved; + enum special_ineq_kind {UNK = 0, AXBC, AXBSC, NK}; // None Kind + vector> literal_special_kind; + // imp(solver &_sol, pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, clause_vector &_learned, const atom_vector &_atoms, const unsigned &_arith_var_num) : + imp(pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, literal_vector &_learned_unit, const atom_vector &_atoms, const unsigned &_arith_var_num) : + // sol(_sol), + pm(_pm), + am(_am), + clauses(_clauses), + learned_unit(_learned_unit), + atoms(_atoms), + arith_var_num(_arith_var_num) { + // all_var_num = atoms.size(); + for (unsigned i = 0; i < arith_var_num; ++i) { + vars_domain.push_back(Var_Domain(am)); + } + clauses_visited.resize(clauses.size()); + literal_special_kind.resize(clauses.size()); + } + sign_kind to_sign_kind(atom::kind kd) { + if (kd == atom::EQ) + return EQ; + if (kd == atom::LT) + return LT; + if (kd == atom::GT) + return GT; + UNREACHABLE(); + } + bool update_interval_intersection(Domain_Interval &ia, const Domain_Interval &ib) { + TRACE("linxi_simple_checker", + tout << "ia: "; + display(tout, am, ia); + tout << "\nib: "; + display(tout, am, ib); + tout << "\n"; + tout << "ia.lower < ib.lower: " << (ia.m_lower < ib.m_lower) << '\n'; + tout << "ia.m_upper < ib.m_upper: " << (ia.m_upper < ib.m_upper) << '\n'; + ); + if (ia.m_lower < ib.m_lower) { + ia.m_lower.copy(ib.m_lower); + improved = true; + } + + if (ib.m_upper < ia.m_upper) { + ia.m_upper.copy(ib.m_upper); + improved = true; + } + if (ia.m_upper < ia.m_lower) + return false; + + + // if (ia.m_lower_inf == 0 && ib.m_upper_inf == 0) { + // if (ia.m_lower > ib.m_upper) + // return false; + // if (ia.m_lower == ib.m_upper && (ia.m_lower_open || ib.m_upper_open)) + // return false; + // } + // if (ib.m_lower_inf == 0 && ia.m_upper_inf == 0) { + // if (ib.m_lower > ia.m_upper) + // return false; + // if (ib.m_lower == ia.m_upper && (ib.m_lower_open || ia.m_upper_open)) + // return false; + // } + // if (ia.m_lower_inf && ib.m_lower_inf) { + // // do nothing + // } + // else { + // if (ia.m_lower_inf) { + // ia.m_lower_inf = 0; + // ia.m_lower_open = ib.m_lower_open; + // am.set(ia.m_lower, ib.m_lower); + // } + // else if (ib.m_lower_inf) { + // // do nothing + // } + // else { + // if (ia.m_lower == ib.m_lower) { + // ia.m_lower_open = (ia.m_lower_open | ib.m_lower_open); + // } + // else if (ia.m_lower < ib.m_lower) { + // ia.m_lower_open = ib.m_lower_open; + // am.set(ia.m_lower, ib.m_lower); + // } + // else { + // // do nothing + // } + // } + // } + + // if (ia.m_upper_inf && ib.m_upper_inf) { + // // do nothing + // } + // else { + // if (ia.m_upper_inf) { + // ia.m_upper_inf = 0; + // ia.m_upper_open = ib.m_upper_open; + // am.set(ia.m_upper, ib.m_upper); + // } + // else if (ib.m_upper_inf) { + // // do nothing + // } + // else { + // if (ia.m_upper == ib.m_upper) { + // ia.m_upper_open = (ia.m_upper_open | ib.m_upper_open); + // } + // else if (ia.m_upper < ib.m_upper) { + // // do nothing + // } + // else { + // ia.m_upper_open = ib.m_upper_open; + // am.set(ia.m_upper, ib.m_upper); + // } + // } + // } + TRACE("linxi_simple_checker", + tout << "after update: "; + display(tout, am, ia); + tout << "\n"; + ); + return true; + } + + bool update_var_ori_domain_interval(Var_Domain &vd, const Domain_Interval &di) { + return update_interval_intersection(vd.ori_val, di); + } + bool update_var_mag_domain_interval_by_ori(Var_Domain &vd, const Domain_Interval &di) { + TRACE("linxi_simple_checker", + tout << "vd mag val: "; + display(tout, am, vd.mag_val); + tout << "\n"; + tout << "di: "; + display(tout, am, di); + tout << "\n"; + ); + Domain_Interval mag_di(am, 0, 0, 1, 1); + // am.set(mag_di.m_lower.m_val, 0); + + if (di.m_lower.m_inf) { + mag_di.m_upper.m_inf = 1; + mag_di.m_upper.m_open = 1; + if (am.is_neg(di.m_upper.m_val)) { + // am.neg(di.m_upper); + am.set(mag_di.m_lower.m_val, di.m_upper.m_val*-1); + mag_di.m_lower.m_open = di.m_upper.m_open; + } + else if (am.is_zero(di.m_upper.m_val)) { + mag_di.m_lower.m_open = di.m_upper.m_open; + } + else { + return true; + } + } + else if (di.m_upper.m_inf) { + mag_di.m_upper.m_inf = 1; + mag_di.m_upper.m_open = 1; + if (am.is_neg(di.m_lower.m_val)) { + return true; + } + else if (am.is_zero(di.m_lower.m_val)) { + mag_di.m_lower.m_open = di.m_lower.m_open; + } + else { + am.set(mag_di.m_lower.m_val, di.m_lower.m_val); + mag_di.m_lower.m_open = di.m_lower.m_open; + } + } + else { + mag_di.m_lower.m_inf = 0; + mag_di.m_upper.m_inf = 0; + if (!am.is_neg(di.m_lower.m_val)) { + mag_di.m_lower.m_open = di.m_lower.m_open; + mag_di.m_upper.m_open = di.m_upper.m_open; + am.set(mag_di.m_lower.m_val, di.m_lower.m_val); + am.set(mag_di.m_upper.m_val, di.m_upper.m_val); + } + else if (!am.is_pos(di.m_upper.m_val)) { + mag_di.m_lower.m_open = di.m_upper.m_open; + mag_di.m_upper.m_open = di.m_lower.m_open; + + am.set(mag_di.m_lower.m_val, di.m_upper.m_val*-1); + am.set(mag_di.m_upper.m_val, di.m_lower.m_val*-1); + } + else { + scoped_anum nl(am); + am.set(nl, di.m_lower.m_val); + am.neg(nl); + am.set(mag_di.m_lower.m_val, 0); + mag_di.m_lower.m_open = 0; + if (nl < di.m_upper.m_val) { + mag_di.m_upper.m_open = di.m_upper.m_open; + am.set(mag_di.m_upper.m_val, di.m_upper.m_val); + } + else if (nl == di.m_upper.m_val) { + mag_di.m_upper.m_open = (di.m_lower.m_open | di.m_upper.m_open); + am.set(mag_di.m_upper.m_val, di.m_upper.m_val); + } + else { + mag_di.m_upper.m_open = di.m_lower.m_open; + am.set(mag_di.m_upper.m_val, nl); + } + } + } + TRACE("linxi_simple_checker", + tout << "mag di: "; + display(tout, am, mag_di); + tout << "\n"; + ); + return update_interval_intersection(vd.mag_val, mag_di); + } + void calc_formula(scoped_anum &num, const scoped_anum &a, unsigned b, const scoped_anum &c) { + LINXI_DEBUG; + scoped_anum frac(am); + am.div(c, a, frac); + am.neg(frac); + if (b > 1) + am.root(frac, b, num); + else + am.set(num, frac); + } + bool process_odd_degree_formula(Var_Domain &vd, sign_kind nsk, const scoped_anum &a, unsigned b, const scoped_anum &c) { + LINXI_DEBUG; + Domain_Interval now_di(am); + scoped_anum num(am); + calc_formula(num, a, b, c); + TRACE("linxi_simple_checker", + tout << "nsk: "; + display(tout, nsk); + tout << '\n'; + tout << "num: " << num << '\n'; + ); + if (nsk == EQ) { + now_di.set_num(num); + // am.set(now_di.m_lower.m_val, num); + // am.set(now_di.m_upper.m_val, num); + // now_di.m_lower.m_inf = 0; + // now_di.m_upper.m_inf = 0; + // now_di.m_lower.m_open = 0; + // now_di.m_upper.m_open = 0; + } + else if (nsk == LT) { + am.set(now_di.m_upper.m_val, num); + now_di.m_upper.m_inf = 0; + now_di.m_upper.m_open = 1; + } + else if (nsk == GT) { + am.set(now_di.m_lower.m_val, num); + now_di.m_lower.m_inf = 0; + now_di.m_lower.m_open = 1; + } + else if (nsk == LE) { + am.set(now_di.m_upper.m_val, num); + now_di.m_upper.m_inf = 0; + now_di.m_upper.m_open = 0; + } + else if (nsk == GE) { + am.set(now_di.m_lower.m_val, num); + now_di.m_lower.m_inf = 0; + now_di.m_lower.m_open = 0; + } + else { + UNREACHABLE(); + } + TRACE("linxi_simple_checker", + tout << "now_di: "; + display(tout, am, now_di); + tout << "\n"; + ); + if (!update_var_ori_domain_interval(vd, now_di)) + return false; + if (!update_var_mag_domain_interval_by_ori(vd, vd.ori_val)) + return false; + return true; + } +/* + +if (nsk == EQ) { +return false; +} +else if (nsk == LT) { +return false; +} +else if (nsk == GT) { +return true; +} +else if (nsk == LE) { +return false; +} +else if (nsk == GE) { +return true; +} +else { +UNREACHABLE(); +} +*/ + bool process_even_degree_formula(Var_Domain &vd, sign_kind nsk, const scoped_anum &a, unsigned b, const scoped_anum &c) { + LINXI_DEBUG; + scoped_anum num(am), frac(am); + am.div(c, a, frac); + am.neg(frac); + + if (frac < 0) { + if (nsk == EQ || nsk == LT || nsk == LE) { + return false; + } + else if (nsk == GT || nsk == GE) { + return true; + } + else { + UNREACHABLE(); + } + } + else if (frac == 0) { + if (nsk == EQ || nsk == LE) { + Domain_Interval di(am); + di.set_num(0); + if (!update_interval_intersection(vd.ori_val, di)) + return false; + if (!update_interval_intersection(vd.mag_val, di)) + return false; + } + else if (nsk == LT) { + return false; + } + else if (nsk == GT) { + Domain_Interval di(am); + di.m_lower.set_num(0, 1); + if (!update_interval_intersection(vd.mag_val, di)) + return false; + } + else if (nsk == GE) { + return true; + } + else { + UNREACHABLE(); + } + } + else { + scoped_anum num(am); + am.root(frac, b, num); + if (nsk == EQ) { + Domain_Interval di(am); + di.set_num(num); + // di.m_lower_open = 0; + // di.m_upper_open = 0; + // di.m_lower_inf = 0; + // di.m_upper_inf = 0; + // am.set(di.m_lower, num); + // am.set(di.m_upper, num); + // if (!update_interval_intersection(vd.ori_val, di)) + // return false; + if (!update_interval_intersection(vd.mag_val, di)) + return false; + } + else if (nsk == LT) { + Domain_Interval di(am, 0, 0, 1, 0); + // [0, num) + am.set(di.m_lower.m_val, 0); + am.set(di.m_upper.m_val, num); + if (!update_interval_intersection(vd.mag_val, di)) + return false; + + // (-num, num) + di.m_lower.m_open = 1; + // am.set(di.m_upper, num); + am.neg(num); + am.set(di.m_lower.m_val, num); + if (!update_interval_intersection(vd.ori_val, di)) + return false; + } + else if (nsk == GT) { + // (num, inf) + Domain_Interval di(am, 1, 0, 1, 1); + // di.m_lower_open = 1; + // di.m_upper_open = 1; + // di.m_lower_inf = 0; + // di.m_upper_inf = 1; + am.set(di.m_lower.m_val, num); + if (!update_interval_intersection(vd.mag_val, di)) + return false; + } + else if (nsk == LE) { + Domain_Interval di(am, 0, 0, 0, 0); + // [0, num] + // di.m_lower_open = 0; + // di.m_upper_open = 0; + // di.m_lower_inf = 0; + // di.m_upper_inf = 0; + am.set(di.m_lower.m_val, 0); + am.set(di.m_upper.m_val, num); + if (!update_interval_intersection(vd.mag_val, di)) + return false; + // [-num, num] + // am.set(di.m_upper, num); + am.neg(num); + am.set(di.m_lower.m_val, num); + if (!update_interval_intersection(vd.ori_val, di)) + return false; + } + else if (nsk == GE) { + // [num, inf) + Domain_Interval di(am, 0, 0, 1, 1); + // di.m_lower_open = 0; + // di.m_upper_open = 1; + // di.m_lower_inf = 0; + // di.m_upper_inf = 1; + am.set(di.m_lower.m_val, num); + if (!update_interval_intersection(vd.mag_val, di)) + return false; + } + else { + UNREACHABLE(); + } + } + return true; + } + + bool update_var_domain(sign_kind nsk, const scoped_anum &a, var x, unsigned b, const scoped_anum &c) { + LINXI_DEBUG; + Var_Domain &vd = vars_domain[x]; + if (am.is_neg(a)) { + if (nsk == LT) + nsk = GT; + else if (nsk == GT) + nsk = LT; + else if (nsk == LE) + nsk = GE; + else if (nsk == GE) + nsk = LE; + } + if (nsk == NEQ) { + if (am.is_zero(c)) { + Domain_Interval di(am, 1, 0, 1, 1); + am.set(di.m_lower.m_val, 0); + return update_interval_intersection(vd.mag_val, di); + } + else { + return true; + } + } + if ((b & 1) == 1) + return process_odd_degree_formula(vd, nsk, a, b, c); + else + return process_even_degree_formula(vd, nsk, a, b, c); + } + + bool check_is_axbc(const poly *p, scoped_anum &a, var &x, unsigned &b, scoped_anum& c) { + // is a*(x^b) + c*1 form + // LINXI_DEBUG; + // LINXI_HERE; + // TRACE("linxi_simple_checker", + // tout << a << "x[" << x << "]^" << b << " "; + // tout << "+ " << c << " "; + // // display(tout, nsk); + // // tout << " 0\n"; + // ); + if (pm.size(p) == 1 && pm.is_var(pm.get_monomial(p, 0), x)) { + LINXI_HERE; + am.set(a, 1); + b = 1; + am.set(c, 0); + return true; + } + // LINXI_HERE; + if (pm.size(p) != 2) + return false; + if (!pm.is_unit(pm.get_monomial(p, 1))) + return false; + monomial *m = pm.get_monomial(p, 0); + if (pm.size(m) != 1) + return false; + x = pm.get_var(m, 0); + b = pm.degree(m, 0); + // LINXI_HERE; + am.set(a, pm.coeff(p, 0)); + am.set(c, pm.coeff(p, 1)); + return true; + } + + bool collect_domain_axbc_form(unsigned cid, unsigned lid) { + // is_var_num, a*(x^b) + c form + LINXI_DEBUG; + literal lit = (*clauses[cid])[lid]; + bool s = lit.sign(); + ineq_atom *ia = to_ineq_atom(atoms[lit.var()]); + if (ia->size() > 1) { + // clauses_visited[cid].visited = true; + return true; + } + poly *p = ia->p(0); + if (literal_special_kind[cid][lid] != UNK && + literal_special_kind[cid][lid] != AXBC) + return true; + var x; + scoped_anum a(am), c(am); + unsigned b; + + if (!check_is_axbc(p, a, x, b, c)) { + // vec_id.push_back(cid); + return true; + } + clauses_visited[cid].visited = true; + literal_special_kind[cid][lid] = AXBC; + sign_kind nsk = to_sign_kind(ia->get_kind()); + if (s) { + if (nsk == EQ) + nsk = NEQ; + else if (nsk == LT) + nsk = GE; + else if (nsk == GT) + nsk = LE; + } + TRACE("linxi_simple_checker", + tout << a << "x[" << x << "]^" << b << " + " << c << " "; + display(tout, nsk); + tout << " 0 \n"; + ); + if (!update_var_domain(nsk, a, x, b, c)) + return false; + TRACE("linxi_simple_checker", + tout << "original: "; + display(tout, am, vars_domain[x].ori_val); + tout << "\nmagnitude: "; + display(tout, am, vars_domain[x].mag_val); + tout << "\n"; + ); + return true; + } + bool check_is_axbsc(const poly *p, vector &as, vector &xs, vector &bs, scoped_anum& c, unsigned &cnt) { + // [a*(x^b)] + ... + [a*(x^b)] + c form + LINXI_DEBUG; + unsigned psz = pm.size(p); + am.set(c, 0); + for (unsigned i = 0; i < psz; ++i) { + monomial *m = pm.get_monomial(p, i); + if (pm.size(m) > 1) + return false; + } + LINXI_HERE; + cnt = 0; + for (unsigned i = 0; i < psz; ++i) { + monomial *m = pm.get_monomial(p, i); + // TRACE("linxi_simple_checker", + // tout << "monomial: "; + // pm.display(tout, m); + // tout << '\n'; + // // tout << "coefficient: " << pm.coeff(p, i) << "\n"; + // tout << "m size: " << pm.size(m) << '\n'; + // tout << "# "; + // for (unsigned j = 0, sz = pm.size(m); j < sz; ++j) { + // var v = pm.get_var(m, j); + // tout << " (" << j << ", " << pm.degree_of(m, v) << ")"; + // } + // tout << "\n"; + // ); + if (pm.size(m) == 0) { + am.set(c, pm.coeff(p, i)); + } + else { + // as.push_back(scoped_anum(am)); + am.set(as[cnt++], pm.coeff(p, i)); + xs.push_back(pm.get_var(m, 0)); + bs.push_back(pm.degree(m, 0)); + // TRACE("linxi_simple_checker", + // tout << as.back() << "x[" << xs.back() << "]^" << bs.back() << "\n"; + // ); + } + } + return true; + } + + sign_kind get_axb_sign(const scoped_anum &a, var x, unsigned b) { + Var_Domain &vd = vars_domain[x]; + if (vd.ori_val.m_lower.is_zero() && + vd.ori_val.m_upper.is_zero()) + return EQ; + if ((b & 1) == 0) { + if (am.is_pos(a)) { // a > 0 + if (vd.mag_val.m_lower.is_zero(0)) + return GE; + else + return GT; + } + else { + if (vd.mag_val.m_lower.is_zero(0)) + return LE; + else + return LT; + } + } else { + sign_kind ret = NONE; + if (!vd.ori_val.m_lower.m_inf && !vd.ori_val.m_upper.m_inf) { + if (am.is_zero(vd.ori_val.m_lower.m_val)) { + if (vd.ori_val.m_lower.m_open) + ret = GT; + else + ret = GE; + } + else if (am.is_pos(vd.ori_val.m_lower.m_val)) { + ret = GT; + } + // else { + // ret = NONE; + // } + if (am.is_zero(vd.ori_val.m_upper.m_val)) { + if (vd.ori_val.m_upper.m_open) + ret = LT; + else + ret = LE; + } + else if (am.is_neg(vd.ori_val.m_upper.m_val)) { + ret = LT; + } + // else { + // ret = NONE; + // } + } + else if (!vd.ori_val.m_lower.m_inf) { + if (am.is_pos(vd.ori_val.m_lower.m_val)) { + ret = GT; + } + else if (am.is_zero(vd.ori_val.m_lower.m_val)) { + if (vd.ori_val.m_lower.m_open) + ret = GT; + else + ret = GE; + } + } + else if (!vd.ori_val.m_upper.m_inf) { + if (am.is_neg(vd.ori_val.m_upper.m_val)) { + ret = LT; + } + else if (am.is_zero(vd.ori_val.m_upper.m_val)) { + if (vd.ori_val.m_upper.m_open) + ret = LT; + else + ret = LE; + } + } + if (a < 0) { + if (ret == LT) + ret = GT; + else if (ret == LE) + ret = GE; + else if (ret == GT) + ret = LT; + else if (ret == GE) + ret = LE; + } + return ret; + } + } + + bool check_is_sign_ineq_consistent(sign_kind &nsk, vector &as, vector &xs, vector &bs, scoped_anum& c, bool &is_conflict) { + sign_kind sta = get_axb_sign(as[0], xs[0], bs[0]); + if (sta == NONE) + return false; + unsigned sz = as.size(); + for (unsigned i = 1; i < sz; ++i) { + sign_kind now = get_axb_sign(as[i], xs[i], bs[i]); + TRACE("linxi_simple_checker", + tout << "sta: "; + display(tout, sta); + tout << "\n"; + tout << "now: "; + display(tout, now); + tout << "\n"; + ); + if (now == NONE) + return false; + if (sta == EQ) { + sta = now; + } + else if (sta == LT || sta == LE) { + if (now != LT && now != LE) + return false; + if (sta != now) + sta = LT; + } + else { + if (now != GT && now != GE) + return false; + if (sta != now) + sta = GT; + } + TRACE("linxi_simple_checker", + tout << "after merge\n"; + tout << "sta: "; + display(tout, sta); + tout << "\n"; + ); + } + // if (am.is_zero(c)) { + // // sta = sta; + // } + // else if (am.is_neg(c)) { + // if (sta == EQ) + // sta = LT; + // // else if (sta == LT) + // // sta = LT; + // else if (sta == LE) + // sta = LT; + // else if (sta == GT) + // sta = NONE; + // else if (sta == GE) + // sta = NONE; + // } + // else { // a > 0 + // if (sta == EQ) + // sta = GT; + // else if (sta == LT) + // sta = NONE; + // else if (sta == LE) + // sta = NONE; + // // else if (sta == GT) + // // sta = GT; + // else if (sta == GE) + // sta = GT; + // } + // if (sta == NONE) + // return false; + TRACE("linxi_simple_checker", + tout << "sta: "; + display(tout, sta); + tout << "\n"; + tout << "nsk: "; + display(tout, nsk); + tout << "\n"; + tout << "c: "; + am.display(tout, c); + tout << "\n"; + ); +/* +if (am.is_neg(c)) { // ( == 0) + (c < 0) -> < 0 + +} +else if (am.is_zero(c)) { // ( == 0) + (c == 0) -> == 0 + +} +else { // ( == 0) + (c > 0) -> > 0 + +} + +*/ + if (sta == EQ) { + if (am.is_neg(c)) { // ( == 0) + (c < 0) -> < 0 + if (nsk == EQ || nsk == GE || nsk == GT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + else if (am.is_zero(c)) { // ( == 0) + (c == 0) -> == 0 + if (nsk == GT || nsk == LT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + else { // ( == 0) + (c > 0) -> > 0 + if (nsk == EQ || nsk == LE || nsk == LT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + } + else if (sta == LT) { + if (am.is_neg(c)) { // ( < 0) + (c < 0) -> < 0 + if (nsk == EQ || nsk == GE || nsk == GT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + else if (am.is_zero(c)) { // ( < 0) + (c == 0) -> < 0 + if (nsk == EQ || nsk == GE || nsk == GT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + else { // [(t0 <= 0 + .. + tn <= 0) + (c > 0) >/>= 0] -> t > -c + if (nsk == LE || nsk == LT) + return false; + if (sz > 1 && nsk == EQ) + nsk = GE; + return true; + } + } + else if (sta == LE) { + if (am.is_neg(c)) { // ( <= 0) + (c < 0) -> < 0 + if (nsk == EQ || nsk == GE || nsk == GT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + else if (am.is_zero(c)) { // ( <= 0) + (c == 0) -> <= 0 + if (nsk == GT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + else { // [(t0 <= 0 + .. + tn <= 0) + (c > 0) >/>= 0] -> t > -c + if (nsk == LE || nsk == LT) + return false; + if (sz > 1 && nsk == EQ) + nsk = GE; + return true; + } + } + else if (sta == GT) { + if (am.is_neg(c)) { // [(t0 > 0 + .. + tn > 0) + (c < 0) t < -c + if (nsk == GE || nsk == GT) + return false; + if (sz > 1 && nsk == EQ) + nsk = LE; + return true; + } + else if (am.is_zero(c)) { // ( > 0) + (c == 0) -> > 0 + if (nsk == EQ || nsk == LE || nsk == LT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + else { // (t > 0) + (c > 0) -> > 0 + if (nsk == EQ || nsk == LE || nsk == LT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + } + else if (sta == GE) { + if (am.is_neg(c)) { // [(t0 >= 0 + .. + tn >= 0) + (c < 0) t < -c + if (nsk == GE || nsk == GT) + return false; + if (sz > 1 && nsk == EQ) + nsk = LE; + return true; + } + else if (am.is_zero(c)) { // ( >= 0) + (c == 0) -> >= 0 + if (nsk == LT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + else { // (t >= 0) + (c > 0) -> > 0 + if (nsk == EQ || nsk == LE || nsk == LT) { + is_conflict = true; + return true; + } + else { + return false; + } + } + } + return false; + } + bool collect_domain_sign_ineq_consistent_form(sign_kind nsk, vector &as, vector &xs, vector &bs, scoped_anum& c) { + LINXI_DEBUG; + for (unsigned i = 0, sz = as.size(); i < sz; ++i) { + if (!update_var_domain(nsk, as[i], xs[i], bs[i], c)) + return false; + } + return true; + } + bool process_axbsc_form(sign_kind nsk, unsigned cid, vector &as, vector &xs, vector &bs, scoped_anum& c) { + LINXI_DEBUG; + bool is_conflict(false); + TRACE("linxi_simple_checker", + for (unsigned i = 0, sz = as.size(); i < sz; ++i) { + if (i > 0) + tout << "+ "; + tout << as[i] << "x[" << xs[i] << "]^" << bs[i] << " "; + } + tout << "+ " << c << " "; + display(tout, nsk); + tout << " 0\n"; + ); + if (!check_is_sign_ineq_consistent(nsk, as, xs, bs, c, is_conflict)) + return true; + TRACE("linxi_simple_checker", + tout << "is conflict: " << is_conflict << "\n" + ); + if (is_conflict) + return false; + clauses_visited[cid].visited = true; + if (!collect_domain_sign_ineq_consistent_form(nsk, as, xs, bs, c)) + return false; + return true; + } + bool collect_domain_axbsc_form(unsigned cid, unsigned lid) { + LINXI_DEBUG; + // [a*(x^k)] + ... + [a*(x^b)] + k form + literal lit = (*clauses[cid])[lid]; + bool s = lit.sign(); + ineq_atom *iat = to_ineq_atom(atoms[lit.var()]); + if (iat->size() > 1) + return true; + if (literal_special_kind[cid][lid] != UNK && + literal_special_kind[cid][lid] != AXBSC) + return true; + + poly *p = iat->p(0); + vector as; + for (unsigned i = 0, sz = pm.size(p); i < sz; ++i) { + as.push_back(scoped_anum(am)); + } + vector xs; + vector bs; + scoped_anum c(am); + unsigned cnt; + if (!check_is_axbsc(p, as, xs, bs, c, cnt)) { + literal_special_kind[cid][lid] = NK; + return true; + } + literal_special_kind[cid][lid] = AXBSC; + TRACE("linxi_simple_checker", + tout << "as size: " << as.size() << '\n'; + ); + while (as.size() > cnt) + as.pop_back(); + + sign_kind nsk = to_sign_kind(iat->get_kind()); + if (s) { + if (nsk == EQ) + return true; + else if (nsk == LT) + nsk = GE; + else if (nsk == GT) + nsk = LE; + } + TRACE("linxi_simple_checker", + tout << "ineq atom: " << '\n'; + for (unsigned i = 0, sz = iat->size(); i < sz; ++i) { + pm.display(tout, iat->p(i)); + tout << " is even: " << iat->is_even(i) << "\n"; + } + display(tout, nsk); + tout << " 0\n"; + tout << "\n"; + tout << "as size: " << as.size() << '\n'; + for (unsigned i = 0, sz = as.size(); i < sz; ++i) { + if (i > 0) + tout << "+ "; + tout << as[i] << "x[" << xs[i] << "]^" << bs[i] << " "; + } + tout << "+ " << c << " "; + display(tout, nsk); + tout << " 0\n"; + ); + if (!process_axbsc_form(nsk, cid, as, xs, bs, c)) + return false; + return true; + } + // bool update_all_mag_domain_by_ori() { + // LINXI_HERE; + // for (unsigned i = 0; i < arith_var_num; ++i) { + // if (!update_var_mag_domain_interval_by_ori(vars_domain[i], vars_domain[i].ori_val)) + // return false; + // } + // return true; + // } + bool collect_var_domain() { + LINXI_DEBUG; + // vector vec_id; + for (unsigned i = 0, sz = clauses.size(); i < sz; ++i) { + if (clauses_visited[i].visited) + continue; + if (clauses[i]->size() > 1) + continue; + literal lit = (*clauses[i])[0]; + atom *tmp_atom = atoms[lit.var()]; + if (tmp_atom == nullptr) { + clauses_visited[i].visited = true; + continue; + } + if (!tmp_atom->is_ineq_atom()) { + clauses_visited[i].visited = true; + continue; + } + ineq_atom *tmp_ineq_atom = to_ineq_atom(tmp_atom); + if (tmp_ineq_atom->size() > 1) + continue; + if (!collect_domain_axbc_form(i, 0)) + return false; + } + // if (!update_all_mag_domain_by_ori()) + // return false; + TRACE("linxi_simple_checker", + for (unsigned i = 0; i < arith_var_num; ++i) { + tout << "====== arith[" << i << "] ======\n"; + tout << "original value: "; + display(tout, am, vars_domain[i].ori_val); + tout << "\nmagitude value: "; + display(tout, am, vars_domain[i].mag_val); + tout << "\n"; + tout << "====== arith[" << i << "] ======\n"; + } + ); + // TRACE("linxi_simple_checker", + // tout << "vec_id.size(): " << vec_id.size() << "\n"; + // ); + for (unsigned i = 0, sz = clauses.size(); i < sz; ++i) { + // unsigned id = vec_id[i]; + if (!collect_domain_axbsc_form(i, 0)) + return false; + } + // if (!update_all_mag_domain_by_ori()) + // return false; + return true; + } + void endpoint_multiply(const Endpoint &a, const Endpoint &b, Endpoint &c) { + if (a.is_zero() || b.is_zero()) { + c.set_num(0, 0); + return ; + } + bool a_neg = a.is_neg(), b_neg = b.is_neg(); + if (a.m_inf || b.m_inf) { + c.m_inf = 1; + c.m_open = 1; + if (a_neg == b_neg) + c.m_is_lower = 0; + else + c.m_is_lower = 1; + } + else { + c.m_inf = 0; + c.m_open = (a.m_open | b.m_open); + am.set(c.m_val, a.m_val*b.m_val); + } + } + void get_max_min_endpoint(const ptr_vector &pev, Endpoint *&pmi, Endpoint *&pmx) { + pmi = pmx = pev[0]; + for (unsigned i = 1, sz = pev.size(); i < sz; ++i) { + if (*pmx < *pev[i]) + pmx = pev[i]; + if (*pev[i] < *pmi) + pmi = pev[i]; + } + } + void merge_mul_domain(Domain_Interval &pre, const Domain_Interval &now) { + TRACE("linxi_simple_checker", + tout << "dom: "; + display(tout, am, pre); + tout << "\n"; + tout << "di: "; + display(tout, am, now); + tout << "\n"; + ); + Endpoint plnl(am), plnu(am), punl(am), punu(am); + endpoint_multiply(pre.m_lower, now.m_lower, plnl); + endpoint_multiply(pre.m_lower, now.m_upper, plnu); + endpoint_multiply(pre.m_upper, now.m_lower, punl); + endpoint_multiply(pre.m_upper, now.m_upper, punu); + ptr_vector pev; + pev.push_back(&plnl); + pev.push_back(&plnu); + pev.push_back(&punl); + pev.push_back(&punu); + Endpoint *pmi, *pmx; + get_max_min_endpoint(pev, pmi, pmx); + pre.m_lower.copy(*pmi); + pre.m_lower.m_is_lower = 1; + pre.m_upper.copy(*pmx); + pre.m_upper.m_is_lower = 0; + + // if (pre.m_lower_inf && pre.m_upper_inf) { + // if ((!now.m_lower_inf && am.is_zero(now.m_lower)) && + // (!now.m_upper_inf && am.is_zero(now.m_upper))) { + + // } + // else { + // return ; + // } + // } + // if ((!pre.m_lower_inf && am.is_zero(pre.m_lower)) && + // (!pre.m_upper_inf && am.is_zero(pre.m_upper))) + // return ; + // if (now.m_lower_inf && now.m_upper_inf) { + // pre.m_lower_inf = 1; + // pre.m_upper_inf = 1; + // return ; + // } + // if (pre.m_lower_inf == 0 && !am.is_neg(pre.m_lower)) { + // // {+, +/inf} + // if (now.m_lower_inf == 0 && !am.is_neg(now.m_lower)) { + // // {+, +/inf} * {+, +/inf} + // // {a, b} * {c, d} -> {ac, bd/inf} + // pre.m_lower_open = (pre.m_lower_open | now.m_lower_open); + // am.set(pre.m_lower, now.m_lower * pre.m_lower); + + // pre.m_upper_inf = (pre.m_upper_inf | now.m_upper_inf); + // if (pre.m_upper_inf == 0) { + // pre.m_upper_open = (pre.m_upper_open | now.m_upper_open); + // am.set(pre.m_upper, now.m_upper * pre.m_upper); + // } + // } + // else if (now.m_upper_inf == 0 && !am.is_pos(now.m_upper)) { + // // {+, +/inf} * {-/inf, -} + // // {a, b} * {c, d} -> {bc, ad} + // Domain_Interval tmp_di(am, false); + // tmp_di.m_lower_inf = (pre.m_upper_inf | now.m_lower_inf); + // if (tmp_di.m_lower_inf == 0) { + // tmp_di.m_lower_open = (pre.m_upper_open | now.m_lower_open); + // am.set(tmp_di.m_lower, pre.m_upper * now.m_lower); + // } + + // tmp_di.m_upper_inf = 0; + // tmp_di.m_upper_open = (pre.m_lower_open | now.m_upper_open); + // am.set(tmp_di.m_upper, pre.m_lower * now.m_upper); + + // pre.copy(tmp_di); + // } + // else { + // // {+, +/inf} * {-/inf, +/inf} + // if (pre.m_upper_inf) { + // // {+, +inf) * {-/inf, +/inf} -> (-inf, +inf) + // pre.m_lower_inf = 1; + // } + // else { + // // {+, +} * {-/inf, +/inf} + // // {a, b} * {c, d} -> {bc, bd} + // // order matters! + // pre.m_lower_inf = now.m_lower_inf; + // if (pre.m_lower_inf == 0) { + // pre.m_lower_open = (pre.m_upper_open | now.m_lower_open); + // am.set(pre.m_lower, now.m_lower * pre.m_upper); + // } + // pre.m_upper_inf = now.m_upper_inf; + // if (pre.m_upper_inf == 0) { + // pre.m_upper_open = (pre.m_upper_open | now.m_upper_open); + // am.set(pre.m_upper, now.m_upper * pre.m_upper); + // } + // } + // } + // } + // else if (pre.m_upper_inf == 0 && !am.is_pos(pre.m_upper)) { + // LINXI_HERE; + // // {-/inf, -} + // if (now.m_upper_inf == 0 && !am.is_pos(now.m_upper)) { + // LINXI_HERE; + // // {-/inf, -} * {-/inf, -} + // if (pre.m_lower_inf || now.m_lower_inf) { + // // (-inf, b} * {c, d} -> {bd, +inf) + // // {a, b} * (-inf, d} -> {bd, +inf) + // pre.m_upper_inf = 1; + + // pre.m_lower_open = (pre.m_upper_open | now.m_upper_open); + // am.set(pre.m_lower, now.m_upper * pre.m_upper); + // } + // else { + // // {a, b} * {c, d} -> {bd, ac} + // Domain_Interval tmp_di(am, false); + // tmp_di.m_lower_inf = 0; + // tmp_di.m_upper_inf = 0; + // tmp_di.m_lower_open = (pre.m_upper_open | now.m_upper_open); + // tmp_di.m_upper_open = (pre.m_lower_open | now.m_lower_open); + // am.set(tmp_di.m_lower, pre.m_upper * now.m_upper); + // am.set(tmp_di.m_upper, pre.m_lower * now.m_lower); + // pre.copy(tmp_di); + // } + // } + // else if (now.m_lower_inf == 0 && !am.is_neg(now.m_lower)) { + // LINXI_HERE; + // // {-/inf, -} * {+, +/inf} + // // {a, b} * {c, d} -> {ad, bc} + // Domain_Interval tmp_di(am, false); + // tmp_di.m_lower_inf = (pre.m_lower_inf | now.m_upper_inf); + // if (tmp_di.m_lower_inf == 0) { + // tmp_di.m_lower_open = (pre.m_lower_open | now.m_upper_open); + // am.set(tmp_di.m_lower, pre.m_lower * now.m_upper); + // } + + // tmp_di.m_upper_inf = 0; + // tmp_di.m_upper_open = (pre.m_upper_open | now.m_lower_open); + // am.set(tmp_di.m_upper, pre.m_upper * now.m_lower); + // TRACE("linxi_simple_checker", + // tout << "tmp_di: "; + // display(tout, am, tmp_di); + // tout << "\n"; + // ); + // pre.copy(tmp_di); + // } + // else { + // LINXI_HERE; + // // {-/inf, -} * {-/inf, +/inf} + // if (pre.m_lower_inf) { + // // (-inf, -} * {-/inf, +/inf} -> (-inf, +inf) + // pre.m_upper_inf = 1; + // } + // else { + // // {-, -} * {-/inf, +/inf} + // // {pl, pu} * {nl, nu} -> {pl nu, pl nl} + // // order matters! + // pre.m_lower_inf = now.m_upper_inf; + // if (pre.m_lower_inf == 0) { + // pre.m_lower_open = (pre.m_lower_open | now.m_upper_open); + // am.set(pre.m_lower, now.m_upper * pre.m_lower); + // } + // pre.m_upper_inf = now.m_lower_inf; + // if (pre.m_upper_inf == 0) { + // pre.m_upper_open = (pre.m_lower_open | now.m_lower_open); + // am.set(pre.m_upper, now.m_lower * pre.m_lower); + // } + // } + // } + // } + // else { + // // {-/inf, +/inf} + // if (now.m_lower_inf == 0 && !am.is_neg(now.m_lower)) { + // // {-/inf, +/inf} * {+, +/inf} + // if (now.m_upper_inf) { + // // {-/inf, +/inf} * {+, +inf) -> (-inf, +inf) + // pre.m_lower_inf = 1; + // pre.m_upper_inf = 1; + // } + // else { + // // {a, b} * {c, d} -> {ad, bd} + // // {-/inf, +/inf} * {+, +} + // if (pre.m_lower_inf == 0) { + // pre.m_lower_open = (now.m_upper_open | pre.m_lower_open); + // am.set(pre.m_lower, now.m_upper * pre.m_lower); + // } + // if (pre.m_upper_inf == 0) { + // pre.m_upper_open = (now.m_upper_open | pre.m_upper_open); + // am.set(pre.m_upper, now.m_upper * pre.m_upper); + // } + // } + // } + // else if (now.m_upper_inf == 0 && !am.is_pos(now.m_upper)) { + // // {-/inf, +/inf} * {-/inf, -} + // if (now.m_lower_inf) { + // // {-/inf, +/inf} * (-inf, -} -> (-inf, +inf) + // pre.m_lower_inf = 1; + // pre.m_upper_inf = 1; + // } + // else { + // // {-/inf, +/inf} * {-, -} + // // {pl, pu} * {nl, nu} -> {pu nl, pl nl} + // // order matters! + // if (pre.m_lower_inf == 0) { + // pre.m_lower_open = (pre.m_upper_open | now.m_lower_open); + // am.set(pre.m_lower, now.m_lower * pre.m_upper); + // } + // if (pre.m_upper_inf == 0) { + // pre.m_upper_open = (pre.m_lower_open | now.m_lower_open); + // am.set(pre.m_upper, now.m_lower * pre.m_lower); + // } + // } + // } + // else { + // // {-/inf, +/inf} * {-/inf, +/inf} + // if (pre.m_lower_inf || pre.m_upper_inf || + // now.m_lower_inf || now.m_upper_inf) { + // pre.m_lower_inf = 1; + // pre.m_upper_inf = 1; + // } + // else { + // // {-, +} * {-, +} + // scoped_anum plnl(am), punu(am); + // unsigned plo, puo; + // am.set(plnl, pre.m_lower * now.m_lower); + // am.set(punu, pre.m_upper * now.m_upper); + // scoped_anum plnu(am), punl(am); + // am.set(plnu, pre.m_lower * now.m_upper); + // am.set(punl, pre.m_upper * now.m_lower); + // if (plnl > punu) { + // puo = (pre.m_lower_open | now.m_lower_open); + // am.set(pre.m_upper, plnl); + // } + // else if (plnl == punu) { + // puo = ((pre.m_lower_open | now.m_lower_open) & + // (pre.m_upper_open | now.m_upper_open)); + // am.set(pre.m_upper, plnl); + // } + // else { + // puo = (pre.m_upper_open | now.m_upper_open); + // am.set(pre.m_upper, punu); + // } + // if (plnu < punl) { + // plo = (pre.m_lower_open | now.m_upper_open); + // am.set(pre.m_lower, plnu); + // } + // else if (plnu == punl) { + // plo = ((pre.m_lower_open | now.m_upper_open) & + // (pre.m_upper_open | now.m_lower_open)); + // am.set(pre.m_lower, plnu); + // } + // else { + // plo = (pre.m_upper_open | now.m_lower_open); + // am.set(pre.m_lower, punl); + // } + // } + // } + // } + } + + void get_monomial_domain(monomial *m, const scoped_anum &a, Domain_Interval &dom) { + LINXI_DEBUG; + TRACE("linxi_simple_checker", + tout << "monomial: "; + pm.display(tout, m); + tout << '\n'; + tout << "coefficient: " << a << "\n"; + tout << "# "; + for (unsigned i = 0, sz = pm.size(m); i < sz; ++i) { + var v = pm.get_var(m, i); + tout << " (" << i << ", " << pm.degree_of(m, v) << ")"; + } + tout << "\n"; + ); + + // [a, a] + dom.set_num(a); + for (unsigned i = 0, sz = pm.size(m); i < sz; ++i) { + var v = pm.get_var(m, i); + unsigned deg = pm.degree_of(m, v); + const Domain_Interval &di = ((deg & 1) == 0 ? vars_domain[v].mag_val : vars_domain[v].ori_val); + TRACE("linxi_simple_checker", + tout << "dom: "; + display(tout, am, dom); + tout << "\n"; + tout << "var: " << v; + tout << ", di: "; + display(tout, am, di); + tout << "\n"; + ); + for (unsigned j = 0; j < deg; ++j) { + merge_mul_domain(dom, di); + } + TRACE("linxi_simple_checker", + tout << "after merge mul: "; + display(tout, am, dom); + tout << "\n"; + ); + // mul 0 + // if (dom.m_lower_inf && dom.m_upper_inf) + // return ; + } + } + void endpoint_add(Endpoint &a, const Endpoint &b) { + a.m_inf = (a.m_inf | b.m_inf); + if (a.m_inf == 0) { + am.set(a.m_val, a.m_val + b.m_val); + a.m_open = (a.m_open | b.m_open); + } + } + void merge_add_domain(Domain_Interval &pre, const Domain_Interval &now) { + endpoint_add(pre.m_lower, now.m_lower); + endpoint_add(pre.m_upper, now.m_upper); + // pre.m_lower_inf = (pre.m_lower_inf | now.m_lower_inf); + // if (pre.m_lower_inf == 0) { + // am.set(pre.m_lower, pre.m_lower + now.m_lower); + // pre.m_lower_open = (pre.m_lower_open | now.m_lower_open); + // } + // pre.m_upper_inf = (pre.m_upper_inf | now.m_upper_inf); + // if (pre.m_upper_inf == 0) { + // am.set(pre.m_upper, pre.m_upper + now.m_upper); + // pre.m_upper_open = (pre.m_upper_open | now.m_upper_open); + // } + } + sign_kind get_poly_sign(const poly *p) { + LINXI_DEBUG; + scoped_anum a(am); + am.set(a, pm.coeff(p, 0)); + Domain_Interval pre(am); + get_monomial_domain(pm.get_monomial(p, 0), a, pre); + TRACE("linxi_simple_checker", + tout << "poly: "; + pm.display(tout, p); + tout << "\n"; + ); + TRACE("linxi_simple_checker", + tout << "pre: "; + display(tout, am, pre); + tout << "\n"; + ); + for (unsigned i = 1, sz = pm.size(p); i < sz; ++i) { + am.set(a, pm.coeff(p, i)); + Domain_Interval now(am); + get_monomial_domain(pm.get_monomial(p, i), a, now); + TRACE("linxi_simple_checker", + tout << "pre: "; + display(tout, am, pre); + tout << "\n"; + tout << "now: "; + display(tout, am, now); + tout << "\n"; + ); + if (now.m_lower.m_inf && now.m_upper.m_inf) + return NONE; + merge_add_domain(pre, now); + TRACE("linxi_simple_checker", + tout << "after merge: "; + display(tout, am, pre); + tout << "\n"; + ); + if (pre.m_lower.m_inf && pre.m_upper.m_inf) + return NONE; + } + // if (pre.m_lower_inf && pre.m_upper_inf) + // return NONE; + if (pre.m_lower.m_inf) { + if (am.is_neg(pre.m_upper.m_val)) { + // (-inf, -} + return LT; + } + else if (am.is_zero(pre.m_upper.m_val)) { + // (-inf, 0} + if (pre.m_upper.m_open) + return LT; + else + return LE; + } + else { + // (-inf, +} + return NONE; + } + } + else if (pre.m_upper.m_inf) { + if (am.is_neg(pre.m_lower.m_val)) { + // {-, +inf) + return NONE; + } + else if (am.is_zero(pre.m_lower.m_val)) { + // {0, +inf) + if (pre.m_lower.m_open) + return GT; + else + return GE; + } + else { + // {+, +inf) + return GT; + } + } + else { + // [0, 0] + if (am.is_zero(pre.m_lower.m_val) && am.is_zero(pre.m_upper.m_val)) + return EQ; + else if (am.is_zero(pre.m_lower.m_val)) { + // {0, +} + if (pre.m_lower.m_open) + return GT; + else + return GE; + } + else if (am.is_zero(pre.m_upper.m_val)) { + // {-, 0} + if (pre.m_upper.m_open) + return LT; + else + return LE; + } + else { + if (am.is_pos(pre.m_lower.m_val)) + return GT; + else if (am.is_neg(pre.m_upper.m_val)) + return LT; + else + return NONE; + } + } + return NONE; + } + + sign_kind get_poly_sign_degree(const poly *p, bool is_even) { + LINXI_DEBUG; + sign_kind ret = get_poly_sign(p); + if (is_even) { + if (ret == GE || ret == LE || ret == NONE) + ret = GE; + else if (ret != EQ) + ret = GT; + } + TRACE("linxi_simple_checker", + tout << "ret sign: "; + display(tout, ret); + tout << "\n"; + tout << "is even: " << is_even << "\n"; + ); + return ret; + } + void merge_mul_sign(sign_kind &pre, sign_kind now) { + if (pre == EQ) + return ; + if (now == EQ) { + pre = EQ; + return ; + } + if (pre == NONE) + return ; + + if (now == NONE) { + pre = NONE; + } + // else if (now == EQ) { + // pre = EQ; + // } + else if (now == LT) { + if (pre == GE) + pre = LE; + else if (pre == GT) + pre = LT; + else if (pre == LE) + pre = GE; + else if (pre == LT) + pre = GT; + } + else if (now == GT) { + // if (pre == LE) + // pre = LE; + // else if (pre == LT) + // pre = LT; + // else if (pre == GT) + // pre = GT; + // else if (pre == GE) + // pre = GE; + } + else if (now == LE) { + if (pre == GE) + pre = LE; + else if (pre == GT) + pre = LE; + else if (pre == LE) + pre = GE; + else if (pre == LT) + pre = GE; + } + else if (now == GE) { + // if (pre == LE) + // pre = LE; + if (pre == LT) + pre = LE; + else if (pre == GT) + pre = GE; + // else if (pre == GE) + // pre = GE; + } + } + bool check_ineq_atom_satisfiable(const ineq_atom *iat, bool s) { + LINXI_DEBUG; + TRACE("linxi_simple_checker", + tout << "s: " << s << "\n"; + tout << "kd: " << iat->get_kind() << "\n"; + ); + sign_kind nsk = to_sign_kind(iat->get_kind()); + if (s) { + if (nsk == EQ) + return true; + else if (nsk == GT) + nsk = LE; + else + nsk = GE; + } + TRACE("linxi_simple_checker", + tout << "ineq atom: " << '\n'; + for (unsigned i = 0, sz = iat->size(); i < sz; ++i) { + pm.display(tout, iat->p(i)); + tout << " is even: " << iat->is_even(i) << "\n"; + } + display(tout, nsk); + tout << " 0\n"; + ); + // return true; + + sign_kind pre = get_poly_sign_degree(iat->p(0), iat->is_even(0)); + + for (unsigned i = 1, sz = iat->size(); i < sz; ++i) { + sign_kind now = get_poly_sign_degree(iat->p(i), iat->is_even(i)); + // TRACE("linxi_simple_checker", + // tout << "pre: "; + // display(tout, pre); + // tout << ", now: "; + // display(tout, now); + // tout << "\n"; + // ); + merge_mul_sign(pre, now); + // TRACE("linxi_simple_checker", + // tout << "==> "; + // display(tout, pre); + // ); + if (pre == NONE) + return true; + if ((nsk == EQ || nsk == GE || nsk == LE) && + (pre == EQ || pre == GE || pre == LE)) + return true; + } + TRACE("linxi_simple_checker", + tout << "pre: "; + display(tout, pre); + tout << ", nsk: "; + display(tout, nsk); + tout << "\n"; + ); + if (pre == NONE) + return true; + if (pre == EQ && (nsk == LT || nsk == GT)) + return false; + if (pre == GE && nsk == LT) + return false; + if (pre == GT && (nsk == LT || nsk == LE || nsk == EQ)) + return false; + if (pre == LE && nsk == GT) + return false; + if (pre == LT && (nsk == GT || nsk == GE || nsk == EQ)) + return false; + return true; + } + bool check_literal_satisfiable(unsigned cid, unsigned lit_id) { + LINXI_DEBUG; + literal lit = (*clauses[cid])[lit_id]; + const var &v = lit.var(); + atom *at = atoms[v]; + if (at == nullptr) { + clauses_visited[cid].visited = true; + return true; + } + if (!at->is_ineq_atom()) { + clauses_visited[cid].visited = true; + return true; + } + // TRACE("linxi_sign", + // tout << "literal: " << lit << '\n'; + // ); + bool s = lit.sign(); + return check_ineq_atom_satisfiable(to_ineq_atom(at), s); + } + bool check_clause_satisfiable(unsigned cid) { + LINXI_DEBUG; + const clause *cla = clauses[cid]; + TRACE("linxi_simple_checker", + tout << "clause size: " << cla->size() << '\n'; + ); + unsigned sz = cla->size(); + if (clauses_visited[cid].literal_visited.size() == 0) { + clauses_visited[cid].literal_visited.resize(sz, false); + literal_special_kind[cid].resize(sz, UNK); + } + unsigned sat_lit_id = sz; + for (unsigned i = 0; i < sz; ++i) { + if (clauses_visited[cid].literal_visited[i]) + continue; + if (check_literal_satisfiable(cid, i)) { + if (clauses_visited[cid].visited) + return true; + if (sat_lit_id == sz) + sat_lit_id = i; + else + return true; + } else { + clauses_visited[cid].literal_visited[i] = true; + literal lit = (*clauses[cid])[i]; + lit.neg(); + // if (atoms[lit.var()] != nullptr && atoms[lit.var()]->is_ineq_atom()) { + // ineq_atom *iat = to_ineq_atom(atoms[lit.var()]); + // if (to_sign_kind(iat->get_kind()) == EQ && lit.sign()) { + // continue; + // } + // } + learned_unit.push_back(lit); + // sol.mk_clause(1, &lit); + TRACE("linxi_simple_checker_learned", + tout << "making new clauses!\n"; + tout << "sign: " << lit.sign() << '\n'; + if (atoms[lit.var()] != nullptr && atoms[lit.var()]->is_ineq_atom()) { + ineq_atom *iat = to_ineq_atom(atoms[lit.var()]); + tout << "ineq atom: " << '\n'; + sign_kind nsk = to_sign_kind(iat->get_kind()); + for (unsigned i = 0, sz = iat->size(); i < sz; ++i) { + pm.display(tout, iat->p(i)); + tout << " is even: " << iat->is_even(i) << "\n"; + } + display(tout, nsk); + tout << " 0\n"; + } + ); + } + } + if (sat_lit_id != sz) { + if (!collect_domain_axbc_form(cid, sat_lit_id)) + return false; + if (!collect_domain_axbsc_form(cid, sat_lit_id)) + return false; + return true; + } + return false; + } + bool check() { + LINXI_DEBUG; + for (unsigned i = 0, sz = clauses.size(); i < sz; ++i) { + if (clauses_visited[i].visited) + continue; + if (!check_clause_satisfiable(i)) { + return false; + } + } + return true; + } + void test_anum() { + scoped_anum x(am), y(am); + am.set(x, 3); + am.set(y, 5); + TRACE("linxi_simple_checker", + tout << x << " " << y << std::endl; + ); + } + bool operator()() { + + improved = true; + while (improved) { + improved = false; + if (!check()) + return false; + TRACE("linxi_simple_checker", + for (unsigned i = 0; i < arith_var_num; ++i) { + tout << "====== arith[" << i << "] ======\n"; + tout << "original value: "; + display(tout, am, vars_domain[i].ori_val); + tout << "\nmagitude value: "; + display(tout, am, vars_domain[i].mag_val); + tout << "\n"; + tout << "====== arith[" << i << "] ======\n"; + } + ); + } + // LINXI_DEBUG; + // // test_anum(); + // if (!collect_var_domain()) + // return false; + // TRACE("linxi_simple_checker", + // for (unsigned i = 0; i < arith_var_num; ++i) { + // tout << "====== arith[" << i << "] ======\n"; + // tout << "original value: "; + // display(tout, am, vars_domain[i].ori_val); + // tout << "\nmagitude value: "; + // display(tout, am, vars_domain[i].mag_val); + // tout << "\n"; + // tout << "====== arith[" << i << "] ======\n"; + // } + // ); + // if (!check()) + // return false; + return true; + } + }; + // Simple_Checker::Simple_Checker(solver &_sol, pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, clause_vector &_learned, const atom_vector &_atoms, const unsigned &_arith_var_num) { + Simple_Checker::Simple_Checker(pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, literal_vector &_learned_unit, const atom_vector &_atoms, const unsigned &_arith_var_num) { + LINXI_DEBUG; + // m_imp = alloc(imp, _sol, _pm, _am, _clauses, _learned, _atoms, _arith_var_num); + m_imp = alloc(imp, _pm, _am, _clauses, _learned_unit, _atoms, _arith_var_num); + } + Simple_Checker::~Simple_Checker() { + LINXI_DEBUG; + dealloc(m_imp); + } + bool Simple_Checker::operator()() { + LINXI_DEBUG; + return m_imp->operator()(); + } +} \ No newline at end of file diff --git a/src/nlsat/nlsat_simple_checker.h b/src/nlsat/nlsat_simple_checker.h new file mode 100644 index 000000000..969c7a141 --- /dev/null +++ b/src/nlsat/nlsat_simple_checker.h @@ -0,0 +1,15 @@ +#include "math/polynomial/algebraic_numbers.h" +#include "nlsat/nlsat_clause.h" + + +namespace nlsat { + class Simple_Checker { + struct imp; + imp * m_imp; + public: + // Simple_Checker(solver &_sol, pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, clause_vector &_learned, const atom_vector &_atoms, const unsigned &_arith_var_num); + Simple_Checker(pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, literal_vector &_learned_unit, const atom_vector &_atoms, const unsigned &_arith_var_num); + ~Simple_Checker(); + bool operator()(); + }; +} \ No newline at end of file diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp deleted file mode 100644 index 9f43b7a78..000000000 --- a/src/nlsat/nlsat_solver.cpp +++ /dev/null @@ -1,4027 +0,0 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - nlsat_solver.cpp - -Abstract: - - Nonlinear arithmetic satisfiability procedure. The procedure is - complete for nonlinear real arithmetic, but it also has limited - support for integers. - -Author: - - Leonardo de Moura (leonardo) 2012-01-02. - -Revision History: - ---*/ -#include "util/z3_exception.h" -#include "util/chashtable.h" -#include "util/id_gen.h" -#include "util/map.h" -#include "util/dependency.h" -#include "util/permutation.h" -#include "math/polynomial/algebraic_numbers.h" -#include "math/polynomial/polynomial_cache.h" -#include "nlsat/nlsat_solver.h" -#include "nlsat/nlsat_clause.h" -#include "nlsat/nlsat_assignment.h" -#include "nlsat/nlsat_justification.h" -#include "nlsat/nlsat_evaluator.h" -#include "nlsat/nlsat_explain.h" -#include "nlsat/nlsat_params.hpp" -#include "nlsat/nlsat_simplify.h" - -#define NLSAT_EXTRA_VERBOSE - -#ifdef NLSAT_EXTRA_VERBOSE -#define NLSAT_VERBOSE(CODE) IF_VERBOSE(10, CODE) -#else -#define NLSAT_VERBOSE(CODE) ((void)0) -#endif - -namespace nlsat { - - - typedef chashtable ineq_atom_table; - typedef chashtable root_atom_table; - - // for apply_permutation procedure - void swap(clause * & c1, clause * & c2) noexcept { - std::swap(c1, c2); - } - - struct solver::ctx { - params_ref m_params; - reslimit& m_rlimit; - small_object_allocator m_allocator; - unsynch_mpq_manager m_qm; - pmanager m_pm; - anum_manager m_am; - bool m_incremental; - ctx(reslimit& rlim, params_ref const & p, bool incremental): - m_params(p), - m_rlimit(rlim), - m_allocator("nlsat"), - m_pm(rlim, m_qm, &m_allocator), - m_am(rlim, m_qm, p, &m_allocator), - m_incremental(incremental) - {} - }; - - struct solver::imp { - - - struct dconfig { - typedef imp value_manager; - typedef small_object_allocator allocator; - typedef void* value; - static const bool ref_count = false; - }; - - typedef dependency_manager assumption_manager; - typedef assumption_manager::dependency* _assumption_set; - - typedef obj_ref assumption_set_ref; - - - typedef polynomial::cache cache; - typedef ptr_vector interval_set_vector; - - - - ctx& m_ctx; - solver& m_solver; - reslimit& m_rlimit; - small_object_allocator& m_allocator; - bool m_incremental; - unsynch_mpq_manager& m_qm; - pmanager& m_pm; - cache m_cache; - anum_manager& m_am; - mutable assumption_manager m_asm; - assignment m_assignment, m_lo, m_hi; // partial interpretation - evaluator m_evaluator; - interval_set_manager & m_ism; - ineq_atom_table m_ineq_atoms; - root_atom_table m_root_atoms; - - - vector m_bounds; - - id_gen m_cid_gen; - clause_vector m_clauses; // set of clauses - clause_vector m_learned; // set of learned clauses - clause_vector m_valids; - - unsigned m_num_bool_vars; - atom_vector m_atoms; // bool_var -> atom - svector m_bvalues; // boolean assignment - unsigned_vector m_levels; // bool_var -> level - svector m_justifications; - vector m_bwatches; // bool_var (that are not attached to atoms) -> clauses where it is maximal - bool_vector m_dead; // mark dead boolean variables - id_gen m_bid_gen; - - simplify m_simplify; - - bool_vector m_is_int; // m_is_int[x] is true if variable is integer - vector m_watches; // var -> clauses where variable is maximal - interval_set_vector m_infeasible; // var -> to a set of interval where the variable cannot be assigned to. - atom_vector m_var2eq; // var -> to asserted equality - var_vector m_perm; // var -> var permutation of the variables - var_vector m_inv_perm; - // m_perm: internal -> external - // m_inv_perm: external -> internal - struct perm_display_var_proc : public display_var_proc { - var_vector & m_perm; - display_var_proc m_default_display_var; - display_var_proc const * m_proc; // display external var ids - perm_display_var_proc(var_vector & perm): - m_perm(perm), - m_proc(nullptr) { - } - std::ostream& operator()(std::ostream & out, var x) const override { - if (m_proc == nullptr) - m_default_display_var(out, x); - else - (*m_proc)(out, m_perm[x]); - return out; - } - }; - perm_display_var_proc m_display_var; - - display_assumption_proc const* m_display_assumption; - struct display_literal_assumption : public display_assumption_proc { - imp& i; - literal_vector const& lits; - display_literal_assumption(imp& i, literal_vector const& lits): i(i), lits(lits) {} - std::ostream& operator()(std::ostream& out, assumption a) const override { - if (lits.begin() <= a && a < lits.end()) { - out << *((literal const*)a); - } - else if (i.m_display_assumption) { - (*i.m_display_assumption)(out, a); - } - return out; - } - - }; - struct scoped_display_assumptions { - imp& i; - display_assumption_proc const* m_save; - scoped_display_assumptions(imp& i, display_assumption_proc const& p): i(i), m_save(i.m_display_assumption) { - i.m_display_assumption = &p; - } - ~scoped_display_assumptions() { - i.m_display_assumption = m_save; - } - }; - - explain m_explain; - - bool_var m_bk; // current Boolean variable we are processing - var m_xk; // current arith variable we are processing - - unsigned m_scope_lvl; - - struct bvar_assignment {}; - struct stage {}; - struct trail { - enum kind { BVAR_ASSIGNMENT, INFEASIBLE_UPDT, NEW_LEVEL, NEW_STAGE, UPDT_EQ }; - kind m_kind; - union { - bool_var m_b; - interval_set * m_old_set; - atom * m_old_eq; - }; - trail(bool_var b, bvar_assignment):m_kind(BVAR_ASSIGNMENT), m_b(b) {} - trail(interval_set * old_set):m_kind(INFEASIBLE_UPDT), m_old_set(old_set) {} - trail(bool s, stage):m_kind(s ? NEW_STAGE : NEW_LEVEL) {} - trail(atom * a):m_kind(UPDT_EQ), m_old_eq(a) {} - }; - svector m_trail; - - anum m_zero; - - // configuration - unsigned long long m_max_memory; - unsigned m_lazy; // how lazy the solver is: 0 - satisfy all learned clauses, 1 - process only unit and empty learned clauses, 2 - use only conflict clauses for resolving conflicts - bool m_simplify_cores; - bool m_reorder; - bool m_randomize; - bool m_random_order; - unsigned m_random_seed; - bool m_inline_vars; - bool m_log_lemmas; - bool m_check_lemmas; - unsigned m_max_conflicts; - unsigned m_lemma_count; - - struct stats { - unsigned m_simplifications; - unsigned m_restarts; - unsigned m_conflicts; - unsigned m_propagations; - unsigned m_decisions; - unsigned m_stages; - unsigned m_irrational_assignments; // number of irrational witnesses - void reset() { memset(this, 0, sizeof(*this)); } - stats() { reset(); } - }; - // statistics - stats m_stats; - - imp(solver& s, ctx& c): - m_ctx(c), - m_solver(s), - m_rlimit(c.m_rlimit), - m_allocator(c.m_allocator), - m_incremental(c.m_incremental), - m_qm(c.m_qm), - m_pm(c.m_pm), - m_cache(m_pm), - m_am(c.m_am), - m_asm(*this, m_allocator), - m_assignment(m_am), m_lo(m_am), m_hi(m_am), - m_evaluator(s, m_assignment, m_pm, m_allocator), - m_ism(m_evaluator.ism()), - m_num_bool_vars(0), - m_simplify(s, m_atoms, m_clauses, m_learned, m_pm), - m_display_var(m_perm), - m_display_assumption(nullptr), - m_explain(s, m_assignment, m_cache, m_atoms, m_var2eq, m_evaluator, nlsat_params(c.m_params).cell_sample()), - m_scope_lvl(0), - m_lemma(s), - m_lazy_clause(s), - m_lemma_assumptions(m_asm) { - updt_params(c.m_params); - reset_statistics(); - mk_true_bvar(); - m_lemma_count = 0; - } - - ~imp() { - clear(); - } - - void mk_true_bvar() { - bool_var b = mk_bool_var(); - SASSERT(b == true_bool_var); - literal true_lit(b, false); - mk_clause(1, &true_lit, false, nullptr); - } - - void updt_params(params_ref const & _p) { - nlsat_params p(_p); - m_max_memory = p.max_memory(); - m_lazy = p.lazy(); - m_simplify_cores = p.simplify_conflicts(); - bool min_cores = p.minimize_conflicts(); - m_reorder = p.reorder(); - m_randomize = p.randomize(); - m_max_conflicts = p.max_conflicts(); - m_random_order = p.shuffle_vars(); - m_random_seed = p.seed(); - m_inline_vars = p.inline_vars(); - m_log_lemmas = p.log_lemmas(); - m_check_lemmas = p.check_lemmas(); - m_ism.set_seed(m_random_seed); - m_explain.set_simplify_cores(m_simplify_cores); - m_explain.set_minimize_cores(min_cores); - m_explain.set_factor(p.factor()); - m_am.updt_params(p.p); - } - - void reset() { - m_explain.reset(); - m_lemma.reset(); - m_lazy_clause.reset(); - undo_until_size(0); - del_clauses(); - del_unref_atoms(); - m_cache.reset(); - m_assignment.reset(); - m_lo.reset(); - m_hi.reset(); - } - - void clear() { - m_explain.reset(); - m_lemma.reset(); - m_lazy_clause.reset(); - undo_until_size(0); - del_clauses(); - del_unref_atoms(); - } - - void checkpoint() { - if (!m_rlimit.inc()) throw solver_exception(m_rlimit.get_cancel_msg()); - if (memory::get_allocation_size() > m_max_memory) throw solver_exception(Z3_MAX_MEMORY_MSG); - } - - // ----------------------- - // - // Basic - // - // ----------------------- - - unsigned num_bool_vars() const { - return m_num_bool_vars; - } - - unsigned num_vars() const { - return m_is_int.size(); - } - - bool is_int(var x) const { - return m_is_int[x]; - } - - void inc_ref(assumption) {} - - void dec_ref(assumption) {} - - void inc_ref(_assumption_set a) { - if (a != nullptr) m_asm.inc_ref(a); - } - - void dec_ref(_assumption_set a) { - if (a != nullptr) m_asm.dec_ref(a); - } - - void inc_ref(bool_var b) { - if (b == null_bool_var) - return; - atom * a = m_atoms[b]; - if (a == nullptr) - return; - TRACE("ref", display(tout << "inc: " << b << " " << a->ref_count() << " ", *a) << "\n";); - a->inc_ref(); - } - - void inc_ref(literal l) { - inc_ref(l.var()); - } - - void dec_ref(bool_var b) { - if (b == null_bool_var) - return; - atom * a = m_atoms[b]; - if (a == nullptr) - return; - SASSERT(a->ref_count() > 0); - a->dec_ref(); - TRACE("ref", display(tout << "dec: " << b << " " << a->ref_count() << " ", *a) << "\n";); - if (a->ref_count() == 0) - del(a); - } - - void dec_ref(literal l) { - dec_ref(l.var()); - } - - bool is_arith_atom(bool_var b) const { return m_atoms[b] != nullptr; } - - bool is_arith_literal(literal l) const { return is_arith_atom(l.var()); } - - var max_var(poly const * p) const { - return m_pm.max_var(p); - } - - var max_var(bool_var b) const { - if (!is_arith_atom(b)) - return null_var; - else - return m_atoms[b]->max_var(); - } - - var max_var(literal l) const { - return max_var(l.var()); - } - - /** - \brief Return the maximum variable occurring in cls. - */ - var max_var(unsigned sz, literal const * cls) const { - var x = null_var; - for (unsigned i = 0; i < sz; i++) { - literal l = cls[i]; - if (is_arith_literal(l)) { - var y = max_var(l); - if (x == null_var || y > x) - x = y; - } - } - return x; - } - - var max_var(clause const & cls) const { - return max_var(cls.size(), cls.data()); - } - - /** - \brief Return the maximum Boolean variable occurring in cls. - */ - bool_var max_bvar(clause const & cls) const { - bool_var b = null_bool_var; - for (literal l : cls) { - if (b == null_bool_var || l.var() > b) - b = l.var(); - } - return b; - } - - /** - \brief Return the degree of the maximal variable of the given atom - */ - unsigned degree(atom const * a) const { - if (a->is_ineq_atom()) { - unsigned max = 0; - unsigned sz = to_ineq_atom(a)->size(); - var x = a->max_var(); - for (unsigned i = 0; i < sz; i++) { - unsigned d = m_pm.degree(to_ineq_atom(a)->p(i), x); - if (d > max) - max = d; - } - return max; - } - else { - return m_pm.degree(to_root_atom(a)->p(), a->max_var()); - } - } - - /** - \brief Return the degree of the maximal variable in c - */ - unsigned degree(clause const & c) const { - var x = max_var(c); - if (x == null_var) - return 0; - unsigned max = 0; - for (literal l : c) { - atom const * a = m_atoms[l.var()]; - if (a == nullptr) - continue; - unsigned d = degree(a); - if (d > max) - max = d; - } - return max; - } - - // ----------------------- - // - // Variable, Atoms, Clauses & Assumption creation - // - // ----------------------- - - bool_var mk_bool_var_core() { - bool_var b = m_bid_gen.mk(); - m_num_bool_vars++; - m_atoms .setx(b, nullptr, nullptr); - m_bvalues .setx(b, l_undef, l_undef); - m_levels .setx(b, UINT_MAX, UINT_MAX); - m_justifications.setx(b, null_justification, null_justification); - m_bwatches .setx(b, clause_vector(), clause_vector()); - m_dead .setx(b, false, true); - return b; - } - - bool_var mk_bool_var() { - return mk_bool_var_core(); - } - - var mk_var(bool is_int) { - var x = m_pm.mk_var(); - register_var(x, is_int); - return x; - } - void register_var(var x, bool is_int) { - SASSERT(x == num_vars()); - m_is_int. push_back(is_int); - m_watches. push_back(clause_vector()); - m_infeasible.push_back(nullptr); - m_var2eq. push_back(nullptr); - m_perm. push_back(x); - m_inv_perm. push_back(x); - SASSERT(m_is_int.size() == m_watches.size()); - SASSERT(m_is_int.size() == m_infeasible.size()); - SASSERT(m_is_int.size() == m_var2eq.size()); - SASSERT(m_is_int.size() == m_perm.size()); - SASSERT(m_is_int.size() == m_inv_perm.size()); - } - - bool_vector m_found_vars; - void vars(literal l, var_vector& vs) { - vs.reset(); - atom * a = m_atoms[l.var()]; - if (a == nullptr) { - - } - else if (a->is_ineq_atom()) { - unsigned sz = to_ineq_atom(a)->size(); - var_vector new_vs; - for (unsigned j = 0; j < sz; j++) { - m_found_vars.reset(); - m_pm.vars(to_ineq_atom(a)->p(j), new_vs); - for (unsigned i = 0; i < new_vs.size(); ++i) { - if (!m_found_vars.get(new_vs[i], false)) { - m_found_vars.setx(new_vs[i], true, false); - vs.push_back(new_vs[i]); - } - } - } - } - else { - m_pm.vars(to_root_atom(a)->p(), vs); - //vs.erase(max_var(to_root_atom(a)->p())); - vs.push_back(to_root_atom(a)->x()); - } - } - - void deallocate(ineq_atom * a) { - unsigned obj_sz = ineq_atom::get_obj_size(a->size()); - a->~ineq_atom(); - m_allocator.deallocate(obj_sz, a); - } - - void deallocate(root_atom * a) { - a->~root_atom(); - m_allocator.deallocate(sizeof(root_atom), a); - } - - void del(bool_var b) { - SASSERT(m_bwatches[b].empty()); - //SASSERT(m_bvalues[b] == l_undef); - m_num_bool_vars--; - m_dead[b] = true; - m_atoms[b] = nullptr; - m_bvalues[b] = l_undef; - m_bid_gen.recycle(b); - } - - void del(ineq_atom * a) { - CTRACE("nlsat_solver", a->ref_count() > 0, display(tout, *a) << "\n";); - // this triggers in too many benign cases: - // SASSERT(a->ref_count() == 0); - m_ineq_atoms.erase(a); - del(a->bvar()); - unsigned sz = a->size(); - for (unsigned i = 0; i < sz; i++) - m_pm.dec_ref(a->p(i)); - deallocate(a); - } - - void del(root_atom * a) { - SASSERT(a->ref_count() == 0); - m_root_atoms.erase(a); - del(a->bvar()); - m_pm.dec_ref(a->p()); - deallocate(a); - } - - void del(atom * a) { - if (a == nullptr) - return; - TRACE("nlsat_verbose", display(tout << "del: b" << a->m_bool_var << " " << a->ref_count() << " ", *a) << "\n";); - if (a->is_ineq_atom()) - del(to_ineq_atom(a)); - else - del(to_root_atom(a)); - } - - // Delete atoms with ref_count == 0 - void del_unref_atoms() { - for (auto* a : m_atoms) { - del(a); - } - } - - - ineq_atom* mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool& is_new, bool simplify) { - SASSERT(sz >= 1); - SASSERT(k == atom::LT || k == atom::GT || k == atom::EQ); - int sign = 1; - polynomial_ref p(m_pm); - ptr_buffer uniq_ps; - var max = null_var; - for (unsigned i = 0; i < sz; i++) { - p = m_pm.flip_sign_if_lm_neg(ps[i]); - if (p.get() != ps[i] && !is_even[i]) { - sign = -sign; - } - var curr_max = max_var(p.get()); - if (curr_max > max || max == null_var) - max = curr_max; - if (sz == 1 && simplify) { - if (sign < 0) - k = atom::flip(k); - sign = 1; - polynomial::manager::ineq_type t; - switch (k) { - case atom::EQ: t = polynomial::manager::ineq_type::EQ; break; - case atom::LT: t = polynomial::manager::ineq_type::LT; break; - case atom::GT: t = polynomial::manager::ineq_type::GT; break; - default: UNREACHABLE(); break; - } - polynomial::var_vector vars; - m_pm.vars(p, vars); - bool all_int = all_of(vars, [&](var x) { return is_int(x); }); - if (!all_int) - t = polynomial::manager::ineq_type::EQ; - m_pm.gcd_simplify(p, t); - } - uniq_ps.push_back(m_cache.mk_unique(p)); - TRACE("nlsat_table_bug", tout << "p: " << p << ", uniq: " << uniq_ps.back() << "\n";); - //verbose_stream() << "p: " << p.get() << ", uniq: " << uniq_ps.back() << "\n"; - } - void * mem = m_allocator.allocate(ineq_atom::get_obj_size(sz)); - if (sign < 0) - k = atom::flip(k); - ineq_atom * tmp_atom = new (mem) ineq_atom(k, sz, uniq_ps.data(), is_even, max); - ineq_atom * atom = m_ineq_atoms.insert_if_not_there(tmp_atom); - CTRACE("nlsat_table_bug", tmp_atom != atom, ineq_atom::hash_proc h; - tout << "mk_ineq_atom hash: " << h(tmp_atom) << "\n"; display(tout, *tmp_atom, m_display_var) << "\n";); - CTRACE("nlsat_table_bug", atom->max_var() != max, display(tout << "nonmax: ", *atom, m_display_var) << "\n";); - SASSERT(atom->max_var() == max); - is_new = (atom == tmp_atom); - if (is_new) { - for (unsigned i = 0; i < sz; i++) { - m_pm.inc_ref(atom->p(i)); - } - } - else { - deallocate(tmp_atom); - } - return atom; - } - - bool_var mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify = false) { - bool is_new = false; - ineq_atom* atom = mk_ineq_atom(k, sz, ps, is_even, is_new, simplify); - if (!is_new) { - return atom->bvar(); - } - else { - bool_var b = mk_bool_var_core(); - m_atoms[b] = atom; - atom->m_bool_var = b; - TRACE("nlsat_verbose", display(tout << "create: b" << atom->m_bool_var << " ", *atom) << "\n";); - return b; - } - } - - literal mk_ineq_literal(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify = false) { - SASSERT(k == atom::LT || k == atom::GT || k == atom::EQ); - bool is_const = true; - polynomial::manager::scoped_numeral cnst(m_pm.m()); - m_pm.m().set(cnst, 1); - for (unsigned i = 0; i < sz; ++i) { - if (m_pm.is_const(ps[i])) { - if (m_pm.is_zero(ps[i])) { - m_pm.m().set(cnst, 0); - is_const = true; - break; - } - auto const& c = m_pm.coeff(ps[i], 0); - m_pm.m().mul(cnst, c, cnst); - if (is_even[i] && m_pm.m().is_neg(c)) { - m_pm.m().neg(cnst); - } - } - else { - is_const = false; - } - } - if (is_const) { - if (m_pm.m().is_pos(cnst) && k == atom::GT) return true_literal; - if (m_pm.m().is_neg(cnst) && k == atom::LT) return true_literal; - if (m_pm.m().is_zero(cnst) && k == atom::EQ) return true_literal; - return false_literal; - } - return literal(mk_ineq_atom(k, sz, ps, is_even, simplify), false); - } - - bool_var mk_root_atom(atom::kind k, var x, unsigned i, poly * p) { - polynomial_ref p1(m_pm), uniq_p(m_pm); - p1 = m_pm.flip_sign_if_lm_neg(p); // flipping the sign of the polynomial will not change its roots. - uniq_p = m_cache.mk_unique(p1); - TRACE("nlsat_solver", tout << x << " " << p1 << " " << uniq_p << "\n";); - SASSERT(i > 0); - SASSERT(x >= max_var(p)); - SASSERT(k == atom::ROOT_LT || k == atom::ROOT_GT || k == atom::ROOT_EQ || k == atom::ROOT_LE || k == atom::ROOT_GE); - - void * mem = m_allocator.allocate(sizeof(root_atom)); - root_atom * new_atom = new (mem) root_atom(k, x, i, uniq_p); - root_atom * old_atom = m_root_atoms.insert_if_not_there(new_atom); - SASSERT(old_atom->max_var() == x); - if (old_atom != new_atom) { - deallocate(new_atom); - return old_atom->bvar(); - } - bool_var b = mk_bool_var_core(); - m_atoms[b] = new_atom; - new_atom->m_bool_var = b; - m_pm.inc_ref(new_atom->p()); - return b; - } - - void attach_clause(clause & cls) { - var x = max_var(cls); - if (x != null_var) { - m_watches[x].push_back(&cls); - } - else { - bool_var b = max_bvar(cls); - m_bwatches[b].push_back(&cls); - } - } - - void deattach_clause(clause & cls) { - var x = max_var(cls); - if (x != null_var) { - m_watches[x].erase(&cls); - } - else { - bool_var b = max_bvar(cls); - m_bwatches[b].erase(&cls); - } - } - - void deallocate(clause * cls) { - size_t obj_sz = clause::get_obj_size(cls->size()); - cls->~clause(); - m_allocator.deallocate(obj_sz, cls); - } - - void del_clause(clause * cls) { - deattach_clause(*cls); - m_cid_gen.recycle(cls->id()); - unsigned sz = cls->size(); - for (unsigned i = 0; i < sz; i++) - dec_ref((*cls)[i]); - _assumption_set a = static_cast<_assumption_set>(cls->assumptions()); - dec_ref(a); - deallocate(cls); - } - - void del_clause(clause * cls, clause_vector& clauses) { - clauses.erase(cls); - del_clause(cls); - } - - void del_clauses(ptr_vector & cs) { - for (clause* cp : cs) - del_clause(cp); - cs.reset(); - } - - void del_clauses() { - del_clauses(m_clauses); - del_clauses(m_learned); - del_clauses(m_valids); - } - - // We use a simple heuristic to sort literals - // - bool literals < arith literals - // - sort literals based on max_var - // - sort literal with the same max_var using degree - // break ties using the fact that ineqs are usually cheaper to process than eqs. - struct lit_lt { - imp & m; - lit_lt(imp & _m):m(_m) {} - - bool operator()(literal l1, literal l2) const { - atom * a1 = m.m_atoms[l1.var()]; - atom * a2 = m.m_atoms[l2.var()]; - if (a1 == nullptr && a2 == nullptr) - return l1.index() < l2.index(); - if (a1 == nullptr) - return true; - if (a2 == nullptr) - return false; - var x1 = a1->max_var(); - var x2 = a2->max_var(); - if (x1 < x2) - return true; - if (x1 > x2) - return false; - SASSERT(x1 == x2); - unsigned d1 = m.degree(a1); - unsigned d2 = m.degree(a2); - if (d1 < d2) - return true; - if (d1 > d2) - return false; - if (!a1->is_eq() && a2->is_eq()) - return true; - if (a1->is_eq() && !a2->is_eq()) - return false; - return l1.index() < l2.index(); - } - }; - - class scoped_bool_vars { - imp& s; - svector vec; - public: - scoped_bool_vars(imp& s):s(s) {} - ~scoped_bool_vars() { - for (bool_var v : vec) { - s.dec_ref(v); - } - } - void push_back(bool_var v) { - s.inc_ref(v); - vec.push_back(v); - } - bool_var const* begin() const { return vec.begin(); } - bool_var const* end() const { return vec.end(); } - bool_var operator[](bool_var v) const { return vec[v]; } - }; - - void check_lemma(unsigned n, literal const* cls, bool is_valid, assumption_set a) { - TRACE("nlsat", display(tout << "check lemma: ", n, cls) << "\n"; - display(tout);); - IF_VERBOSE(2, display(verbose_stream() << "check lemma " << (is_valid?"valid: ":"consequence: "), n, cls) << "\n"); - for (clause* c : m_learned) IF_VERBOSE(1, display(verbose_stream() << "lemma: ", *c) << "\n"); - scoped_suspend_rlimit _limit(m_rlimit); - ctx c(m_rlimit, m_ctx.m_params, m_ctx.m_incremental); - solver solver2(c); - imp& checker = *(solver2.m_imp); - checker.m_check_lemmas = false; - checker.m_log_lemmas = false; - checker.m_inline_vars = false; - - auto pconvert = [&](poly* p) { - return convert(m_pm, p, checker.m_pm); - }; - - // need to translate Boolean variables and literals - scoped_bool_vars tr(checker); - for (var x = 0; x < m_is_int.size(); ++x) { - checker.register_var(x, is_int(x)); - } - bool_var bv = 0; - tr.push_back(bv); - for (bool_var b = 1; b < m_atoms.size(); ++b) { - atom* a = m_atoms[b]; - if (a == nullptr) { - bv = checker.mk_bool_var(); - } - else if (a->is_ineq_atom()) { - ineq_atom& ia = *to_ineq_atom(a); - unsigned sz = ia.size(); - polynomial_ref_vector ps(checker.m_pm); - bool_vector is_even; - for (unsigned i = 0; i < sz; ++i) { - ps.push_back(pconvert(ia.p(i))); - is_even.push_back(ia.is_even(i)); - } - bv = checker.mk_ineq_atom(ia.get_kind(), sz, ps.data(), is_even.data()); - } - else if (a->is_root_atom()) { - root_atom& r = *to_root_atom(a); - if (r.x() >= max_var(r.p())) { - // permutation may be reverted after check completes, - // but then root atoms are not used in lemmas. - bv = checker.mk_root_atom(r.get_kind(), r.x(), r.i(), pconvert(r.p())); - } - } - else { - UNREACHABLE(); - } - tr.push_back(bv); - } - if (!is_valid) { - for (clause* c : m_clauses) { - if (!a && c->assumptions()) { - continue; - } - literal_vector lits; - for (literal lit : *c) { - lits.push_back(literal(tr[lit.var()], lit.sign())); - } - checker.mk_external_clause(lits.size(), lits.data(), nullptr); - } - } - for (unsigned i = 0; i < n; ++i) { - literal lit = cls[i]; - literal nlit(tr[lit.var()], !lit.sign()); - checker.mk_external_clause(1, &nlit, nullptr); - } - lbool r = checker.check(); - if (r == l_true) { - for (bool_var b : tr) { - literal lit(b, false); - IF_VERBOSE(0, checker.display(verbose_stream(), lit) << " := " << checker.value(lit) << "\n"); - TRACE("nlsat", checker.display(tout, lit) << " := " << checker.value(lit) << "\n";); - } - for (clause* c : m_learned) { - bool found = false; - for (literal lit: *c) { - literal tlit(tr[lit.var()], lit.sign()); - found |= checker.value(tlit) == l_true; - } - if (!found) { - IF_VERBOSE(0, display(verbose_stream() << "violdated clause: ", *c) << "\n"); - TRACE("nlsat", display(tout << "violdated clause: ", *c) << "\n";); - } - } - for (clause* c : m_valids) { - bool found = false; - for (literal lit: *c) { - literal tlit(tr[lit.var()], lit.sign()); - found |= checker.value(tlit) == l_true; - } - if (!found) { - IF_VERBOSE(0, display(verbose_stream() << "violdated tautology clause: ", *c) << "\n"); - TRACE("nlsat", display(tout << "violdated tautology clause: ", *c) << "\n";); - } - } - throw default_exception("lemma did not check"); - UNREACHABLE(); - } - } - - void log_lemma(std::ostream& out, clause const& cls) { - log_lemma(out, cls.size(), cls.data(), false); - } - - void log_lemma(std::ostream& out, unsigned n, literal const* cls, bool is_valid) { - ++m_lemma_count; - out << "(set-logic NRA)\n"; - if (is_valid) { - display_smt2_bool_decls(out); - display_smt2_arith_decls(out); - } - else - display_smt2(out); - for (unsigned i = 0; i < n; ++i) - display_smt2(out << "(assert ", ~cls[i]) << ")\n"; - display(out << "(echo \"#" << m_lemma_count << " ", n, cls) << "\")\n"; - out << "(check-sat)\n(reset)\n"; - - TRACE("nlsat", display(tout << "(echo \"#" << m_lemma_count << " ", n, cls) << "\")\n"); - } - - clause * mk_clause_core(unsigned num_lits, literal const * lits, bool learned, _assumption_set a) { - SASSERT(num_lits > 0); - unsigned cid = m_cid_gen.mk(); - void * mem = m_allocator.allocate(clause::get_obj_size(num_lits)); - clause * cls = new (mem) clause(cid, num_lits, lits, learned, a); - for (unsigned i = 0; i < num_lits; i++) - inc_ref(lits[i]); - inc_ref(a); - return cls; - } - - clause * mk_clause(unsigned num_lits, literal const * lits, bool learned, _assumption_set a) { - if (num_lits == 0) { - num_lits = 1; - lits = &false_literal; - } - SASSERT(num_lits > 0); - clause * cls = mk_clause_core(num_lits, lits, learned, a); - TRACE("nlsat_sort", display(tout << "mk_clause:\n", *cls) << "\n";); - std::sort(cls->begin(), cls->end(), lit_lt(*this)); - TRACE("nlsat", display(tout << " after sort:\n", *cls) << "\n";); - if (learned && m_log_lemmas) { - log_lemma(verbose_stream(), *cls); - } - if (learned && m_check_lemmas && false) { - check_lemma(cls->size(), cls->data(), false, cls->assumptions()); - } - if (learned) - m_learned.push_back(cls); - else - m_clauses.push_back(cls); - attach_clause(*cls); - return cls; - } - - void mk_external_clause(unsigned num_lits, literal const * lits, assumption a) { - _assumption_set as = nullptr; - if (a != nullptr) - as = m_asm.mk_leaf(a); - if (num_lits == 0) { - num_lits = 1; - lits = &false_literal; - } - mk_clause(num_lits, lits, false, as); - } - - // ----------------------- - // - // Search - // - // ----------------------- - - void save_assign_trail(bool_var b) { - m_trail.push_back(trail(b, bvar_assignment())); - } - - void save_set_updt_trail(interval_set * old_set) { - m_trail.push_back(trail(old_set)); - } - - void save_updt_eq_trail(atom * old_eq) { - m_trail.push_back(trail(old_eq)); - } - - void save_new_stage_trail() { - m_trail.push_back(trail(true, stage())); - } - - void save_new_level_trail() { - m_trail.push_back(trail(false, stage())); - } - - void undo_bvar_assignment(bool_var b) { - m_bvalues[b] = l_undef; - m_levels[b] = UINT_MAX; - del_jst(m_allocator, m_justifications[b]); - m_justifications[b] = null_justification; - if (m_atoms[b] == nullptr && b < m_bk) - m_bk = b; - } - - void undo_set_updt(interval_set * old_set) { - if (m_xk == null_var) - return; - var x = m_xk; - if (x < m_infeasible.size()) { - m_ism.dec_ref(m_infeasible[x]); - m_infeasible[x] = old_set; - } - } - - void undo_new_stage() { - if (m_xk == 0) { - m_xk = null_var; - } - else if (m_xk != null_var) { - m_xk--; - m_assignment.reset(m_xk); - } - } - - void undo_new_level() { - SASSERT(m_scope_lvl > 0); - m_scope_lvl--; - m_evaluator.pop(1); - } - - void undo_updt_eq(atom * a) { - if (m_var2eq.size() > m_xk) - m_var2eq[m_xk] = a; - } - - template - void undo_until(Predicate const & pred) { - while (pred() && !m_trail.empty()) { - trail & t = m_trail.back(); - switch (t.m_kind) { - case trail::BVAR_ASSIGNMENT: - undo_bvar_assignment(t.m_b); - break; - case trail::INFEASIBLE_UPDT: - undo_set_updt(t.m_old_set); - break; - case trail::NEW_STAGE: - undo_new_stage(); - break; - case trail::NEW_LEVEL: - undo_new_level(); - break; - case trail::UPDT_EQ: - undo_updt_eq(t.m_old_eq); - break; - default: - break; - } - m_trail.pop_back(); - } - } - - struct size_pred { - svector & m_trail; - unsigned m_old_size; - size_pred(svector & trail, unsigned old_size):m_trail(trail), m_old_size(old_size) {} - bool operator()() const { return m_trail.size() > m_old_size; } - }; - - // Keep undoing until trail has the given size - void undo_until_size(unsigned old_size) { - SASSERT(m_trail.size() >= old_size); - undo_until(size_pred(m_trail, old_size)); - } - - struct stage_pred { - var const & m_xk; - var m_target; - stage_pred(var const & xk, var target):m_xk(xk), m_target(target) {} - bool operator()() const { return m_xk != m_target; } - }; - - // Keep undoing until stage is new_xk - void undo_until_stage(var new_xk) { - undo_until(stage_pred(m_xk, new_xk)); - } - - struct level_pred { - unsigned const & m_scope_lvl; - unsigned m_new_lvl; - level_pred(unsigned const & scope_lvl, unsigned new_lvl):m_scope_lvl(scope_lvl), m_new_lvl(new_lvl) {} - bool operator()() const { return m_scope_lvl > m_new_lvl; } - }; - - // Keep undoing until level is new_lvl - void undo_until_level(unsigned new_lvl) { - undo_until(level_pred(m_scope_lvl, new_lvl)); - } - - struct unassigned_pred { - bool_var m_b; - svector const & m_bvalues; - unassigned_pred(svector const & bvalues, bool_var b): - m_b(b), - m_bvalues(bvalues) {} - bool operator()() const { return m_bvalues[m_b] != l_undef; } - }; - - // Keep undoing until b is unassigned - void undo_until_unassigned(bool_var b) { - undo_until(unassigned_pred(m_bvalues, b)); - SASSERT(m_bvalues[b] == l_undef); - } - - struct true_pred { - bool operator()() const { return true; } - }; - - void undo_until_empty() { - undo_until(true_pred()); - } - - /** - \brief Create a new scope level - */ - void new_level() { - m_evaluator.push(); - m_scope_lvl++; - save_new_level_trail(); - } - - /** - \brief Return the value of the given literal that was assigned by the search - engine. - */ - lbool assigned_value(literal l) const { - bool_var b = l.var(); - if (l.sign()) - return ~m_bvalues[b]; - else - return m_bvalues[b]; - } - - /** - \brief Assign literal using the given justification - */ - void assign(literal l, justification j) { - TRACE("nlsat_assign", - display(tout << "assigning literal: ", l); - display(tout << " <- ", j);); - - SASSERT(assigned_value(l) == l_undef); - SASSERT(j != null_justification); - SASSERT(!j.is_null()); - if (j.is_decision()) - m_stats.m_decisions++; - else - m_stats.m_propagations++; - bool_var b = l.var(); - m_bvalues[b] = to_lbool(!l.sign()); - m_levels[b] = m_scope_lvl; - m_justifications[b] = j; - save_assign_trail(b); - updt_eq(b, j); - TRACE("nlsat_assign", tout << "b" << b << " -> " << m_bvalues[b] << "\n";); - } - - /** - \brief Create a "case-split" - */ - void decide(literal l) { - new_level(); - assign(l, decided_justification); - } - - /** - \brief Return the value of a literal as defined in Dejan and Leo's paper. - */ - lbool value(literal l) { - lbool val = assigned_value(l); - if (val != l_undef) { - TRACE("nlsat_verbose", display(tout << " assigned value " << val << " for ", l) << "\n";); - return val; - } - bool_var b = l.var(); - atom * a = m_atoms[b]; - if (a == nullptr) { - TRACE("nlsat_verbose", display(tout << " no atom for ", l) << "\n";); - return l_undef; - } - var max = a->max_var(); - if (!m_assignment.is_assigned(max)) { - TRACE("nlsat_verbose", display(tout << " maximal variable not assigned ", l) << "\n";); - return l_undef; - } - val = to_lbool(m_evaluator.eval(a, l.sign())); - TRACE("nlsat_verbose", display(tout << " evaluated value " << val << " for ", l) << "\n";); - TRACE("value_bug", tout << "value of: "; display(tout, l); tout << " := " << val << "\n"; - tout << "xk: " << m_xk << ", a->max_var(): " << a->max_var() << "\n"; - display_assignment(tout);); - return val; - } - - /** - \brief Return true if the given clause is already satisfied in the current partial interpretation. - */ - bool is_satisfied(clause const & cls) const { - for (literal l : cls) { - if (const_cast(this)->value(l) == l_true) { - TRACE("value_bug:", tout << l << " := true\n";); - return true; - } - } - return false; - } - - /** - \brief Return true if the given clause is false in the current partial interpretation. - */ - bool is_inconsistent(unsigned sz, literal const * cls) { - for (unsigned i = 0; i < sz; i++) { - if (value(cls[i]) != l_false) { - TRACE("is_inconsistent", tout << "literal is not false:\n"; display(tout, cls[i]); tout << "\n";); - return false; - } - } - return true; - } - - /** - \brief Process a clauses that contains only Boolean literals. - */ - bool process_boolean_clause(clause const & cls) { - SASSERT(m_xk == null_var); - unsigned num_undef = 0; - unsigned first_undef = UINT_MAX; - unsigned sz = cls.size(); - for (unsigned i = 0; i < sz; i++) { - literal l = cls[i]; - SASSERT(m_atoms[l.var()] == nullptr); - SASSERT(value(l) != l_true); - if (value(l) == l_false) - continue; - SASSERT(value(l) == l_undef); - num_undef++; - if (first_undef == UINT_MAX) - first_undef = i; - } - if (num_undef == 0) - return false; - SASSERT(first_undef != UINT_MAX); - if (num_undef == 1) - assign(cls[first_undef], mk_clause_jst(&cls)); // unit clause - else - decide(cls[first_undef]); - return true; - } - - /** - \brief assign l to true, because l + (justification of) s is infeasible in RCF in the current interpretation. - */ - literal_vector core; - ptr_vector clauses; - void R_propagate(literal l, interval_set const * s, bool include_l = true) { - m_ism.get_justifications(s, core, clauses); - if (include_l) - core.push_back(~l); - auto j = mk_lazy_jst(m_allocator, core.size(), core.data(), clauses.size(), clauses.data()); - TRACE("nlsat_resolve", display(tout, j); display_eval(tout << "evaluated:", j)); - assign(l, j); - SASSERT(value(l) == l_true); - } - - /** - \brief m_infeasible[m_xk] <- m_infeasible[m_xk] Union s - */ - void updt_infeasible(interval_set const * s) { - SASSERT(m_xk != null_var); - interval_set * xk_set = m_infeasible[m_xk]; - save_set_updt_trail(xk_set); - interval_set_ref new_set(m_ism); - TRACE("nlsat_inf_set", tout << "updating infeasible set\n"; m_ism.display(tout, xk_set) << "\n"; m_ism.display(tout, s) << "\n";); - new_set = m_ism.mk_union(s, xk_set); - TRACE("nlsat_inf_set", tout << "new infeasible set:\n"; m_ism.display(tout, new_set) << "\n";); - SASSERT(!m_ism.is_full(new_set)); - m_ism.inc_ref(new_set); - m_infeasible[m_xk] = new_set; - } - - /** - \brief Update m_var2eq mapping. - */ - void updt_eq(bool_var b, justification j) { - if (!m_simplify_cores) - return; - if (m_bvalues[b] != l_true) - return; - atom * a = m_atoms[b]; - if (a == nullptr || a->get_kind() != atom::EQ || to_ineq_atom(a)->size() > 1 || to_ineq_atom(a)->is_even(0)) - return; - switch (j.get_kind()) { - case justification::CLAUSE: - if (j.get_clause()->assumptions() != nullptr) return; - break; - case justification::LAZY: - if (j.get_lazy()->num_clauses() > 0) return; - if (j.get_lazy()->num_lits() > 0) return; - break; - default: - break; - } - var x = m_xk; - SASSERT(a->max_var() == x); - SASSERT(x != null_var); - if (m_var2eq[x] != 0 && degree(m_var2eq[x]) <= degree(a)) - return; // we only update m_var2eq if the new equality has smaller degree - TRACE("nlsat_simplify_core", tout << "Saving equality for "; m_display_var(tout, x) << " (x" << x << ") "; - tout << "scope-lvl: " << scope_lvl() << "\n"; display(tout, literal(b, false)) << "\n"; - display(tout, j); - ); - save_updt_eq_trail(m_var2eq[x]); - m_var2eq[x] = a; - } - - /** - \brief Process a clause that contains nonlinear arithmetic literals - - If satisfy_learned is true, then learned clauses are satisfied even if m_lazy > 0 - */ - bool process_arith_clause(clause const & cls, bool satisfy_learned) { - if (!satisfy_learned && m_lazy >= 2 && cls.is_learned()) { - TRACE("nlsat", tout << "skip learned\n";); - return true; // ignore lemmas in super lazy mode - } - SASSERT(m_xk == max_var(cls)); - unsigned num_undef = 0; // number of undefined literals - unsigned first_undef = UINT_MAX; // position of the first undefined literal - interval_set_ref first_undef_set(m_ism); // infeasible region of the first undefined literal - interval_set * xk_set = m_infeasible[m_xk]; // current set of infeasible interval for current variable - SASSERT(!m_ism.is_full(xk_set)); - for (unsigned idx = 0; idx < cls.size(); ++idx) { - literal l = cls[idx]; - checkpoint(); - if (value(l) == l_false) - continue; - if (value(l) == l_true) - return true; // could happen if clause is a tautology - CTRACE("nlsat", max_var(l) != m_xk || value(l) != l_undef, display(tout); - tout << "xk: " << m_xk << ", max_var(l): " << max_var(l) << ", l: "; display(tout, l) << "\n"; - display(tout, cls) << "\n";); - SASSERT(value(l) == l_undef); - SASSERT(max_var(l) == m_xk); - bool_var b = l.var(); - atom * a = m_atoms[b]; - SASSERT(a != nullptr); - interval_set_ref curr_set(m_ism); - curr_set = m_evaluator.infeasible_intervals(a, l.sign(), &cls); - TRACE("nlsat_inf_set", tout << "infeasible set for literal: "; display(tout, l); tout << "\n"; m_ism.display(tout, curr_set); tout << "\n"; - display(tout, cls) << "\n";); - if (m_ism.is_empty(curr_set)) { - TRACE("nlsat_inf_set", tout << "infeasible set is empty, found literal\n";); - R_propagate(l, nullptr); - SASSERT(is_satisfied(cls)); - return true; - } - if (m_ism.is_full(curr_set)) { - TRACE("nlsat_inf_set", tout << "infeasible set is R, skip literal\n";); - R_propagate(~l, nullptr); - continue; - } - if (m_ism.subset(curr_set, xk_set)) { - TRACE("nlsat_inf_set", tout << "infeasible set is a subset of current set, found literal\n";); - R_propagate(l, xk_set); - return true; - } - interval_set_ref tmp(m_ism); - tmp = m_ism.mk_union(curr_set, xk_set); - if (m_ism.is_full(tmp)) { - TRACE("nlsat_inf_set", tout << "infeasible set + current set = R, skip literal\n"; - display(tout, cls) << "\n"; - m_ism.display(tout, tmp); tout << "\n"; - ); - R_propagate(~l, tmp, false); - continue; - } - num_undef++; - if (first_undef == UINT_MAX) { - first_undef = idx; - first_undef_set = curr_set; - } - } - TRACE("nlsat_inf_set", tout << "num_undef: " << num_undef << "\n";); - if (num_undef == 0) - return false; - SASSERT(first_undef != UINT_MAX); - if (num_undef == 1) { - // unit clause - assign(cls[first_undef], mk_clause_jst(&cls)); - updt_infeasible(first_undef_set); - } - else if ( satisfy_learned || - !cls.is_learned() /* must always satisfy input clauses */ || - m_lazy == 0 /* if not in lazy mode, we also satiffy lemmas */) { - decide(cls[first_undef]); - updt_infeasible(first_undef_set); - } - else { - TRACE("nlsat_lazy", tout << "skipping clause, satisfy_learned: " << satisfy_learned << ", cls.is_learned(): " << cls.is_learned() - << ", lazy: " << m_lazy << "\n";); - } - return true; - } - - /** - \brief Try to satisfy the given clause. Return true if succeeded. - - If satisfy_learned is true, then (arithmetic) learned clauses are satisfied even if m_lazy > 0 - */ - bool process_clause(clause const & cls, bool satisfy_learned) { - if (is_satisfied(cls)) - return true; - if (m_xk == null_var) - return process_boolean_clause(cls); - else - return process_arith_clause(cls, satisfy_learned); - } - - /** - \brief Try to satisfy the given "set" of clauses. - Return 0, if the set was satisfied, or the violating clause otherwise - */ - clause * process_clauses(clause_vector const & cs) { - for (clause* c : cs) { - if (!process_clause(*c, false)) - return c; - } - return nullptr; // succeeded - } - - /** - \brief Make sure m_bk is the first unassigned pure Boolean variable. - Set m_bk == null_bool_var if there is no unassigned pure Boolean variable. - */ - void peek_next_bool_var() { - while (m_bk < m_atoms.size()) { - if (!m_dead[m_bk] && m_atoms[m_bk] == nullptr && m_bvalues[m_bk] == l_undef) { - return; - } - m_bk++; - } - m_bk = null_bool_var; - } - - /** - \brief Create a new stage. See Dejan and Leo's paper. - */ - void new_stage() { - m_stats.m_stages++; - save_new_stage_trail(); - if (m_xk == null_var) - m_xk = 0; - else - m_xk++; - } - - /** - \brief Assign m_xk - */ - void select_witness() { - scoped_anum w(m_am); - SASSERT(!m_ism.is_full(m_infeasible[m_xk])); - m_ism.pick_in_complement(m_infeasible[m_xk], is_int(m_xk), w, m_randomize); - TRACE("nlsat", - tout << "infeasible intervals: "; m_ism.display(tout, m_infeasible[m_xk]); tout << "\n"; - tout << "assigning "; m_display_var(tout, m_xk) << "(x" << m_xk << ") -> " << w << "\n";); - TRACE("nlsat_root", tout << "value as root object: "; m_am.display_root(tout, w); tout << "\n";); - if (!m_am.is_rational(w)) - m_stats.m_irrational_assignments++; - m_assignment.set_core(m_xk, w); - } - - - - bool is_satisfied() { - if (m_bk == null_bool_var && m_xk >= num_vars()) { - TRACE("nlsat", tout << "found model\n"; display_assignment(tout);); - fix_patch(); - SASSERT(check_satisfied(m_clauses)); - return true; // all variables were assigned, and all clauses were satisfied. - } - else { - return false; - } - } - - - /** - \brief main procedure - */ - lbool search() { - TRACE("nlsat", tout << "starting search...\n"; display(tout); tout << "\nvar order:\n"; display_vars(tout);); - TRACE("nlsat_proof", tout << "ASSERTED\n"; display(tout);); - TRACE("nlsat_proof_sk", tout << "ASSERTED\n"; display_abst(tout);); - TRACE("nlsat_mathematica", display_mathematica(tout);); - TRACE("nlsat", display_smt2(tout);); - m_bk = 0; - m_xk = null_var; - - while (true) { - if (should_reorder()) - do_reorder(); - -#if 0 - if (should_gc()) - do_gc(); -#endif - - if (should_simplify()) - do_simplify(); - - CASSERT("nlsat", check_satisfied()); - if (m_xk == null_var) { - peek_next_bool_var(); - if (m_bk == null_bool_var) - new_stage(); // move to arith vars - } - else { - new_stage(); // peek next arith var - } - TRACE("nlsat_bug", tout << "xk: x" << m_xk << " bk: b" << m_bk << "\n";); - if (is_satisfied()) { - return l_true; - } - while (true) { - TRACE("nlsat_verbose", tout << "processing variable "; - if (m_xk != null_var) { - m_display_var(tout, m_xk); tout << " " << m_watches[m_xk].size(); - } - else { - tout << m_bwatches[m_bk].size() << " boolean b" << m_bk; - } - tout << "\n";); - checkpoint(); - clause * conflict_clause; - if (m_xk == null_var) - conflict_clause = process_clauses(m_bwatches[m_bk]); - else - conflict_clause = process_clauses(m_watches[m_xk]); - if (conflict_clause == nullptr) - break; - if (!resolve(*conflict_clause)) - return l_false; - if (m_stats.m_conflicts >= m_max_conflicts) - return l_undef; - log(); - } - - if (m_xk == null_var) { - if (m_bvalues[m_bk] == l_undef) { - decide(literal(m_bk, true)); - m_bk++; - } - } - else { - select_witness(); - } - } - } - - void gc() { - if (m_learned.size() <= 4*m_clauses.size()) - return; - reset_watches(); - reinit_cache(); - unsigned j = 0; - for (unsigned i = 0; i < m_learned.size(); ++i) { - auto cls = m_learned[i]; - if (i - j < m_clauses.size() && cls->size() > 1 && !cls->is_active()) - del_clause(cls); - else { - m_learned[j++] = cls; - cls->set_active(false); - } - } - m_learned.shrink(j); - reattach_arith_clauses(m_clauses); - reattach_arith_clauses(m_learned); - } - - - bool should_gc() { - return m_learned.size() > 10 * m_clauses.size(); - } - - void do_gc() { - undo_to_base(); - gc(); - } - - void undo_to_base() { - init_search(); - m_bk = 0; - m_xk = null_var; - } - - unsigned m_restart_threshold = 10000; - bool should_reorder() { - return m_stats.m_conflicts > 0 && m_stats.m_conflicts % m_restart_threshold == 0; - } - - void do_reorder() { - undo_to_base(); - m_stats.m_restarts++; - m_stats.m_conflicts++; - if (m_reordered) - restore_order(); - apply_reorder(); - } - - bool m_did_simplify = false; - bool should_simplify() { - return - !m_did_simplify && m_inline_vars && - !m_incremental && m_stats.m_conflicts > 100; - } - - void do_simplify() { - undo_to_base(); - m_did_simplify = true; - m_simplify(); - } - - unsigned m_next_conflict = 100; - void log() { - if (m_stats.m_conflicts != 1 && m_stats.m_conflicts < m_next_conflict) - return; - m_next_conflict += 100; - IF_VERBOSE(2, verbose_stream() << "(nlsat :conflicts " << m_stats.m_conflicts - << " :decisions " << m_stats.m_decisions - << " :propagations " << m_stats.m_propagations - << " :clauses " << m_clauses.size() - << " :learned " << m_learned.size() << ")\n"); - } - - - lbool search_check() { - lbool r = l_undef; - m_stats.m_conflicts = 0; - m_stats.m_restarts = 0; - m_next_conflict = 0; - while (true) { - r = search(); - if (r != l_true) - break; - ++m_stats.m_restarts; - vector> bounds; - - for (var x = 0; x < num_vars(); x++) { - if (is_int(x) && m_assignment.is_assigned(x) && !m_am.is_int(m_assignment.value(x))) { - scoped_anum v(m_am), vlo(m_am); - v = m_assignment.value(x); - rational lo; - m_am.int_lt(v, vlo); - if (!m_am.is_int(vlo)) - continue; - m_am.to_rational(vlo, lo); - // derive tight bounds. - while (true) { - lo++; - if (!m_am.gt(v, lo.to_mpq())) { - lo--; - break; - } - } - bounds.push_back(std::make_pair(x, lo)); - } - } - if (bounds.empty()) - break; - - gc(); - if (m_stats.m_restarts % 10 == 0) { - if (m_reordered) - restore_order(); - apply_reorder(); - } - - init_search(); - IF_VERBOSE(2, verbose_stream() << "(nlsat-b&b :conflicts " << m_stats.m_conflicts - << " :decisions " << m_stats.m_decisions - << " :propagations " << m_stats.m_propagations - << " :clauses " << m_clauses.size() - << " :learned " << m_learned.size() << ")\n"); - for (auto const& b : bounds) { - var x = b.first; - rational lo = b.second; - rational hi = lo + 1; // rational::one(); - bool is_even = false; - polynomial_ref p(m_pm); - rational one(1); - m_lemma.reset(); - p = m_pm.mk_linear(1, &one, &x, -lo); - poly* p1 = p.get(); - m_lemma.push_back(~mk_ineq_literal(atom::GT, 1, &p1, &is_even)); - p = m_pm.mk_linear(1, &one, &x, -hi); - poly* p2 = p.get(); - m_lemma.push_back(~mk_ineq_literal(atom::LT, 1, &p2, &is_even)); - - // perform branch and bound - clause * cls = mk_clause(m_lemma.size(), m_lemma.data(), true, nullptr); - IF_VERBOSE(4, display(verbose_stream(), *cls) << "\n"); - if (cls) { - TRACE("nlsat", display(tout << "conflict " << lo << " " << hi, *cls); tout << "\n";); - } - } - } - return r; - } - - bool m_reordered = false; - - void apply_reorder() { - m_reordered = false; - if (!can_reorder()) - ; - else if (m_random_order) { - shuffle_vars(); - m_reordered = true; - } - else if (m_reorder) { - heuristic_reorder(); - m_reordered = true; - } - } - - lbool check() { - TRACE("nlsat_smt2", display_smt2(tout);); - TRACE("nlsat_fd", tout << "is_full_dimensional: " << is_full_dimensional() << "\n";); - init_search(); - m_explain.set_full_dimensional(is_full_dimensional()); - - apply_reorder(); - -#if 0 - if (!m_incremental && m_inline_vars) { - if (!m_simplify()) - return l_false; - } -#endif - IF_VERBOSE(3, verbose_stream() << "search\n"); - sort_watched_clauses(); - lbool r = search_check(); - CTRACE("nlsat_model", r == l_true, tout << "model before restore order\n"; display_assignment(tout);); - if (m_reordered) - restore_order(); - CTRACE("nlsat_model", r == l_true, tout << "model\n"; display_assignment(tout);); - CTRACE("nlsat", r == l_false, display(tout << "unsat\n");); - SASSERT(r != l_true || check_satisfied(m_clauses)); - return r; - } - - void init_search() { - undo_until_empty(); - while (m_scope_lvl > 0) { - undo_new_level(); - } - m_xk = null_var; - for (unsigned i = 0; i < m_bvalues.size(); ++i) { - m_bvalues[i] = l_undef; - } - m_assignment.reset(); - } - - lbool check(literal_vector& assumptions) { - literal_vector result; - unsigned sz = assumptions.size(); - literal const* ptr = assumptions.data(); - for (unsigned i = 0; i < sz; ++i) { - mk_external_clause(1, ptr+i, (assumption)(ptr+i)); - } - display_literal_assumption dla(*this, assumptions); - scoped_display_assumptions _scoped_display(*this, dla); - lbool r = check(); - - if (r == l_false) { - // collect used literals from m_lemma_assumptions - vector deps; - get_core(deps); - for (unsigned i = 0; i < deps.size(); ++i) { - literal const* lp = (literal const*)(deps[i]); - if (ptr <= lp && lp < ptr + sz) { - result.push_back(*lp); - } - } - } - collect(assumptions, m_clauses); - collect(assumptions, m_learned); - del_clauses(m_valids); - if (m_check_lemmas) { - for (clause* c : m_learned) { - check_lemma(c->size(), c->data(), false, nullptr); - } - } - -#if 0 - for (clause* c : m_learned) { - IF_VERBOSE(0, display(verbose_stream() << "KEEP: ", c->size(), c->c_ptr()) << "\n"); - } -#endif - assumptions.reset(); - assumptions.append(result); - return r; - } - - void get_core(vector& deps) { - m_asm.linearize(m_lemma_assumptions.get(), deps); - } - - void collect(literal_vector const& assumptions, clause_vector& clauses) { - unsigned j = 0; - for (clause * c : clauses) { - if (collect(assumptions, *c)) { - del_clause(c); - } - else { - clauses[j++] = c; - } - } - clauses.shrink(j); - } - - bool collect(literal_vector const& assumptions, clause const& c) { - unsigned sz = assumptions.size(); - literal const* ptr = assumptions.data(); - _assumption_set asms = static_cast<_assumption_set>(c.assumptions()); - if (asms == nullptr) { - return false; - } - vector deps; - m_asm.linearize(asms, deps); - for (auto dep : deps) { - if (ptr <= dep && dep < ptr + sz) { - return true; - } - } - return false; - } - - // ----------------------- - // - // Conflict Resolution - // - // ----------------------- - svector m_marks; // bool_var -> bool temp mark used during conflict resolution - unsigned m_num_marks; - scoped_literal_vector m_lemma; - scoped_literal_vector m_lazy_clause; - assumption_set_ref m_lemma_assumptions; // assumption tracking - - // Conflict resolution invariant: a marked literal is in m_lemma or on the trail stack. - - bool check_marks() { - for (unsigned m : m_marks) { - (void)m; - SASSERT(m == 0); - } - return true; - } - - unsigned scope_lvl() const { return m_scope_lvl; } - - bool is_marked(bool_var b) const { return m_marks.get(b, 0) == 1; } - - void mark(bool_var b) { m_marks.setx(b, 1, 0); } - - void reset_mark(bool_var b) { m_marks[b] = 0; } - - void reset_marks() { - for (auto const& l : m_lemma) { - reset_mark(l.var()); - } - } - - void process_antecedent(literal antecedent) { - checkpoint(); - bool_var b = antecedent.var(); - TRACE("nlsat_resolve", display(tout << "resolving antecedent: ", antecedent) << "\n";); - if (assigned_value(antecedent) == l_undef) { - checkpoint(); - // antecedent must be false in the current arith interpretation - SASSERT(value(antecedent) == l_false || m_rlimit.is_canceled()); - if (!is_marked(b)) { - SASSERT(is_arith_atom(b) && max_var(b) < m_xk); // must be in a previous stage - TRACE("nlsat_resolve", tout << "literal is unassigned, but it is false in arithmetic interpretation, adding it to lemma\n";); - mark(b); - m_lemma.push_back(antecedent); - } - return; - } - - unsigned b_lvl = m_levels[b]; - TRACE("nlsat_resolve", tout << "b_lvl: " << b_lvl << ", is_marked(b): " << is_marked(b) << ", m_num_marks: " << m_num_marks << "\n";); - if (!is_marked(b)) { - mark(b); - if (b_lvl == scope_lvl() /* same level */ && max_var(b) == m_xk /* same stage */) { - TRACE("nlsat_resolve", tout << "literal is in the same level and stage, increasing marks\n";); - m_num_marks++; - } - else { - TRACE("nlsat_resolve", tout << "previous level or stage, adding literal to lemma\n"; - tout << "max_var(b): " << max_var(b) << ", m_xk: " << m_xk << ", lvl: " << b_lvl << ", scope_lvl: " << scope_lvl() << "\n";); - m_lemma.push_back(antecedent); - } - } - } - - void resolve_clause(bool_var b, unsigned sz, literal const * c) { - TRACE("nlsat_proof", tout << "resolving "; if (b != null_bool_var) display_atom(tout, b) << "\n"; display(tout, sz, c); tout << "\n";); - TRACE("nlsat_proof_sk", tout << "resolving "; if (b != null_bool_var) tout << "b" << b; tout << "\n"; display_abst(tout, sz, c); tout << "\n";); - - for (unsigned i = 0; i < sz; i++) { - if (c[i].var() != b) - process_antecedent(c[i]); - } - } - - void resolve_clause(bool_var b, clause & c) { - TRACE("nlsat_resolve", tout << "resolving clause "; if (b != null_bool_var) tout << "for b: " << b << "\n"; display(tout, c) << "\n";); - c.set_active(true); - resolve_clause(b, c.size(), c.data()); - m_lemma_assumptions = m_asm.mk_join(static_cast<_assumption_set>(c.assumptions()), m_lemma_assumptions); - } - - void resolve_lazy_justification(bool_var b, lazy_justification const & jst) { - TRACE("nlsat_resolve", tout << "resolving lazy_justification for b" << b << "\n";); - unsigned sz = jst.num_lits(); - - // Dump lemma as Mathematica formula that must be true, - // if the current interpretation (really) makes the core in jst infeasible. - TRACE("nlsat_mathematica", - tout << "assignment lemma\n"; - literal_vector core; - for (unsigned i = 0; i < sz; i++) { - core.push_back(~jst.lit(i)); - } - display_mathematica_lemma(tout, core.size(), core.data(), true);); - - m_lazy_clause.reset(); - m_explain(jst.num_lits(), jst.lits(), m_lazy_clause); - for (unsigned i = 0; i < sz; i++) - m_lazy_clause.push_back(~jst.lit(i)); - - // lazy clause is a valid clause - TRACE("nlsat_mathematica", display_mathematica_lemma(tout, m_lazy_clause.size(), m_lazy_clause.data());); - TRACE("nlsat_proof_sk", tout << "theory lemma\n"; display_abst(tout, m_lazy_clause.size(), m_lazy_clause.data()); tout << "\n";); - TRACE("nlsat_resolve", - tout << "m_xk: " << m_xk << ", "; m_display_var(tout, m_xk) << "\n"; - tout << "new valid clause:\n"; - display(tout, m_lazy_clause.size(), m_lazy_clause.data()) << "\n";); - - - if (m_log_lemmas) - log_lemma(verbose_stream(), m_lazy_clause.size(), m_lazy_clause.data(), true); - - if (m_check_lemmas) { - check_lemma(m_lazy_clause.size(), m_lazy_clause.data(), true, nullptr); - m_valids.push_back(mk_clause_core(m_lazy_clause.size(), m_lazy_clause.data(), false, nullptr)); - } - -#ifdef Z3DEBUG - { - unsigned sz = m_lazy_clause.size(); - for (unsigned i = 0; i < sz; i++) { - literal l = m_lazy_clause[i]; - if (l.var() != b) { - if (value(l) != l_false) - display(verbose_stream() << value(l) << " ", 1, &l); - SASSERT(value(l) == l_false || m_rlimit.is_canceled()); - } - else { - SASSERT(value(l) == l_true || m_rlimit.is_canceled()); - SASSERT(!l.sign() || m_bvalues[b] == l_false); - SASSERT(l.sign() || m_bvalues[b] == l_true); - } - } - } -#endif - checkpoint(); - resolve_clause(b, m_lazy_clause.size(), m_lazy_clause.data()); - - for (unsigned i = 0; i < jst.num_clauses(); ++i) { - clause const& c = jst.clause(i); - TRACE("nlsat", display(tout << "adding clause assumptions ", c) << "\n";); - m_lemma_assumptions = m_asm.mk_join(static_cast<_assumption_set>(c.assumptions()), m_lemma_assumptions); - } - } - - /** - \brief Return true if all literals in ls are from previous stages. - */ - bool only_literals_from_previous_stages(unsigned num, literal const * ls) const { - for (unsigned i = 0; i < num; i++) { - if (max_var(ls[i]) == m_xk) - return false; - } - return true; - } - - /** - \brief Return the maximum scope level in ls. - - \pre This method assumes value(ls[i]) is l_false for i in [0, num) - */ - unsigned max_scope_lvl(unsigned num, literal const * ls) { - unsigned max = 0; - for (unsigned i = 0; i < num; i++) { - literal l = ls[i]; - bool_var b = l.var(); - SASSERT(value(ls[i]) == l_false); - if (assigned_value(l) == l_false) { - unsigned lvl = m_levels[b]; - if (lvl > max) - max = lvl; - } - else { - // l must be a literal from a previous stage that is false in the current interpretation - SASSERT(assigned_value(l) == l_undef); - SASSERT(max_var(b) != null_var); - SASSERT(m_xk != null_var); - SASSERT(max_var(b) < m_xk); - } - } - return max; - } - - /** - \brief Remove literals of the given lvl (that are in the current stage) from lemma. - - \pre This method assumes value(ls[i]) is l_false for i in [0, num) - */ - void remove_literals_from_lvl(scoped_literal_vector & lemma, unsigned lvl) { - TRACE("nlsat_resolve", tout << "removing literals from lvl: " << lvl << " and stage " << m_xk << "\n";); - unsigned sz = lemma.size(); - unsigned j = 0; - for (unsigned i = 0; i < sz; i++) { - literal l = lemma[i]; - bool_var b = l.var(); - SASSERT(is_marked(b)); - SASSERT(value(lemma[i]) == l_false); - if (assigned_value(l) == l_false && m_levels[b] == lvl && max_var(b) == m_xk) { - m_num_marks++; - continue; - } - lemma.set(j, l); - j++; - } - lemma.shrink(j); - } - - /** - \brief Return true if it is a Boolean lemma. - */ - bool is_bool_lemma(unsigned sz, literal const * ls) const { - for (unsigned i = 0; i < sz; i++) { - if (m_atoms[ls[i].var()] != nullptr) - return false; - } - return true; - } - - - /** - Return the maximal decision level in lemma for literals in the first sz-1 positions that - are at the same stage. If all these literals are from previous stages, - we just backtrack the current level. - */ - unsigned find_new_level_arith_lemma(unsigned sz, literal const * lemma) { - SASSERT(!is_bool_lemma(sz, lemma)); - unsigned new_lvl = 0; - bool found_lvl = false; - for (unsigned i = 0; i < sz - 1; i++) { - literal l = lemma[i]; - if (max_var(l) == m_xk) { - bool_var b = l.var(); - if (!found_lvl) { - found_lvl = true; - new_lvl = m_levels[b]; - } - else { - if (m_levels[b] > new_lvl) - new_lvl = m_levels[b]; - } - } - } - SASSERT(!found_lvl || new_lvl < scope_lvl()); - if (!found_lvl) { - TRACE("nlsat_resolve", tout << "fail to find new lvl, using previous one\n";); - new_lvl = scope_lvl() - 1; - } - return new_lvl; - } - - struct scoped_reset_marks { - imp& i; - scoped_reset_marks(imp& i):i(i) {} - ~scoped_reset_marks() { if (i.m_num_marks > 0) { i.m_num_marks = 0; for (char& m : i.m_marks) m = 0; } } - }; - - - /** - \brief Return true if the conflict was solved. - */ - bool resolve(clause & conflict) { - clause * conflict_clause = &conflict; - m_lemma_assumptions = nullptr; - start: - SASSERT(check_marks()); - TRACE("nlsat_proof", tout << "STARTING RESOLUTION\n";); - TRACE("nlsat_proof_sk", tout << "STARTING RESOLUTION\n";); - m_stats.m_conflicts++; - TRACE("nlsat", tout << "resolve, conflicting clause:\n"; display(tout, *conflict_clause) << "\n"; - tout << "xk: "; if (m_xk != null_var) m_display_var(tout, m_xk); else tout << ""; tout << "\n"; - tout << "scope_lvl: " << scope_lvl() << "\n"; - tout << "current assignment\n"; display_assignment(tout);); - - m_num_marks = 0; - m_lemma.reset(); - m_lemma_assumptions = nullptr; - scoped_reset_marks _sr(*this); - resolve_clause(null_bool_var, *conflict_clause); - - unsigned top = m_trail.size(); - bool found_decision; - while (true) { - found_decision = false; - while (m_num_marks > 0) { - checkpoint(); - SASSERT(top > 0); - trail & t = m_trail[top-1]; - SASSERT(t.m_kind != trail::NEW_STAGE); // we only mark literals that are in the same stage - if (t.m_kind == trail::BVAR_ASSIGNMENT) { - bool_var b = t.m_b; - if (is_marked(b)) { - TRACE("nlsat_resolve", tout << "found marked: b" << b << "\n"; display_atom(tout, b) << "\n";); - m_num_marks--; - reset_mark(b); - justification jst = m_justifications[b]; - switch (jst.get_kind()) { - case justification::CLAUSE: - resolve_clause(b, *(jst.get_clause())); - break; - case justification::LAZY: - resolve_lazy_justification(b, *(jst.get_lazy())); - break; - case justification::DECISION: - SASSERT(m_num_marks == 0); - found_decision = true; - TRACE("nlsat_resolve", tout << "found decision\n";); - m_lemma.push_back(literal(b, m_bvalues[b] == l_true)); - break; - default: - UNREACHABLE(); - break; - } - } - } - top--; - } - - // m_lemma is an implicating clause after backtracking current scope level. - if (found_decision) - break; - - // If lemma only contains literals from previous stages, then we can stop. - // We make progress by returning to a previous stage with additional information (new lemma) - // that forces us to select a new partial interpretation - if (only_literals_from_previous_stages(m_lemma.size(), m_lemma.data())) - break; - - // Conflict does not depend on the current decision, and it is still in the current stage. - // We should find - // - the maximal scope level in the lemma - // - remove literal assigned in the scope level from m_lemma - // - backtrack to this level - // - and continue conflict resolution from there - // - we must bump m_num_marks for literals removed from m_lemma - unsigned max_lvl = max_scope_lvl(m_lemma.size(), m_lemma.data()); - TRACE("nlsat_resolve", tout << "conflict does not depend on current decision, backtracking to level: " << max_lvl << "\n";); - SASSERT(max_lvl < scope_lvl()); - remove_literals_from_lvl(m_lemma, max_lvl); - undo_until_level(max_lvl); - top = m_trail.size(); - TRACE("nlsat_resolve", tout << "scope_lvl: " << scope_lvl() << " num marks: " << m_num_marks << "\n";); - SASSERT(scope_lvl() == max_lvl); - } - - TRACE("nlsat_proof", tout << "New lemma\n"; display(tout, m_lemma); tout << "\n=========================\n";); - TRACE("nlsat_proof_sk", tout << "New lemma\n"; display_abst(tout, m_lemma); tout << "\n=========================\n";); - - if (m_lemma.empty()) { - TRACE("nlsat", tout << "empty clause generated\n";); - return false; // problem is unsat, empty clause was generated - } - - reset_marks(); // remove marks from the literals in m_lemmas. - TRACE("nlsat", tout << "new lemma:\n"; display(tout, m_lemma.size(), m_lemma.data()); tout << "\n"; - tout << "found_decision: " << found_decision << "\n";); - - if (m_check_lemmas) { - check_lemma(m_lemma.size(), m_lemma.data(), false, m_lemma_assumptions.get()); - } - - if (m_log_lemmas) - log_lemma(verbose_stream(), m_lemma.size(), m_lemma.data(), false); - - // There are two possibilities: - // 1) m_lemma contains only literals from previous stages, and they - // are false in the current interpretation. We make progress - // by returning to a previous stage with additional information (new clause) - // that forces us to select a new partial interpretation - // >>> Return to some previous stage (we may also backjump many decisions and stages). - // - // 2) m_lemma contains at most one literal from the current level (the last literal). - // Moreover, this literal was a decision, but the new lemma forces it to - // be assigned to a different value. - // >>> In this case, we remain in the same stage but, we add a new asserted literal - // in a previous scope level. We may backjump many decisions. - // - unsigned sz = m_lemma.size(); - clause * new_cls = nullptr; - if (!found_decision) { - // Case 1) - // We just have to find the maximal variable in m_lemma, and return to that stage - // Remark: the lemma may contain only boolean literals, in this case new_max_var == null_var; - var new_max_var = max_var(sz, m_lemma.data()); - TRACE("nlsat_resolve", tout << "backtracking to stage: " << new_max_var << ", curr: " << m_xk << "\n";); - undo_until_stage(new_max_var); - SASSERT(m_xk == new_max_var); - new_cls = mk_clause(sz, m_lemma.data(), true, m_lemma_assumptions.get()); - TRACE("nlsat", tout << "new_level: " << scope_lvl() << "\nnew_stage: " << new_max_var << "\n"; - if (new_max_var != null_var) m_display_var(tout, new_max_var) << "\n";); - } - else { - SASSERT(scope_lvl() >= 1); - // Case 2) - if (is_bool_lemma(m_lemma.size(), m_lemma.data())) { - // boolean lemma, we just backtrack until the last literal is unassigned. - bool_var max_bool_var = m_lemma[m_lemma.size()-1].var(); - undo_until_unassigned(max_bool_var); - } - else { - // We must find the maximal decision level in literals in the first sz-1 positions that - // are at the same stage. If all these literals are from previous stages, - // we just backtrack the current level. - unsigned new_lvl = find_new_level_arith_lemma(m_lemma.size(), m_lemma.data()); - TRACE("nlsat", tout << "backtracking to new level: " << new_lvl << ", curr: " << m_scope_lvl << "\n";); - undo_until_level(new_lvl); - } - - if (lemma_is_clause(*conflict_clause)) { - TRACE("nlsat", tout << "found decision literal in conflict clause\n";); - VERIFY(process_clause(*conflict_clause, true)); - return true; - } - new_cls = mk_clause(sz, m_lemma.data(), true, m_lemma_assumptions.get()); - } - NLSAT_VERBOSE(display(verbose_stream(), *new_cls) << "\n";); - if (!process_clause(*new_cls, true)) { - TRACE("nlsat", tout << "new clause triggered another conflict, restarting conflict resolution...\n"; - display(tout, *new_cls) << "\n"; - ); - // we are still in conflict - conflict_clause = new_cls; - goto start; - } - TRACE("nlsat_resolve_done", display_assignment(tout);); - return true; - } - - bool lemma_is_clause(clause const& cls) const { - bool same = (m_lemma.size() == cls.size()); - for (unsigned i = 0; same && i < m_lemma.size(); ++i) { - same = m_lemma[i] == cls[i]; - } - return same; - } - - - // ----------------------- - // - // Debugging - // - // ----------------------- - - bool check_watches() const { -#ifdef Z3DEBUG - for (var x = 0; x < num_vars(); x++) { - clause_vector const & cs = m_watches[x]; - unsigned sz = cs.size(); - for (unsigned i = 0; i < sz; i++) { - SASSERT(max_var(*(cs[i])) == x); - } - } -#endif - return true; - } - - bool check_bwatches() const { -#ifdef Z3DEBUG - for (bool_var b = 0; b < m_bwatches.size(); b++) { - clause_vector const & cs = m_bwatches[b]; - unsigned sz = cs.size(); - for (unsigned i = 0; i < sz; i++) { - clause const & c = *(cs[i]); - SASSERT(max_var(c) == null_var); - SASSERT(max_bvar(c) == b); - } - } -#endif - return true; - } - - bool check_invariant() const { - SASSERT(check_watches()); - SASSERT(check_bwatches()); - return true; - } - - bool check_satisfied(clause_vector const & cs) const { - unsigned sz = cs.size(); - for (unsigned i = 0; i < sz; i++) { - clause const & c = *(cs[i]); - if (!is_satisfied(c)) { - TRACE("nlsat", tout << "not satisfied\n"; display(tout, c); tout << "\n";); - return false; - } - } - return true; - } - - bool check_satisfied() const { - TRACE("nlsat", tout << "bk: b" << m_bk << ", xk: x" << m_xk << "\n"; if (m_xk != null_var) { m_display_var(tout, m_xk); tout << "\n"; }); - unsigned num = m_atoms.size(); - if (m_bk != null_bool_var) - num = m_bk; - for (bool_var b = 0; b < num; b++) { - if (!check_satisfied(m_bwatches[b])) { - UNREACHABLE(); - return false; - } - } - if (m_xk != null_var) { - for (var x = 0; x < m_xk; x++) { - if (!check_satisfied(m_watches[x])) { - UNREACHABLE(); - return false; - } - } - } - return true; - } - - // ----------------------- - // - // Statistics - // - // ----------------------- - - void collect_statistics(statistics & st) { - st.update("nlsat conflicts", m_stats.m_conflicts); - st.update("nlsat propagations", m_stats.m_propagations); - st.update("nlsat decisions", m_stats.m_decisions); - st.update("nlsat restarts", m_stats.m_restarts); - st.update("nlsat stages", m_stats.m_stages); - st.update("nlsat simplifications", m_stats.m_simplifications); - st.update("nlsat irrational assignments", m_stats.m_irrational_assignments); - } - - void reset_statistics() { - m_stats.reset(); - } - - // ----------------------- - // - // Variable reordering - // - // ----------------------- - - struct var_info_collector { - pmanager & pm; - atom_vector const & m_atoms; - var_vector m_shuffle; - unsigned_vector m_max_degree; - unsigned_vector m_num_occs; - - var_info_collector(pmanager & _pm, atom_vector const & atoms, unsigned num_vars): - pm(_pm), - m_atoms(atoms) { - m_max_degree.resize(num_vars, 0); - m_num_occs.resize(num_vars, 0); - } - - var_vector m_vars; - void collect(poly * p) { - m_vars.reset(); - pm.vars(p, m_vars); - unsigned sz = m_vars.size(); - for (unsigned i = 0; i < sz; i++) { - var x = m_vars[i]; - unsigned k = pm.degree(p, x); - m_num_occs[x]++; - if (k > m_max_degree[x]) - m_max_degree[x] = k; - } - } - - void collect(literal l) { - bool_var b = l.var(); - atom * a = m_atoms[b]; - if (a == nullptr) - return; - if (a->is_ineq_atom()) { - unsigned sz = to_ineq_atom(a)->size(); - for (unsigned i = 0; i < sz; i++) { - collect(to_ineq_atom(a)->p(i)); - } - } - else { - collect(to_root_atom(a)->p()); - } - } - - void collect(clause const & c) { - unsigned sz = c.size(); - for (unsigned i = 0; i < sz; i++) - collect(c[i]); - } - - void collect(clause_vector const & cs) { - unsigned sz = cs.size(); - for (unsigned i = 0; i < sz; i++) - collect(*(cs[i])); - } - - std::ostream& display(std::ostream & out, display_var_proc const & proc) { - unsigned sz = m_num_occs.size(); - for (unsigned i = 0; i < sz; i++) { - proc(out, i); out << " -> " << m_max_degree[i] << " : " << m_num_occs[i] << "\n"; - } - return out; - } - }; - - struct reorder_lt { - var_info_collector const & m_info; - reorder_lt(var_info_collector const & info):m_info(info) {} - bool operator()(var x, var y) const { - // high degree first - if (m_info.m_max_degree[x] < m_info.m_max_degree[y]) - return false; - if (m_info.m_max_degree[x] > m_info.m_max_degree[y]) - return true; - // more constrained first - if (m_info.m_num_occs[x] < m_info.m_num_occs[y]) - return false; - if (m_info.m_num_occs[x] > m_info.m_num_occs[y]) - return true; - return m_info.m_shuffle[x] < m_info.m_shuffle[y]; - } - }; - - // Order variables by degree and number of occurrences - void heuristic_reorder() { - unsigned num = num_vars(); - var_info_collector collector(m_pm, m_atoms, num); - collector.collect(m_clauses); - collector.collect(m_learned); - init_shuffle(collector.m_shuffle); - TRACE("nlsat_reorder", collector.display(tout, m_display_var);); - var_vector new_order; - for (var x = 0; x < num; x++) - new_order.push_back(x); - - std::sort(new_order.begin(), new_order.end(), reorder_lt(collector)); - TRACE("nlsat_reorder", - tout << "new order: "; for (unsigned i = 0; i < num; i++) tout << new_order[i] << " "; tout << "\n";); - var_vector perm; - perm.resize(num, 0); - for (var x = 0; x < num; x++) { - perm[new_order[x]] = x; - } - reorder(perm.size(), perm.data()); - SASSERT(check_invariant()); - } - - void init_shuffle(var_vector& p) { - unsigned num = num_vars(); - for (var x = 0; x < num; x++) - p.push_back(x); - - random_gen r(++m_random_seed); - shuffle(p.size(), p.data(), r); - } - - void shuffle_vars() { - var_vector p; - init_shuffle(p); - reorder(p.size(), p.data()); - } - - bool can_reorder() const { - return all_of(m_learned, [&](clause* c) { return !has_root_atom(*c); }) - && all_of(m_clauses, [&](clause* c) { return !has_root_atom(*c); }); - } - - /** - \brief Reorder variables using the giving permutation. - p maps internal variables to their new positions - */ - - - void reorder(unsigned sz, var const * p) { - - remove_learned_roots(); - SASSERT(can_reorder()); - TRACE("nlsat_reorder", tout << "solver before variable reorder\n"; display(tout); - display_vars(tout); - tout << "\npermutation:\n"; - for (unsigned i = 0; i < sz; i++) tout << p[i] << " "; tout << "\n"; - ); - // verbose_stream() << "\npermutation: " << p[0] << " count " << count << " " << m_rlimit.is_canceled() << "\n"; - reinit_cache(); - SASSERT(num_vars() == sz); - TRACE("nlsat_bool_assignment_bug", tout << "before reset watches\n"; display_bool_assignment(tout);); - reset_watches(); - assignment new_assignment(m_am); - for (var x = 0; x < num_vars(); x++) { - if (m_assignment.is_assigned(x)) - new_assignment.set(p[x], m_assignment.value(x)); - } - var_vector new_inv_perm; - new_inv_perm.resize(sz); - // the undo_until_size(0) statement erases the Boolean assignment. - // undo_until_size(0) - undo_until_stage(null_var); - m_cache.reset(); -#ifdef Z3DEBUG - for (var x = 0; x < num_vars(); x++) { - SASSERT(m_watches[x].empty()); - } -#endif - // update m_perm mapping - for (unsigned ext_x = 0; ext_x < sz; ext_x++) { - // p: internal -> new pos - // m_perm: internal -> external - // m_inv_perm: external -> internal - new_inv_perm[ext_x] = p[m_inv_perm[ext_x]]; - m_perm.set(new_inv_perm[ext_x], ext_x); - } - bool_vector is_int; - is_int.swap(m_is_int); - for (var x = 0; x < sz; x++) { - m_is_int.setx(p[x], is_int[x], false); - SASSERT(m_infeasible[x] == 0); - } - m_inv_perm.swap(new_inv_perm); -#ifdef Z3DEBUG - for (var x = 0; x < num_vars(); x++) { - SASSERT(x == m_inv_perm[m_perm[x]]); - SASSERT(m_watches[x].empty()); - } -#endif - m_pm.rename(sz, p); - for (auto& b : m_bounds) - b.x = p[b.x]; - TRACE("nlsat_bool_assignment_bug", tout << "before reinit cache\n"; display_bool_assignment(tout);); - reinit_cache(); - m_assignment.swap(new_assignment); - reattach_arith_clauses(m_clauses); - reattach_arith_clauses(m_learned); - TRACE("nlsat_reorder", tout << "solver after variable reorder\n"; display(tout); display_vars(tout);); - } - - - /** - \brief Restore variable order. - */ - void restore_order() { - // m_perm: internal -> external - // m_inv_perm: external -> internal - var_vector p; - p.append(m_perm); - reorder(p.size(), p.data()); -#ifdef Z3DEBUG - for (var x = 0; x < num_vars(); x++) { - SASSERT(m_perm[x] == x); - SASSERT(m_inv_perm[x] == x); - } -#endif - } - - /** - \brief After variable reordering some lemmas containing root atoms may be ill-formed. - */ - void remove_learned_roots() { - unsigned j = 0; - for (clause* c : m_learned) { - if (has_root_atom(*c)) { - del_clause(c); - } - else { - m_learned[j++] = c; - } - } - m_learned.shrink(j); - } - - /** - \brief Return true if the clause contains an ill formed root atom - */ - bool has_root_atom(clause const & c) const { - for (literal lit : c) { - bool_var b = lit.var(); - atom * a = m_atoms[b]; - if (a && a->is_root_atom()) - return true; - } - return false; - } - - /** - \brief reinsert all polynomials in the unique cache - */ - void reinit_cache() { - reinit_cache(m_clauses); - reinit_cache(m_learned); - for (atom* a : m_atoms) - reinit_cache(a); - } - void reinit_cache(clause_vector const & cs) { - for (clause* c : cs) - reinit_cache(*c); - } - void reinit_cache(clause const & c) { - for (literal l : c) - reinit_cache(l); - } - void reinit_cache(literal l) { - bool_var b = l.var(); - reinit_cache(m_atoms[b]); - } - void reinit_cache(atom* a) { - if (a == nullptr) { - - } - else if (a->is_ineq_atom()) { - var max = 0; - unsigned sz = to_ineq_atom(a)->size(); - for (unsigned i = 0; i < sz; i++) { - poly * p = to_ineq_atom(a)->p(i); - VERIFY(m_cache.mk_unique(p) == p); - var x = m_pm.max_var(p); - if (x > max) - max = x; - } - a->m_max_var = max; - } - else { - poly * p = to_root_atom(a)->p(); - VERIFY(m_cache.mk_unique(p) == p); - a->m_max_var = m_pm.max_var(p); - } - } - - void reset_watches() { - unsigned num = num_vars(); - for (var x = 0; x < num; x++) { - m_watches[x].reset(); - } - } - - void reattach_arith_clauses(clause_vector const & cs) { - for (clause* cp : cs) { - var x = max_var(*cp); - if (x != null_var) - m_watches[x].push_back(cp); - } - } - - // ----------------------- - // - // Solver initialization - // - // ----------------------- - - struct degree_lt { - unsigned_vector & m_degrees; - degree_lt(unsigned_vector & ds):m_degrees(ds) {} - bool operator()(unsigned i1, unsigned i2) const { - if (m_degrees[i1] < m_degrees[i2]) - return true; - if (m_degrees[i1] > m_degrees[i2]) - return false; - return i1 < i2; - } - }; - - unsigned_vector m_cs_degrees; - unsigned_vector m_cs_p; - void sort_clauses_by_degree(unsigned sz, clause ** cs) { - if (sz <= 1) - return; - TRACE("nlsat_reorder_clauses", tout << "before:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); - m_cs_degrees.reset(); - m_cs_p.reset(); - for (unsigned i = 0; i < sz; i++) { - m_cs_p.push_back(i); - m_cs_degrees.push_back(degree(*(cs[i]))); - } - std::sort(m_cs_p.begin(), m_cs_p.end(), degree_lt(m_cs_degrees)); - TRACE("nlsat_reorder_clauses", tout << "permutation: "; ::display(tout, m_cs_p.begin(), m_cs_p.end()); tout << "\n";); - apply_permutation(sz, cs, m_cs_p.data()); - TRACE("nlsat_reorder_clauses", tout << "after:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); - } - - void sort_watched_clauses() { - unsigned num = num_vars(); - for (unsigned i = 0; i < num; i++) { - clause_vector & ws = m_watches[i]; - sort_clauses_by_degree(ws.size(), ws.data()); - } - } - - // ----------------------- - // - // Full dimensional - // - // A problem is in the full dimensional fragment if it does - // not contain equalities or non-strict inequalities. - // - // ----------------------- - - bool is_full_dimensional(literal l) const { - atom * a = m_atoms[l.var()]; - if (a == nullptr) - return true; - switch (a->get_kind()) { - case atom::EQ: return l.sign(); - case atom::LT: return !l.sign(); - case atom::GT: return !l.sign(); - case atom::ROOT_EQ: return l.sign(); - case atom::ROOT_LT: return !l.sign(); - case atom::ROOT_GT: return !l.sign(); - case atom::ROOT_LE: return l.sign(); - case atom::ROOT_GE: return l.sign(); - default: - UNREACHABLE(); - return false; - } - } - - bool is_full_dimensional(clause const & c) const { - for (literal l : c) { - if (!is_full_dimensional(l)) - return false; - } - return true; - } - - bool is_full_dimensional(clause_vector const & cs) const { - for (clause* c : cs) { - if (!is_full_dimensional(*c)) - return false; - } - return true; - } - - bool is_full_dimensional() const { - return is_full_dimensional(m_clauses); - } - - - // ----------------------- - // - // Simplification - // - // ----------------------- - - // solve simple equalities - // TBD WU-Reit decomposition? - - // - elim_unconstrained - // - solve_eqs - // - fm - - /** - \brief isolate variables in unit equalities. - Assume a clause is c == v*p + q - and the context implies p > 0 - - replace v by -q/p - remove clause c, - The for other occurrences of v, - replace v*r + v*v*r' > 0 by - by p*p*v*r + p*p*v*v*r' > 0 - by p*q*r + q*q*r' > 0 - - The method ignores lemmas and assumes constraints don't use roots. - */ - - - - // Eliminated variables are tracked in m_bounds. - // Each element in m_bounds tracks the eliminated variable and an upper or lower bound - // that has to be satisfied. Variables that are eliminated through equalities are tracked - // by non-strict bounds. A satisfiable solution is required to provide an evaluation that - // is consistent with the bounds. For equalities, the non-strict lower or upper bound can - // always be assigned as a value to the variable. - - void fix_patch() { - m_lo.reset(); m_hi.reset(); - for (auto& b : m_bounds) - m_assignment.reset(b.x); - for (unsigned i = m_bounds.size(); i-- > 0; ) - fix_patch(m_bounds[i]); - } - - // x is unassigned, lo < x -> x <- lo + 1 - // x is unassigned, x < hi -> x <- hi - 1 - // x is unassigned, lo <= x -> x <- lo - // x is unassigned, x <= hi -> x <- hi - // x is assigned above hi, lo is strict lo < x < hi -> set x <- (lo + hi)/2 - // x is assigned below hi, above lo -> no-op - // x is assigned below lo, hi is strict lo < x < hi -> set x <-> (lo + hi)/2 - // x is assigned above hi, x <= hi -> x <- hi - // x is assigned blow lo, lo <= x -> x <- lo - void fix_patch(bound_constraint& b) { - var x = b.x; - scoped_anum Av(m_am), Bv(m_am), val(m_am); - m_pm.eval(b.A, m_assignment, Av); - m_pm.eval(b.B, m_assignment, Bv); - m_am.neg(Bv); - val = Bv / Av; - // Ax >= B - // is-lower : A > 0 - // is-upper: A < 0 - // x <- B / A - bool is_lower = m_am.is_pos(Av); - TRACE("nlsat", - m_display_var(tout << "patch v" << x << " ", x) << "\n"; - if (m_assignment.is_assigned(x)) m_am.display(tout << "previous value: ", m_assignment.value(x)); tout << "\n"; - m_am.display(tout << "updated value: ", val); tout << "\n"; - ); - - if (!m_assignment.is_assigned(x)) { - if (!b.is_strict) - m_assignment.set_core(x, val); - else if (is_lower) - m_assignment.set_core(x, val + 1); - else - m_assignment.set_core(x, val - 1); - } - else { - auto& aval = m_assignment.value(x); - if (is_lower) { - // lo < value(x), lo < x -> x is unchanged - if (b.is_strict && m_am.lt(val, aval)) - ; - else if (!b.is_strict && m_am.le(val, aval)) - ; - else if (!b.is_strict) - m_assignment.set_core(x, val); - // aval < lo < x, hi is unassigned: x <- lo + 1 - else if (!m_hi.is_assigned(x)) - m_assignment.set_core(x, val + 1); - // aval < lo < x, hi is assigned: x <- (lo + hi) / 2 - else { - scoped_anum mid(m_am); - m_am.add(m_hi.value(x), val, mid); - mid = mid / 2; - m_assignment.set_core(x, mid); - } - } - else { - // dual to lower bounds - if (b.is_strict && m_am.lt(aval, val)) - ; - else if (!b.is_strict && m_am.le(aval, val)) - ; - else if (!b.is_strict) - m_assignment.set_core(x, val); - else if (!m_lo.is_assigned(x)) - m_assignment.set_core(x, val - 1); - else { - scoped_anum mid(m_am); - m_am.add(m_lo.value(x), val, mid); - mid = mid / 2; - m_assignment.set_core(x, mid); - } - } - } - - if (is_lower) { - if (!m_lo.is_assigned(x) || m_am.lt(m_lo.value(x), val)) - m_lo.set_core(x, val); - } - else { - if (!m_hi.is_assigned(x) || m_am.gt(m_hi.value(x), val)) - m_hi.set_core(x, val); - } - } - - bool is_unit_ineq(clause const& c) const { - return - c.size() == 1 && - m_atoms[c[0].var()] && - m_atoms[c[0].var()]->is_ineq_atom(); - } - - bool is_unit_eq(clause const& c) const { - return - is_unit_ineq(c) && - !c[0].sign() && - m_atoms[c[0].var()]->is_eq(); - } - - /** - \brief determine whether the clause is a comparison v > k or v < k', where k >= 0 or k' <= 0. - */ - lbool is_cmp0(clause const& c, var& v) { - if (!is_unit_ineq(c)) - return l_undef; - literal lit = c[0]; - ineq_atom const& a = *to_ineq_atom(m_atoms[lit.var()]); - bool sign = lit.sign(); - poly * p0; - if (!is_single_poly(a, p0)) - return l_undef; - if (m_pm.is_var(p0, v)) { - if (!sign && a.get_kind() == atom::GT) { - return l_true; - } - if (!sign && a.get_kind() == atom::LT) { - return l_false; - } - return l_undef; - } - polynomial::scoped_numeral n(m_pm.m()); - if (m_pm.is_var_num(p0, v, n)) { - // x - k > 0 - if (!sign && a.get_kind() == atom::GT && m_pm.m().is_nonneg(n)) { - return l_true; - } - // x + k < 0 - if (!sign && a.get_kind() == atom::LT && m_pm.m().is_nonpos(n)) { - return l_false; - } - // !(x + k > 0) - if (sign && a.get_kind() == atom::GT && m_pm.m().is_pos(n)) { - return l_false; - } - // !(x - k < 0) - if (sign && a.get_kind() == atom::LT && m_pm.m().is_neg(n)) { - return l_true; - } - } - return l_undef; - } - - bool is_single_poly(ineq_atom const& a, poly*& p) { - unsigned sz = a.size(); - return sz == 1 && a.is_odd(0) && (p = a.p(0), true); - } - - bool is_unit(polynomial_ref const& p) { - if (!m_pm.is_const(p)) - return false; - auto const& c = m_pm.coeff(p, 0); - return m_pm.m().is_one(c) || m_pm.m().is_minus_one(c); - } - - // ----------------------- - // - // Pretty printing - // - // ----------------------- - - std::ostream& display_num_assignment(std::ostream & out, display_var_proc const & proc) const { - for (var x = 0; x < num_vars(); x++) { - if (m_assignment.is_assigned(x)) { - proc(out, x); - out << " -> "; - m_am.display_decimal(out, m_assignment.value(x)); - out << "\n"; - } - } - return out; - } - - std::ostream& display_bool_assignment(std::ostream & out) const { - unsigned sz = m_atoms.size(); - for (bool_var b = 0; b < sz; b++) { - if (m_atoms[b] == nullptr && m_bvalues[b] != l_undef) { - out << "b" << b << " -> " << (m_bvalues[b] == l_true ? "true" : "false") << " @" << m_levels[b] << "\n"; - } - else if (m_atoms[b] != nullptr && m_bvalues[b] != l_undef) { - display(out << "b" << b << " ", *m_atoms[b]) << " -> " << (m_bvalues[b] == l_true ? "true" : "false") << " @" << m_levels[b] << "\n"; - } - } - TRACE("nlsat_bool_assignment", - for (bool_var b = 0; b < sz; b++) { - out << "b" << b << " -> " << m_bvalues[b] << " "; - if (m_atoms[b]) display(out, *m_atoms[b]); - out << "\n"; - }); - return out; - } - - bool display_mathematica_assignment(std::ostream & out) const { - bool first = true; - for (var x = 0; x < num_vars(); x++) { - if (m_assignment.is_assigned(x)) { - if (first) - first = false; - else - out << " && "; - out << "x" << x << " == "; - m_am.display_mathematica(out, m_assignment.value(x)); - } - } - return !first; - } - - std::ostream& display_num_assignment(std::ostream & out) const { - return display_num_assignment(out, m_display_var); - } - - std::ostream& display_assignment(std::ostream& out) const { - display_bool_assignment(out); - display_num_assignment(out); - return out; - } - - std::ostream& display(std::ostream& out, justification j) const { - switch (j.get_kind()) { - case justification::CLAUSE: - display(out, *j.get_clause()) << "\n"; - break; - case justification::LAZY: { - lazy_justification const& lz = *j.get_lazy(); - display_not(out, lz.num_lits(), lz.lits()) << "\n"; - for (unsigned i = 0; i < lz.num_clauses(); ++i) { - display(out, lz.clause(i)) << "\n"; - } - break; - } - default: - out << j.get_kind() << "\n"; - break; - } - return out; - } - - bool m_display_eval = false; - std::ostream& display_eval(std::ostream& out, justification j) { - flet _display(m_display_eval, true); - return display(out, j); - } - - std::ostream& display_ineq(std::ostream & out, ineq_atom const & a, display_var_proc const & proc, bool use_star = false) const { - unsigned sz = a.size(); - for (unsigned i = 0; i < sz; i++) { - if (use_star && i > 0) - out << "*"; - bool is_even = a.is_even(i); - if (is_even || sz > 1) - out << "("; - display_polynomial(out, a.p(i), proc, use_star); - if (is_even || sz > 1) - out << ")"; - if (is_even) - out << "^2"; - } - switch (a.get_kind()) { - case atom::LT: out << " < 0"; break; - case atom::GT: out << " > 0"; break; - case atom::EQ: out << " = 0"; break; - default: UNREACHABLE(); break; - } - return out; - } - - std::ostream& display_mathematica(std::ostream & out, ineq_atom const & a) const { - unsigned sz = a.size(); - for (unsigned i = 0; i < sz; i++) { - if (i > 0) - out << "*"; - bool is_even = a.is_even(i); - if (sz > 1) - out << "("; - if (is_even) - out << "("; - m_pm.display(out, a.p(i), display_var_proc(), true); - if (is_even) - out << "^2)"; - if (sz > 1) - out << ")"; - } - switch (a.get_kind()) { - case atom::LT: out << " < 0"; break; - case atom::GT: out << " > 0"; break; - case atom::EQ: out << " == 0"; break; - default: UNREACHABLE(); break; - } - return out; - } - - std::ostream& display_polynomial_smt2(std::ostream & out, poly const* p, display_var_proc const & proc) const { - return m_pm.display_smt2(out, p, proc); - } - - std::ostream& display_ineq_smt2(std::ostream & out, ineq_atom const & a, display_var_proc const & proc) const { - switch (a.get_kind()) { - case atom::LT: out << "(< "; break; - case atom::GT: out << "(> "; break; - case atom::EQ: out << "(= "; break; - default: UNREACHABLE(); break; - } - unsigned sz = a.size(); - if (sz > 1) - out << "(* "; - for (unsigned i = 0; i < sz; i++) { - if (i > 0) out << " "; - if (a.is_even(i)) { - out << "(* "; - display_polynomial_smt2(out, a.p(i), proc); - out << " "; - display_polynomial_smt2(out, a.p(i), proc); - out << ")"; - } - else { - display_polynomial_smt2(out, a.p(i), proc); - } - } - if (sz > 1) - out << ")"; - out << " 0)"; - return out; - } - - std::ostream& display_poly_root(std::ostream& out, char const* y, root_atom const& a, display_var_proc const& proc) const { - out << "(exists (("; proc(out,a.x()); out << " Real))\n"; - out << "(and (= " << y << " "; - proc(out, a.x()); - out << ") (= 0 "; - display_polynomial_smt2(out, a.p(), proc); - out << ")))\n"; - return out; - } - - std::ostream& display_binary_smt2(std::ostream& out, poly const* p1, char const* rel, poly const* p2, display_var_proc const& proc) const { - out << "(" << rel << " "; - display_polynomial_smt2(out, p1, proc); - out << " "; - display_polynomial_smt2(out, p2, proc); - out << ")"; - return out; - } - - - std::ostream& display_linear_root_smt2(std::ostream & out, root_atom const & a, display_var_proc const & proc) const { - polynomial_ref A(m_pm), B(m_pm), Z(m_pm), Ax(m_pm); - polynomial::scoped_numeral zero(m_qm); - m_pm.m().set(zero, 0); - A = m_pm.derivative(a.p(), a.x()); - B = m_pm.neg(m_pm.substitute(a.p(), a.x(), zero)); - Z = m_pm.mk_zero(); - - Ax = m_pm.mul(m_pm.mk_polynomial(a.x()), A); - - // x < root[1](ax + b) == (a > 0 => ax + b < 0) & (a < 0 => ax + b > 0) - // x < root[1](ax + b) == (a > 0 => ax < -b) & (a < 0 => ax > -b) - - char const* rel1 = "<", *rel2 = ">"; - switch (a.get_kind()) { - case atom::ROOT_LT: rel1 = "<"; rel2 = ">"; break; - case atom::ROOT_GT: rel1 = ">"; rel2 = "<"; break; - case atom::ROOT_LE: rel1 = "<="; rel2 = ">="; break; - case atom::ROOT_GE: rel1 = ">="; rel2 = "<="; break; - case atom::ROOT_EQ: rel1 = rel2 = "="; break; - default: UNREACHABLE(); break; - } - - out << "(and "; - out << "(=> "; display_binary_smt2(out, A, ">", Z, proc); display_binary_smt2(out, Ax, rel1, B, proc); out << ") "; - out << "(=> "; display_binary_smt2(out, A, "<", Z, proc); display_binary_smt2(out, Ax, rel2, B, proc); out << ") "; - out << ")"; - - return out; - } - - - std::ostream& display_root_smt2(std::ostream& out, root_atom const& a, display_var_proc const& proc) const { - if (a.i() == 1 && m_pm.degree(a.p(), a.x()) == 1) - return display_linear_root_smt2(out, a, proc); -#if 1 - out << "(exists ("; - for (unsigned j = 0; j < a.i(); ++j) { - std::string y = std::string("y") + std::to_string(j); - out << "(" << y << " Real) "; - } - out << ")\n"; - out << "(and\n"; - for (unsigned j = 0; j < a.i(); ++j) { - std::string y = std::string("y") + std::to_string(j); - display_poly_root(out, y.c_str(), a, proc); - } - for (unsigned j = 0; j + 1 < a.i(); ++j) { - std::string y1 = std::string("y") + std::to_string(j); - std::string y2 = std::string("y") + std::to_string(j+1); - out << "(< " << y1 << " " << y2 << ")\n"; - } - - std::string yn = "y" + std::to_string(a.i() - 1); - - // TODO we need (forall z : z < yn . p(z) => z = y1 or ... z = y_{n-1}) - // to say y1, .., yn are the first n distinct roots. - // - out << "(forall ((z Real)) (=> (and (< z " << yn << ") "; display_poly_root(out, "z", a, proc) << ") "; - if (a.i() == 1) { - out << "false))\n"; - } - else { - out << "(or "; - for (unsigned j = 0; j + 1 < a.i(); ++j) { - std::string y1 = std::string("y") + std::to_string(j); - out << "(= z " << y1 << ") "; - } - out << ")))\n"; - } - switch (a.get_kind()) { - case atom::ROOT_LT: out << "(< "; proc(out, a.x()); out << " " << yn << ")"; break; - case atom::ROOT_GT: out << "(> "; proc(out, a.x()); out << " " << yn << ")"; break; - case atom::ROOT_LE: out << "(<= "; proc(out, a.x()); out << " " << yn << ")"; break; - case atom::ROOT_GE: out << "(>= "; proc(out, a.x()); out << " " << yn << ")"; break; - case atom::ROOT_EQ: out << "(= "; proc(out, a.x()); out << " " << yn << ")"; NOT_IMPLEMENTED_YET(); break; - default: UNREACHABLE(); break; - } - out << "))"; - return out; -#endif - - - return display_root(out, a, proc); - } - - std::ostream& display_root(std::ostream & out, root_atom const & a, display_var_proc const & proc) const { - proc(out, a.x()); - switch (a.get_kind()) { - case atom::ROOT_LT: out << " < "; break; - case atom::ROOT_GT: out << " > "; break; - case atom::ROOT_LE: out << " <= "; break; - case atom::ROOT_GE: out << " >= "; break; - case atom::ROOT_EQ: out << " = "; break; - default: UNREACHABLE(); break; - } - out << "root[" << a.i() << "]("; - display_polynomial(out, a.p(), proc); - out << ")"; - return out; - } - - struct mathematica_var_proc : public display_var_proc { - var m_x; - public: - mathematica_var_proc(var x):m_x(x) {} - std::ostream& operator()(std::ostream & out, var x) const override { - if (m_x == x) - return out << "#1"; - else - return out << "x" << x; - } - }; - - std::ostream& display_mathematica(std::ostream & out, root_atom const & a) const { - out << "x" << a.x(); - switch (a.get_kind()) { - case atom::ROOT_LT: out << " < "; break; - case atom::ROOT_GT: out << " > "; break; - case atom::ROOT_LE: out << " <= "; break; - case atom::ROOT_GE: out << " >= "; break; - case atom::ROOT_EQ: out << " == "; break; - default: UNREACHABLE(); break; - } - out << "Root["; - display_polynomial(out, a.p(), mathematica_var_proc(a.x()), true); - out << " &, " << a.i() << "]"; - return out; - } - - std::ostream& display(std::ostream & out, atom const & a, display_var_proc const & proc) const { - if (a.is_ineq_atom()) - return display_ineq(out, static_cast(a), proc); - else - return display_root(out, static_cast(a), proc); - } - - std::ostream& display(std::ostream & out, atom const & a) const { - return display(out, a, m_display_var); - } - - std::ostream& display_mathematica(std::ostream & out, atom const & a) const { - if (a.is_ineq_atom()) - return display_mathematica(out, static_cast(a)); - else - return display_mathematica(out, static_cast(a)); - } - - std::ostream& display_smt2(std::ostream & out, atom const & a, display_var_proc const & proc) const { - if (a.is_ineq_atom()) - return display_ineq_smt2(out, static_cast(a), proc); - else - return display_root_smt2(out, static_cast(a), proc); - } - - std::ostream& display_atom(std::ostream & out, bool_var b, display_var_proc const & proc) const { - if (b == 0) - out << "true"; - else if (m_atoms[b] == 0) - out << "b" << b; - else - display(out, *(m_atoms[b]), proc); - return out; - } - - std::ostream& display_atom(std::ostream & out, bool_var b) const { - return display_atom(out, b, m_display_var); - } - - std::ostream& display_mathematica_atom(std::ostream & out, bool_var b) const { - if (b == 0) - out << "(0 < 1)"; - else if (m_atoms[b] == 0) - out << "b" << b; - else - display_mathematica(out, *(m_atoms[b])); - return out; - } - - std::ostream& display_smt2_atom(std::ostream & out, bool_var b, display_var_proc const & proc) const { - if (b == 0) - out << "true"; - else if (m_atoms[b] == 0) - out << "b" << b; - else - display_smt2(out, *(m_atoms[b]), proc); - return out; - } - - std::ostream& display(std::ostream & out, literal l, display_var_proc const & proc) const { - if (l.sign()) { - bool_var b = l.var(); - out << "!"; - if (m_atoms[b] != 0) - out << "("; - display_atom(out, b, proc); - if (m_atoms[b] != 0) - out << ")"; - } - else { - display_atom(out, l.var(), proc); - } - return out; - } - - std::ostream& display(std::ostream & out, literal l) const { - return display(out, l, m_display_var); - } - - std::ostream& display_smt2(std::ostream & out, literal l) const { - return display_smt2(out, l, m_display_var); - } - - std::ostream& display_mathematica(std::ostream & out, literal l) const { - if (l.sign()) { - bool_var b = l.var(); - out << "!"; - if (m_atoms[b] != 0) - out << "("; - display_mathematica_atom(out, b); - if (m_atoms[b] != 0) - out << ")"; - } - else { - display_mathematica_atom(out, l.var()); - } - return out; - } - - std::ostream& display_smt2(std::ostream & out, literal l, display_var_proc const & proc) const { - if (l.sign()) { - bool_var b = l.var(); - out << "(not "; - display_smt2_atom(out, b, proc); - out << ")"; - } - else { - display_smt2_atom(out, l.var(), proc); - } - return out; - } - - std::ostream& display_assumptions(std::ostream & out, _assumption_set s) const { - if (!m_display_assumption) - return out; - vector deps; - m_asm.linearize(s, deps); - bool first = true; - for (auto dep : deps) { - if (first) first = false; else out << " "; - (*m_display_assumption)(out, dep); - } - return out; - } - - std::ostream& display(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { - for (unsigned i = 0; i < num; i++) { - if (i > 0) - out << " or "; - display(out, ls[i], proc); - } - return out; - } - - std::ostream& display(std::ostream & out, unsigned num, literal const * ls) const { - return display(out, num, ls, m_display_var); - } - - std::ostream& display_not(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { - for (unsigned i = 0; i < num; i++) { - if (i > 0) - out << " or "; - display(out, ~ls[i], proc); - } - return out; - } - - std::ostream& display_not(std::ostream & out, unsigned num, literal const * ls) const { - return display_not(out, num, ls, m_display_var); - } - - std::ostream& display(std::ostream & out, scoped_literal_vector const & cs) { - return display(out, cs.size(), cs.data(), m_display_var); - } - - std::ostream& display(std::ostream & out, clause const & c, display_var_proc const & proc) const { - if (c.assumptions() != nullptr) { - display_assumptions(out, static_cast<_assumption_set>(c.assumptions())); - out << " |- "; - } - return display(out, c.size(), c.data(), proc); - } - - std::ostream& display(std::ostream & out, clause const & c) const { - return display(out, c, m_display_var); - } - - - std::ostream& display_polynomial(std::ostream& out, poly* p, display_var_proc const & proc, bool use_star = false) const { - if (m_display_eval) { - polynomial_ref q(m_pm); - q = p; - for (var x = 0; x < num_vars(); x++) - if (m_assignment.is_assigned(x)) { - auto& a = m_assignment.value(x); - if (!m_am.is_rational(a)) - continue; - mpq r; - m_am.to_rational(a, r); - q = m_pm.substitute(q, 1, &x, &r); - } - m_pm.display(out, q, proc, use_star); - } - else - m_pm.display(out, p, proc, use_star); - return out; - } - - // -- - - std::ostream& display_smt2(std::ostream & out, unsigned n, literal const* ls) const { - return display_smt2(out, n, ls, display_var_proc()); - } - - - std::ostream& display_smt2(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { - if (num == 0) { - out << "false"; - } - else if (num == 1) { - display_smt2(out, ls[0], proc); - } - else { - out << "(or"; - for (unsigned i = 0; i < num; i++) { - out << " "; - display_smt2(out, ls[i], proc); - } - out << ")"; - } - return out; - } - - std::ostream& display_smt2(std::ostream & out, clause const & c, display_var_proc const & proc = display_var_proc()) const { - return display_smt2(out, c.size(), c.data(), proc); - } - - std::ostream& display_abst(std::ostream & out, literal l) const { - if (l.sign()) { - bool_var b = l.var(); - out << "!"; - if (b == true_bool_var) - out << "true"; - else - out << "b" << b; - } - else { - out << "b" << l.var(); - } - return out; - } - - std::ostream& display_abst(std::ostream & out, unsigned num, literal const * ls) const { - for (unsigned i = 0; i < num; i++) { - if (i > 0) - out << " or "; - display_abst(out, ls[i]); - } - return out; - } - - std::ostream& display_abst(std::ostream & out, scoped_literal_vector const & cs) const { - return display_abst(out, cs.size(), cs.data()); - } - - std::ostream& display_abst(std::ostream & out, clause const & c) const { - return display_abst(out, c.size(), c.data()); - } - - std::ostream& display_mathematica(std::ostream & out, clause const & c) const { - out << "("; - unsigned sz = c.size(); - for (unsigned i = 0; i < sz; i++) { - if (i > 0) - out << " || "; - display_mathematica(out, c[i]); - } - out << ")"; - return out; - } - - // Debugging support: - // Display generated lemma in Mathematica format. - // Mathematica must reduce lemma to True (modulo resource constraints). - std::ostream& display_mathematica_lemma(std::ostream & out, unsigned num, literal const * ls, bool include_assignment = false) const { - out << "Resolve[ForAll[{"; - // var definition - for (unsigned i = 0; i < num_vars(); i++) { - if (i > 0) - out << ", "; - out << "x" << i; - } - out << "}, "; - if (include_assignment) { - out << "!("; - if (!display_mathematica_assignment(out)) - out << "0 < 1"; // nothing was printed - out << ") || "; - } - for (unsigned i = 0; i < num; i++) { - if (i > 0) - out << " || "; - display_mathematica(out, ls[i]); - } - out << "], Reals]\n"; // end of exists - return out; - } - - std::ostream& display(std::ostream & out, clause_vector const & cs, display_var_proc const & proc) const { - for (clause* c : cs) { - display(out, *c, proc) << "\n"; - } - return out; - } - - std::ostream& display(std::ostream & out, clause_vector const & cs) const { - return display(out, cs, m_display_var); - } - - std::ostream& display_mathematica(std::ostream & out, clause_vector const & cs) const { - unsigned sz = cs.size(); - for (unsigned i = 0; i < sz; i++) { - if (i > 0) out << ",\n"; - display_mathematica(out << " ", *(cs[i])); - } - return out; - } - - std::ostream& display_abst(std::ostream & out, clause_vector const & cs) const { - for (clause* c : cs) { - display_abst(out, *c) << "\n"; - } - return out; - } - - std::ostream& display(std::ostream & out, display_var_proc const & proc) const { - display(out, m_clauses, proc); - if (!m_learned.empty()) { - display(out << "Lemmas:\n", m_learned, proc); - } - return out; - } - - std::ostream& display_mathematica(std::ostream & out) const { - return display_mathematica(out << "{\n", m_clauses) << "}\n"; - } - - std::ostream& display_abst(std::ostream & out) const { - display_abst(out, m_clauses); - if (!m_learned.empty()) { - display_abst(out << "Lemmas:\n", m_learned); - } - return out; - } - - std::ostream& display(std::ostream & out) const { - display(out, m_display_var); - display_assignment(out << "assignment:\n"); - return out << "---\n"; - } - - std::ostream& display_vars(std::ostream & out) const { - for (unsigned i = 0; i < num_vars(); i++) { - out << i << " -> "; m_display_var(out, i); out << "\n"; - } - return out; - } - - std::ostream& display_smt2_arith_decls(std::ostream & out) const { - unsigned sz = m_is_int.size(); - for (unsigned i = 0; i < sz; i++) { - if (is_int(i)) { - out << "(declare-fun "; m_display_var(out, i) << " () Int)\n"; - } - else { - out << "(declare-fun "; m_display_var(out, i) << " () Real)\n"; - } - } - return out; - } - - std::ostream& display_smt2_bool_decls(std::ostream & out) const { - unsigned sz = m_atoms.size(); - for (unsigned i = 0; i < sz; i++) { - if (m_atoms[i] == nullptr) - out << "(declare-fun b" << i << " () Bool)\n"; - } - return out; - } - - std::ostream& display_smt2(std::ostream & out) const { - display_smt2_bool_decls(out); - display_smt2_arith_decls(out); - out << "(assert (and true\n"; - for (clause* c : m_clauses) { - display_smt2(out, *c, m_display_var) << "\n"; - } - out << "))\n" << std::endl; - return out; - } - }; - - solver::solver(reslimit& rlim, params_ref const & p, bool incremental) { - m_ctx = alloc(ctx, rlim, p, incremental); - m_imp = alloc(imp, *this, *m_ctx); - } - - solver::solver(ctx& ctx) { - m_ctx = nullptr; - m_imp = alloc(imp, *this, ctx); - } - - solver::~solver() { - dealloc(m_imp); - dealloc(m_ctx); - } - - lbool solver::check() { - return m_imp->check(); - } - - lbool solver::check(literal_vector& assumptions) { - return m_imp->check(assumptions); - } - - void solver::get_core(vector& assumptions) { - return m_imp->get_core(assumptions); - } - - void solver::reset() { - m_imp->reset(); - } - - - void solver::updt_params(params_ref const & p) { - m_imp->updt_params(p); - } - - - void solver::collect_param_descrs(param_descrs & d) { - algebraic_numbers::manager::collect_param_descrs(d); - nlsat_params::collect_param_descrs(d); - } - - unsynch_mpq_manager & solver::qm() { - return m_imp->m_qm; - } - - anum_manager & solver::am() { - return m_imp->m_am; - } - - pmanager & solver::pm() { - return m_imp->m_pm; - } - - void solver::set_display_var(display_var_proc const & proc) { - m_imp->m_display_var.m_proc = &proc; - } - - void solver::set_display_assumption(display_assumption_proc const& proc) { - m_imp->m_display_assumption = &proc; - } - - - unsigned solver::num_vars() const { - return m_imp->num_vars(); - } - - bool solver::is_int(var x) const { - return m_imp->is_int(x); - } - - bool_var solver::mk_bool_var() { - return m_imp->mk_bool_var(); - } - - literal solver::mk_true() { - return literal(0, false); - } - - atom * solver::bool_var2atom(bool_var b) { - return m_imp->m_atoms[b]; - } - - void solver::vars(literal l, var_vector& vs) { - m_imp->vars(l, vs); - } - - atom_vector const& solver::get_atoms() { - return m_imp->m_atoms; - } - - atom_vector const& solver::get_var2eq() { - return m_imp->m_var2eq; - } - - evaluator& solver::get_evaluator() { - return m_imp->m_evaluator; - } - - explain& solver::get_explain() { - return m_imp->m_explain; - } - - void solver::reorder(unsigned sz, var const* p) { - m_imp->reorder(sz, p); - } - - void solver::restore_order() { - m_imp->restore_order(); - } - - void solver::set_rvalues(assignment const& as) { - m_imp->m_assignment.copy(as); - } - - void solver::get_rvalues(assignment& as) { - as.copy(m_imp->m_assignment); - } - - void solver::get_bvalues(svector const& bvars, svector& vs) { - vs.reset(); - for (bool_var b : bvars) { - vs.reserve(b + 1, l_undef); - if (!m_imp->m_atoms[b]) { - vs[b] = m_imp->m_bvalues[b]; - } - } - TRACE("nlsat", display(tout);); - } - - void solver::set_bvalues(svector const& vs) { - TRACE("nlsat", display(tout);); - for (bool_var b = 0; b < vs.size(); ++b) { - if (vs[b] != l_undef) { - m_imp->m_bvalues[b] = vs[b]; - SASSERT(!m_imp->m_atoms[b]); - } - } -#if 0 - m_imp->m_bvalues.reset(); - m_imp->m_bvalues.append(vs); - m_imp->m_bvalues.resize(m_imp->m_atoms.size(), l_undef); - for (unsigned i = 0; i < m_imp->m_atoms.size(); ++i) { - atom* a = m_imp->m_atoms[i]; - SASSERT(!a); - if (a) { - m_imp->m_bvalues[i] = to_lbool(m_imp->m_evaluator.eval(a, false)); - } - } -#endif - TRACE("nlsat", display(tout);); - } - - void solver::del_clause(clause* c) { - m_imp->del_clause(c); - } - - var solver::mk_var(bool is_int) { - return m_imp->mk_var(is_int); - } - - bool_var solver::mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even) { - return m_imp->mk_ineq_atom(k, sz, ps, is_even); - } - - literal solver::mk_ineq_literal(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify) { - return m_imp->mk_ineq_literal(k, sz, ps, is_even, simplify); - } - - bool_var solver::mk_root_atom(atom::kind k, var x, unsigned i, poly * p) { - return m_imp->mk_root_atom(k, x, i, p); - } - - void solver::inc_ref(bool_var b) { - m_imp->inc_ref(b); - } - - void solver::dec_ref(bool_var b) { - m_imp->dec_ref(b); - } - - void solver::inc_ref(assumption a) { - m_imp->inc_ref(static_cast(a)); - } - - void solver::dec_ref(assumption a) { - m_imp->dec_ref(static_cast(a)); - } - - void solver::mk_clause(unsigned num_lits, literal * lits, assumption a) { - return m_imp->mk_external_clause(num_lits, lits, a); - } - - std::ostream& solver::display(std::ostream & out) const { - return m_imp->display(out); - } - - std::ostream& solver::display(std::ostream & out, literal l) const { - return m_imp->display(out, l); - } - - std::ostream& solver::display(std::ostream & out, unsigned n, literal const* ls) const { - for (unsigned i = 0; i < n; ++i) { - display(out, ls[i]); - out << "; "; - } - return out; - } - - std::ostream& solver::display(std::ostream & out, literal_vector const& ls) const { - return display(out, ls.size(), ls.data()); - } - - std::ostream& solver::display_smt2(std::ostream & out, literal l) const { - return m_imp->display_smt2(out, l); - } - - std::ostream& solver::display_smt2(std::ostream & out, unsigned n, literal const* ls) const { - for (unsigned i = 0; i < n; ++i) { - display_smt2(out, ls[i]); - out << " "; - } - return out; - } - - std::ostream& solver::display(std::ostream& out, clause const& c) const { - return m_imp->display(out, c); - } - - std::ostream& solver::display_smt2(std::ostream & out) const { - return m_imp->display_smt2(out); - } - - std::ostream& solver::display_smt2(std::ostream & out, literal_vector const& ls) const { - return display_smt2(out, ls.size(), ls.data()); - } - - std::ostream& solver::display(std::ostream & out, var x) const { - return m_imp->m_display_var(out, x); - } - - std::ostream& solver::display(std::ostream & out, atom const& a) const { - return m_imp->display(out, a, m_imp->m_display_var); - } - - display_var_proc const & solver::display_proc() const { - return m_imp->m_display_var; - } - - anum const & solver::value(var x) const { - if (m_imp->m_assignment.is_assigned(x)) - return m_imp->m_assignment.value(x); - return m_imp->m_zero; - } - - lbool solver::bvalue(bool_var b) const { - return m_imp->m_bvalues[b]; - } - - lbool solver::value(literal l) const { - return m_imp->value(l); - } - - bool solver::is_interpreted(bool_var b) const { - return m_imp->m_atoms[b] != 0; - } - - void solver::reset_statistics() { - return m_imp->reset_statistics(); - } - - void solver::collect_statistics(statistics & st) { - return m_imp->collect_statistics(st); - } - - clause* solver::mk_clause(unsigned n, literal const* lits, bool learned, internal_assumption a) { - return m_imp->mk_clause(n, lits, learned, static_cast(a)); - } - - void solver::inc_simplify() { - m_imp->m_stats.m_simplifications++; - } - - bool solver::has_root_atom(clause const& c) const { - return m_imp->has_root_atom(c); - } - - void solver::add_bound(bound_constraint const& c) { - m_imp->m_bounds.push_back(c); - } - - assumption solver::join(assumption a, assumption b) { - return (m_imp->m_asm.mk_join(static_cast(a), static_cast(b))); - } - -}; diff --git a/src/nlsat/nlsat_symmetry_checker.cpp b/src/nlsat/nlsat_symmetry_checker.cpp new file mode 100644 index 000000000..8d0ee8766 --- /dev/null +++ b/src/nlsat/nlsat_symmetry_checker.cpp @@ -0,0 +1,356 @@ +#include "nlsat/nlsat_symmetry_checker.h" + +struct Debug_Tracer { + std::string tag_str; + Debug_Tracer(std::string _tag_str) { + tag_str = _tag_str; + TRACE("linxi_symmetry_checker", + tout << "Debug_Tracer begin\n"; + tout << tag_str << "\n"; + ); + } + ~Debug_Tracer() { + TRACE("linxi_symmetry_checker", + tout << "Debug_Tracer end\n"; + tout << tag_str << "\n"; + ); + } +}; + +// #define _LINXI_DEBUG + +#ifdef _LINXI_DEBUG +#define LINXI_DEBUG_CORE(x) std::stringstream DEBUG_ss_##x; DEBUG_ss_##x << __FUNCTION__ << " " << __FILE__ << ":" << __LINE__; Debug_Tracer DEBUG_dt_##x(DEBUG_ss_##x.str()); +#define LINXI_DEBUG_TRANS(x) LINXI_DEBUG_CORE(x); +#define LINXI_DEBUG LINXI_DEBUG_TRANS(__LINE__); +#define LINXI_HERE TRACE("linxi_symmetry_checker", tout << "here\n";); +#else +#define LINXI_DEBUG { }((void) 0 ); +#define LINXI_HERE { }((void) 0 ); +#endif + + + +namespace nlsat { + struct Symmetry_Checker::imp { + // solver / + pmanager ± + unsynch_mpq_manager &qm; + const clause_vector &clauses; + const atom_vector &atoms; + const bool_vector &is_int; + const unsigned arith_var_num; + // vector vars_hash; + vector> vars_occur; + bool is_check; + var tx, ty; + struct Variable_Information { + unsigned long long hash_value; + unsigned deg; + var x; + bool is_int; + bool operator< (const Variable_Information &rhs) const { + return hash_value < rhs.hash_value; + } + bool operator== (const Variable_Information &rhs) const { + if (hash_value != rhs.hash_value) + return false; + if (deg != rhs.deg) + return false; + if (x != rhs.x) + return false; + if (is_int != rhs.is_int) + return false; + return true; + } + bool operator!= (const Variable_Information &rhs) const { + return !(*this == rhs); + } + }; + unsigned long long VAR_BASE = 601; + void collect_var_info(Variable_Information &var_info, var x, unsigned deg) { + LINXI_DEBUG; + if (is_check) { + if (x == tx) { + x = ty; + } + else if (x == ty) { + x = tx; + } + else { + // do nothing + } + } + else { + vars_occur[x].push_back(deg); + } + var_info.deg = deg; + var_info.x = x; + var_info.is_int = is_int[x]; + var_info.hash_value = 0; + for (unsigned i = 0; i < deg; ++i) { + var_info.hash_value = var_info.hash_value*VAR_BASE + (unsigned long long)x; + } + var_info.hash_value = var_info.hash_value*VAR_BASE + (unsigned long long)var_info.is_int; + } + struct Monomial_Information { + unsigned long long hash_value; + unsigned long long coef; + vector vars_info; + bool operator< (const Monomial_Information &rhs) const { + return hash_value < rhs.hash_value; + } + bool operator== (const Monomial_Information &rhs) const { + if (hash_value != rhs.hash_value) + return false; + if (coef != rhs.coef) + return false; + if (vars_info.size() != rhs.vars_info.size()) + return false; + for (unsigned i = 0, sz = vars_info.size(); i < sz; ++i) { + if (vars_info[i] != rhs.vars_info[i]) + return false; + } + return true; + } + bool operator!= (const Monomial_Information &rhs) const { + return !(*this == rhs); + } + }; + unsigned long long MONO_BASE = 99991; + + void collect_mono_info(Monomial_Information &mono_info, monomial *m, unsigned long long coef) { + LINXI_DEBUG; + unsigned sz = pm.size(m); + mono_info.vars_info.resize(sz); + for (unsigned i = 0; i < sz; ++i) { + collect_var_info(mono_info.vars_info[i], pm.get_var(m, i), pm.degree(m, i)); + } + mono_info.coef = coef; + mono_info.hash_value = coef; + std::sort(mono_info.vars_info.begin(), mono_info.vars_info.end()); + for (unsigned i = 0; i < sz; ++i) { + mono_info.hash_value = mono_info.hash_value*MONO_BASE + mono_info.vars_info[i].hash_value; + } + } + struct Polynomial_Information { + unsigned long long hash_value; + bool is_even; + vector monos_info; + bool operator< (const Polynomial_Information &rhs) const { + return hash_value < rhs.hash_value; + } + bool operator== (const Polynomial_Information &rhs) const { + if (hash_value != rhs.hash_value) + return false; + if (is_even != rhs.is_even) + return false; + if (monos_info.size() != rhs.monos_info.size()) + return false; + for (unsigned i = 0, sz = monos_info.size(); i < sz; ++i) { + if (monos_info[i] != rhs.monos_info[i]) + return false; + } + return true; + } + bool operator!= (const Polynomial_Information &rhs) const { + return !(*this == rhs); + } + }; + unsigned long long POLY_BASE = 99991; + void collect_poly_info(Polynomial_Information &poly_info, poly *p, bool is_even) { + LINXI_DEBUG; + unsigned sz = pm.size(p); + poly_info.monos_info.resize(sz); + for (unsigned i = 0; i < sz; ++i) { + collect_mono_info(poly_info.monos_info[i], pm.get_monomial(p, i), qm.get_uint64(pm.coeff(p, i))); + } + poly_info.hash_value = 0; + std::sort(poly_info.monos_info.begin(), poly_info.monos_info.end()); + for (unsigned i = 0; i < sz; ++i) { + poly_info.hash_value = poly_info.hash_value*POLY_BASE + poly_info.monos_info[i].hash_value; + } + poly_info.is_even = is_even; + if (is_even) { + poly_info.hash_value = poly_info.hash_value*poly_info.hash_value; + } + } + struct Atom_Information { + unsigned long long hash_value; + atom::kind akd; + vector polys_info; + bool operator< (const Atom_Information &rhs) const { + return hash_value < rhs.hash_value; + } + bool operator== (const Atom_Information &rhs) const { + if (hash_value != rhs.hash_value) + return false; + if (akd != rhs.akd) + return false; + if (polys_info.size() != rhs.polys_info.size()) + return false; + for (unsigned i = 0, sz = polys_info.size(); i < sz; ++i) { + if (polys_info[i] != rhs.polys_info[i]) + return false; + } + return true; + } + bool operator!= (const Atom_Information &rhs) const { + return !(*this == rhs); + } + }; + unsigned long long ATOM_BASE = 233; + void collect_atom_info(Atom_Information &atom_info, ineq_atom *iat) { + LINXI_DEBUG; + unsigned sz = iat->size(); + atom_info.polys_info.resize(sz); + for (unsigned i = 0; i < sz; ++i) { + collect_poly_info(atom_info.polys_info[i], iat->p(i), iat->is_even(i)); + } + atom_info.hash_value = 0; + std::sort(atom_info.polys_info.begin(), atom_info.polys_info.end()); + for (unsigned i = 0; i < sz; ++i) { + atom_info.hash_value = atom_info.hash_value*ATOM_BASE + atom_info.polys_info[i].hash_value; + } + atom_info.akd = iat->get_kind(); + atom_info.hash_value = atom_info.hash_value*ATOM_BASE + (unsigned long long)atom_info.akd; + } + struct Literal_Information { + unsigned long long hash_value; + vector atom_info; // not atoms + bool operator< (const Literal_Information &rhs) const { + return hash_value < rhs.hash_value; + } + bool operator== (const Literal_Information &rhs) const { + if (hash_value != rhs.hash_value) + return false; + if (atom_info.size() != rhs.atom_info.size()) + return false; + for (unsigned i = 0, sz = atom_info.size(); i < sz; ++i) { + if (atom_info[i] != rhs.atom_info[i]) + return false; + } + return true; + } + bool operator!= (const Literal_Information &rhs) const { + return !(*this == rhs); + } + }; + void collect_lit_info(Literal_Information &lit_info, literal lit) { + LINXI_DEBUG; + atom *at = atoms[lit.var()]; + if (at == nullptr || !at->is_ineq_atom()) { + lit_info.hash_value = lit.to_uint(); + } + else { + lit_info.atom_info.resize(1); + collect_atom_info(lit_info.atom_info[0], to_ineq_atom(at)); + lit_info.hash_value = lit_info.atom_info[0].hash_value; + } + } + struct Clause_Information { + unsigned long long hash_value; + vector lits_info; + bool operator< (const Clause_Information &rhs) const { + return hash_value < rhs.hash_value; + } + bool operator== (const Clause_Information &rhs) const { + if (hash_value != rhs.hash_value) + return false; + if (lits_info.size() != rhs.lits_info.size()) + return false; + for (unsigned i = 0, sz = lits_info.size(); i < sz; ++i) { + if (lits_info[i] != rhs.lits_info[i]) + return false; + } + return true; + } + bool operator!= (const Clause_Information &rhs) const { + return !(*this == rhs); + } + }; + unsigned long long CLA_BASE = 9973; + void collect_cla_info(Clause_Information &cla_info, clause *cla) { + LINXI_DEBUG; + unsigned sz = cla->size(); + cla_info.lits_info.resize(sz); + for (unsigned i = 0; i < sz; ++i) { + literal lit = (*cla)[i]; + collect_lit_info(cla_info.lits_info[i], lit); + } + cla_info.hash_value = 0; + std::sort(cla_info.lits_info.begin(), cla_info.lits_info.end()); + for (unsigned i = 0; i < sz; ++i) { + cla_info.hash_value = cla_info.hash_value*CLA_BASE + cla_info.lits_info[i].hash_value; + } + } + + void collect_clas_info(vector &clas_info) { + LINXI_DEBUG; + unsigned sz = clauses.size(); + clas_info.resize(sz); + for (unsigned i = 0; i < sz; ++i) { + collect_cla_info(clas_info[i], clauses[i]); + } + std::sort(clas_info.begin(), clas_info.end()); + if (!is_check) { + for (unsigned i = 0; i < arith_var_num; ++i) { + std::sort(vars_occur[i].begin(), vars_occur[i].begin()); + } + } + } + vector ori_clas_info; + imp(pmanager &_pm, unsynch_mpq_manager &_qm, const clause_vector &_clauses, const atom_vector &_atoms, const bool_vector &_is_int, const unsigned &_arith_var_num) : + // sol(_sol), + pm(_pm), + qm(_qm), + clauses(_clauses), + atoms(_atoms), + is_int(_is_int), + arith_var_num(_arith_var_num), + is_check(false) { + vars_occur.resize(arith_var_num); + collect_clas_info(ori_clas_info); + // vars_hash.resize(arith_var_num, 0); + } + vector check_clas_info; + bool check_occur_same(var x, var y) { + if (vars_occur[x].size() != vars_occur[y].size()) + return false; + for (unsigned i = 0, sz = vars_occur[x].size(); i < sz; ++i) { + if (vars_occur[x][i] != vars_occur[y][i]) + return false; + } + return true; + } + bool check_symmetry(var x, var y) { + if (!check_occur_same(x, y)) { + return false; + } + is_check = true; + tx = x, ty = y; + collect_clas_info(check_clas_info); + for (unsigned i = 0, sz = clauses.size(); i < sz; ++i) { + if (ori_clas_info[i] != check_clas_info[i]) + return false; + } + return true; + } + }; + Symmetry_Checker::Symmetry_Checker(pmanager &_pm, unsynch_mpq_manager &_qm, const clause_vector &_clauses, const atom_vector &_atoms, const bool_vector &_is_int, const unsigned &_arith_var_num) { + LINXI_DEBUG; + // m_imp = alloc(imp, _sol, _pm, _am, _clauses, _learned, _atoms, _arith_var_num); + m_imp = alloc(imp, _pm, _qm, _clauses, _atoms, _is_int, _arith_var_num); + } + Symmetry_Checker::~Symmetry_Checker() { + LINXI_DEBUG; + dealloc(m_imp); + } + // bool Symmetry_Checker::operator()() { + // LINXI_DEBUG; + + // } + bool Symmetry_Checker::check_symmetry(var x, var y) { + return m_imp->check_symmetry(x, y); + } +} \ No newline at end of file diff --git a/src/nlsat/nlsat_symmetry_checker.h b/src/nlsat/nlsat_symmetry_checker.h new file mode 100644 index 000000000..1db5cb24b --- /dev/null +++ b/src/nlsat/nlsat_symmetry_checker.h @@ -0,0 +1,13 @@ +#include "nlsat/nlsat_clause.h" + +namespace nlsat { + class Symmetry_Checker { + struct imp; + imp * m_imp; + public: + // Simple_Checker(solver &_sol, pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, clause_vector &_learned, const atom_vector &_atoms, const unsigned &_arith_var_num); + Symmetry_Checker(pmanager &_pm, unsynch_mpq_manager &_qm, const clause_vector &_clauses, const atom_vector &_atoms, const bool_vector &_is_int, const unsigned &_arith_var_num); + ~Symmetry_Checker(); + bool check_symmetry(var x, var y); + }; +} \ No newline at end of file diff --git a/src/nlsat/nlsat_variable_ordering_strategy.cpp b/src/nlsat/nlsat_variable_ordering_strategy.cpp new file mode 100644 index 000000000..8c4723fd3 --- /dev/null +++ b/src/nlsat/nlsat_variable_ordering_strategy.cpp @@ -0,0 +1,282 @@ +#include "nlsat/nlsat_variable_ordering_strategy.h" + +namespace nlsat { + struct VOS_Var_Info_Collector::imp { + pmanager & pm; + atom_vector const & m_atoms; + unsigned num_vars; + Variable_Ordering_Strategy_Type m_vos_type; + + /** Maximum degree of this variable. */ + unsigned_vector m_max_degree; + /** Sum of degrees of this variable within all polynomials. */ + unsigned_vector m_sum_poly_degree; + /** Number of polynomials that contain this variable. */ + unsigned_vector m_num_polynomials; + + /** Maximum degree of the leading coefficient of this variable. */ + unsigned_vector m_max_lc_degree; + /** Maximum of total degrees of terms that contain this variable. */ + unsigned_vector m_max_terms_tdegree; + /** Sum of degrees of this variable within all terms. */ + unsigned_vector m_sum_term_degree; + /** Number of terms that contain this variable. */ + unsigned_vector m_num_terms; + + + unsigned_vector m_num_uni; + numeral_vector m_coeffs; + + + imp(pmanager & _pm, atom_vector const & atoms, unsigned _num_vars, unsigned _vos_type): + pm(_pm), + m_atoms(atoms), + num_vars(_num_vars), + m_vos_type(Variable_Ordering_Strategy_Type(_vos_type)) { + + m_max_degree.resize(num_vars, 0); + m_sum_poly_degree.resize(num_vars, 0); + m_num_polynomials.resize(num_vars, 0); + + if (m_vos_type != ONLYPOLY) { + m_max_lc_degree.resize(num_vars, 0); + m_max_terms_tdegree.resize(num_vars, 0); + m_sum_term_degree.resize(num_vars, 0); + m_num_terms.resize(num_vars, 0); + + + m_num_uni.resize(num_vars, 0); + m_coeffs.resize(num_vars, 0); + + } + } + + void collect(monomial * m) { + unsigned mdeg = 0; + for (unsigned i = 0, sz = pm.size(m); i < sz; ++i) { + var x = pm.get_var(m, i); + mdeg += pm.degree_of(m, x); + ++m_num_terms[x]; + } + + for (unsigned i = 0, sz = pm.size(m); i < sz; ++i) { + var x = pm.get_var(m, i); + m_sum_term_degree[x] += mdeg; + if (mdeg > m_max_terms_tdegree[x]) + m_max_terms_tdegree[x] = mdeg; + unsigned lc_deg = mdeg - pm.degree_of(m, x); + if (lc_deg > m_max_lc_degree[x]) + m_max_lc_degree[x] = lc_deg; + } + } + + void collect(poly * p) { + var_vector vec_vars; + pm.vars(p, vec_vars); + + if (m_vos_type == UNIVARIATE) { + if (vec_vars.size() == 1) + ++m_num_uni[vec_vars[0]]; + } + + for (unsigned i = 0, sz = vec_vars.size(); i < sz; ++i) { + var x = vec_vars[i]; + unsigned k = pm.degree(p, x); + ++m_num_polynomials[x]; + m_sum_poly_degree[x] += k; + if (k > m_max_degree[x]) + m_max_degree[x] = k; + + if (m_vos_type == FEATURE){ + for (unsigned kl = 0; kl <= k; kl++) { + scoped_numeral curr(pm.m()); + if (pm.const_coeff(p, x, kl, curr)) { + pm.m().abs(curr); + if (pm.m().gt(curr, m_coeffs[x])) { + pm.m().set(m_coeffs[x], curr); + } + } + } + } + + } + + if (m_vos_type != ONLYPOLY && m_vos_type != UNIVARIATE){ + for (unsigned i = 0, sz = pm.size(p); i < sz; ++i) { + collect(pm.get_monomial(p, i)); + } + } + } + + void collect(literal l) { + bool_var b = l.var(); + atom * a = m_atoms[b]; + if (a == nullptr) + return; + if (a->is_ineq_atom()) { + unsigned sz = to_ineq_atom(a)->size(); + for (unsigned i = 0; i < sz; i++) { + collect(to_ineq_atom(a)->p(i)); + } + } + else { + collect(to_root_atom(a)->p()); + } + } + + void collect(clause const & c) { + unsigned sz = c.size(); + for (unsigned i = 0; i < sz; i++) + collect(c[i]); + } + + void collect(clause_vector const & cs) { + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) + collect(*(cs[i])); + } + + + struct univariate_reorder_lt { + VOS_Var_Info_Collector::imp const *m_info; + univariate_reorder_lt(VOS_Var_Info_Collector::imp const *info):m_info(info) {} + bool operator()(var x, var y) const { + if (m_info->m_num_uni[x] != m_info->m_num_uni[y]) + return m_info->m_num_uni[x] > m_info->m_num_uni[y]; + return x < y; + } + }; + + struct feature_reorder_lt { + VOS_Var_Info_Collector::imp const *m_info; + feature_reorder_lt(VOS_Var_Info_Collector::imp const * info): m_info(info){} + bool operator()(var x, var y) const { + if (m_info->m_max_degree[x] != m_info->m_max_degree[y]) + return m_info->m_max_degree[x] > m_info->m_max_degree[y]; + if (m_info->m_max_terms_tdegree[x] != m_info->m_max_terms_tdegree[y]) + return m_info->m_max_terms_tdegree[x] > m_info->m_max_terms_tdegree[y]; + if (!m_info->pm.m().eq(m_info->m_coeffs[x], m_info->m_coeffs[y])) { + return m_info->pm.m().lt(m_info->m_coeffs[x], m_info->m_coeffs[y]); + } + return x < y; + } + }; + struct brown_reorder_lt { + VOS_Var_Info_Collector::imp const *m_info; + brown_reorder_lt(VOS_Var_Info_Collector::imp const *info):m_info(info) {} + bool operator()(var x, var y) const { + // if (a.max_degree != b.max_degree) + // return a.max_degree > b.max_degree; + // if (a.max_terms_tdegree != b.max_terms_tdegree) + // return a.max_terms_tdegree > b.max_terms_tdegree; + // return a.num_terms > b.num_terms; + if (m_info->m_max_degree[x] != m_info->m_max_degree[y]) + return m_info->m_max_degree[x] > m_info->m_max_degree[y]; + if (m_info->m_max_terms_tdegree[x] != m_info->m_max_terms_tdegree[y]) + return m_info->m_max_terms_tdegree[x] > m_info->m_max_terms_tdegree[y]; + if (m_info->m_num_terms[x] != m_info->m_num_terms[y]) + return m_info->m_num_terms[x] > m_info->m_num_terms[y]; + return x < y; + } + }; + struct triangular_reorder_lt { + const VOS_Var_Info_Collector::imp *m_info; + triangular_reorder_lt(VOS_Var_Info_Collector::imp const *info):m_info(info) {} + bool operator()(var x, var y) const { + // if (a.max_degree != b.max_degree) + // return a.max_degree > b.max_degree; + // if (a.max_lc_degree != b.max_lc_degree) + // return a.max_lc_degree > b.max_lc_degree; + // return a.sum_poly_degree > b.sum_poly_degree; + if (m_info->m_max_degree[x] != m_info->m_max_degree[y]) + return m_info->m_max_degree[x] > m_info->m_max_degree[y]; + if (m_info->m_max_lc_degree[x] != m_info->m_max_lc_degree[y]) + return m_info->m_max_lc_degree[x] > m_info->m_max_lc_degree[y]; + if (m_info->m_sum_poly_degree[x] != m_info->m_sum_poly_degree[y]) + return m_info->m_sum_poly_degree[x] > m_info->m_sum_poly_degree[y]; + return x < y; + } + }; + struct onlypoly_reorder_lt { + const VOS_Var_Info_Collector::imp *m_info; + onlypoly_reorder_lt(VOS_Var_Info_Collector::imp const *info):m_info(info) {} + bool operator()(var x, var y) const { + // high degree first + if (m_info->m_max_degree[x] != m_info->m_max_degree[y]) + return m_info->m_max_degree[x] > m_info->m_max_degree[y]; + // + if (m_info->m_sum_poly_degree[x] != m_info->m_sum_poly_degree[y]) + return m_info->m_sum_poly_degree[x] > m_info->m_sum_poly_degree[y]; + // more constrained first + if (m_info->m_num_polynomials[x] != m_info->m_num_polynomials[y]) + return m_info->m_num_polynomials[x] > m_info->m_num_polynomials[y]; + return x < y; + } + }; + bool check_invariant() const {return true;} // what is the invariant + void operator()(var_vector &perm) { + var_vector new_order; + for (var x = 0; x < num_vars; x++) { + new_order.push_back(x); + } + if (m_vos_type == BROWN) { + std::sort(new_order.begin(), new_order.end(), brown_reorder_lt(this)); + } + else if (m_vos_type == TRIANGULAR) { + std::sort(new_order.begin(), new_order.end(), triangular_reorder_lt(this)); + } + else if (m_vos_type == ONLYPOLY) { + std::sort(new_order.begin(), new_order.end(), onlypoly_reorder_lt(this)); + } + + else if(m_vos_type == UNIVARIATE){ + std::sort(new_order.begin(), new_order.end(), univariate_reorder_lt(this)); + } + else if(m_vos_type == FEATURE){ + std::sort(new_order.begin(), new_order.end(), feature_reorder_lt(this)); + } + + else { + UNREACHABLE(); + } + TRACE("linxi_reorder", + tout << "new order: "; + for (unsigned i = 0; i < num_vars; i++) + tout << new_order[i] << " "; + tout << "\n"; + ); + perm.resize(num_vars, 0); + for (var x = 0; x < num_vars; x++) { + perm[new_order[x]] = x; + } + + SASSERT(check_invariant()); + } + // std::ostream& display(std::ostream & out, display_var_proc const & proc) { + // unsigned sz = m_num_occs.size(); + // for (unsigned i = 0; i < sz; i++) { + // proc(out, i); out << " -> " << m_max_degree[i] << " : " << m_num_occs[i] << "\n"; + // } + // return out; + // } + + // std::ostream& display(std::ostream & out, display_var_proc const & proc) { + // for (unsigned i = 0; i < num_vars; ++i) { + // proc(out, i); out << " -> " << m_max_degree[i] << " : " << m_sum_poly_degree[i] << "\n"; + // } + // return out; + // } + }; + VOS_Var_Info_Collector::VOS_Var_Info_Collector(pmanager & _pm, atom_vector const & _atoms, unsigned _num_vars, unsigned _vos_type) { + m_imp = alloc(imp, _pm, _atoms, _num_vars, _vos_type); + } + VOS_Var_Info_Collector::~VOS_Var_Info_Collector() { + dealloc(m_imp); + } + void VOS_Var_Info_Collector::collect(clause_vector const & cs) { + m_imp->collect(cs); + } + void VOS_Var_Info_Collector::operator()(var_vector &perm) { + m_imp->operator()(perm); + } +} diff --git a/src/nlsat/nlsat_variable_ordering_strategy.h b/src/nlsat/nlsat_variable_ordering_strategy.h new file mode 100644 index 000000000..6e01825c3 --- /dev/null +++ b/src/nlsat/nlsat_variable_ordering_strategy.h @@ -0,0 +1,27 @@ +#include "nlsat/nlsat_clause.h" + + +#include "math/polynomial/algebraic_numbers.h" +#include "math/polynomial/polynomial.h" + + +namespace nlsat { + + typedef polynomial::manager::scoped_numeral scoped_numeral; + typedef polynomial::manager::numeral_vector numeral_vector; + + + // enum Variable_Ordering_Strategy_Type {NONE = 0, BROWN, TRIANGULAR, ONLYPOLY}; + + enum Variable_Ordering_Strategy_Type {NONE = 0, BROWN, TRIANGULAR, ONLYPOLY, UNIVARIATE, FEATURE, ROOT}; + + class VOS_Var_Info_Collector { + struct imp; + imp * m_imp; + public: + VOS_Var_Info_Collector(pmanager & _pm, atom_vector const & atoms, unsigned _num_vars, unsigned _vos_type); + ~VOS_Var_Info_Collector(); + void operator()(var_vector &perm); + void collect(clause_vector const & cs); + }; +} \ No newline at end of file diff --git a/src/tactic/smtlogics/qfnra_tactic.cpp b/src/tactic/smtlogics/qfnra_tactic.cpp index b9fec4366..5ecfa2426 100644 --- a/src/tactic/smtlogics/qfnra_tactic.cpp +++ b/src/tactic/smtlogics/qfnra_tactic.cpp @@ -23,6 +23,8 @@ Notes: #include "nlsat/tactic/qfnra_nlsat_tactic.h" #include "tactic/smtlogics/smt_tactic.h" +#include "tactic/smtlogics/qflra_tactic.h" + static tactic * mk_qfnra_sat_solver(ast_manager& m, params_ref const& p, unsigned bv_size) { params_ref nra2sat_p = p; nra2sat_p.set_uint("nla2bv_max_bv_size", p.get_uint("nla2bv_max_bv_size", bv_size)); @@ -32,24 +34,305 @@ static tactic * mk_qfnra_sat_solver(ast_manager& m, params_ref const& p, unsigne mk_fail_if_undecided_tactic()); } +tactic * mk_multilinear_ls_tactic(ast_manager & m, params_ref const & p, unsigned ls_time = 60) { + params_ref p_mls = p; + p_mls.set_bool("use_ls", true); + p_mls.set_uint("ls_time",ls_time); + return using_params(mk_smt_tactic(m), p_mls); +} + +tactic * linxi_mk_qfnra_very_small_solver(ast_manager& m, params_ref const& p) { + ptr_vector ts; + { + params_ref p_sc = p; + p_sc.set_bool("linxi_simple_check", true); + // p_sc.set_uint("seed", 997); + ts.push_back(try_for(and_then(mk_qfnra_nlsat_tactic(m, p_sc), mk_fail_if_undecided_tactic()), 10 * 1000)); + } + { + params_ref p_heuristic = p; + // p_heuristic.set_uint("seed", 233); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_heuristic), 4 * 1000)); + + params_ref p_order_4 = p; + p_order_4.set_uint("linxi_variable_ordering_strategy", 4); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_4), 4 * 1000)); + + params_ref p_order_3 = p; + p_order_3.set_uint("linxi_variable_ordering_strategy", 3); + // p_order_3.set_uint("seed", 17); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_3), 6 * 1000)); + + params_ref p_order_1 = p; + p_order_1.set_uint("linxi_variable_ordering_strategy", 1); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_1), 8 * 1000)); + + params_ref p_order_5 = p; + p_order_5.set_uint("linxi_variable_ordering_strategy", 5); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_5), 8 * 1000)); + + params_ref p_order_2 = p; + p_order_2.set_uint("linxi_variable_ordering_strategy", 2); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_2), 10 * 1000)); + } + { + ts.push_back(mk_multilinear_ls_tactic(m, p, 60)); + } + { + params_ref p_l = p; + p_l.set_bool("arith.greatest_error_pivot", true); + ts.push_back(and_then(try_for(using_params(mk_smt_tactic(m), p_l), 300 * 1000), mk_fail_if_undecided_tactic())); + } + for (unsigned i = 0; i < 200; ++i) { // 3s * 200 = 600s + params_ref p_i = p; + p_i.set_uint("seed", i); + p_i.set_bool("shuffle_vars", true); + // if ((i & 1) == 0) + // p_i.set_bool("randomize", false); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_i), 3 * 1000)); + } + { + ts.push_back(mk_qfnra_nlsat_tactic(m, p)); + } + return or_else(ts.size(), ts.data()); +} + +tactic * linxi_mk_qfnra_small_solver(ast_manager& m, params_ref const& p) { + ptr_vector ts; + { + params_ref p_sc = p; + p_sc.set_bool("linxi_simple_check", true); + // p_sc.set_uint("seed", 997); + ts.push_back(try_for(and_then(mk_qfnra_nlsat_tactic(m, p_sc), mk_fail_if_undecided_tactic()), 20 * 1000)); + } + { + params_ref p_heuristic = p; + // p_heuristic.set_uint("seed", 233); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_heuristic), 5 * 1000)); + + params_ref p_order_4 = p; + p_order_4.set_uint("linxi_variable_ordering_strategy", 4); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_4), 5 * 1000)); + + params_ref p_order_3 = p; + p_order_3.set_uint("linxi_variable_ordering_strategy", 3); + // p_order_3.set_uint("seed", 17); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_3), 10 * 1000)); + + params_ref p_order_1 = p; + p_order_1.set_uint("linxi_variable_ordering_strategy", 1); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_1), 15 * 1000)); + + + params_ref p_order_5 = p; + p_order_5.set_uint("linxi_variable_ordering_strategy", 5); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_5), 15 * 1000)); + + + params_ref p_order_2 = p; + p_order_2.set_uint("linxi_variable_ordering_strategy", 2); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_2), 20 * 1000)); + } + { + ts.push_back(mk_multilinear_ls_tactic(m, p, 70)); + } + { + params_ref p_l = p; + p_l.set_bool("arith.greatest_error_pivot", true); + ts.push_back(and_then(try_for(using_params(mk_smt_tactic(m), p_l), 350 * 1000), mk_fail_if_undecided_tactic())); + } + for (unsigned i = 0; i < 100; ++i) { // 5s * 100 = 500s + params_ref p_i = p; + p_i.set_uint("seed", i); + p_i.set_bool("shuffle_vars", true); + // if ((i & 1) == 0) + // p_i.set_bool("randomize", false); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_i), 5 * 1000)); + } + { + ts.push_back(mk_qfnra_nlsat_tactic(m, p)); + } + return or_else(ts.size(), ts.data()); +} + +tactic * linxi_mk_qfnra_middle_solver(ast_manager& m, params_ref const& p) { + ptr_vector ts; + { + params_ref p_sc = p; + p_sc.set_bool("linxi_simple_check", true); + // p_sc.set_uint("seed", 997); + ts.push_back(try_for(and_then(mk_qfnra_nlsat_tactic(m, p_sc), mk_fail_if_undecided_tactic()), 30 * 1000)); + } + { + params_ref p_heuristic = p; + // p_heuristic.set_uint("seed", 233); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_heuristic), 10 * 1000)); + + + params_ref p_order_4 = p; + p_order_4.set_uint("linxi_variable_ordering_strategy", 4); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_4), 15 * 1000)); + + + params_ref p_order_3 = p; + p_order_3.set_uint("linxi_variable_ordering_strategy", 3); + // p_order_3.set_uint("seed", 17); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_3), 15 * 1000)); + + params_ref p_order_1 = p; + p_order_1.set_uint("linxi_variable_ordering_strategy", 1); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_1), 20 * 1000)); + + + params_ref p_order_5 = p; + p_order_5.set_uint("linxi_variable_ordering_strategy", 5); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_5), 20 * 1000)); + + + params_ref p_order_2 = p; + p_order_2.set_uint("linxi_variable_ordering_strategy", 2); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_2), 25 * 1000)); + } + { + ts.push_back(mk_multilinear_ls_tactic(m, p, 80)); + } + { + params_ref p_l = p; + p_l.set_bool("arith.greatest_error_pivot", true); + ts.push_back(and_then(try_for(using_params(mk_smt_tactic(m), p_l), 375 * 1000), mk_fail_if_undecided_tactic())); + } + for (unsigned i = 0; i < 40; ++i) { // 10s * 40 = 400s + params_ref p_i = p; + p_i.set_uint("seed", i); + p_i.set_bool("shuffle_vars", true); + // if ((i & 1) == 0) + // p_i.set_bool("randomize", false); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_i), 10 * 1000)); + } + { + ts.push_back(mk_qfnra_nlsat_tactic(m, p)); + } + return or_else(ts.size(), ts.data()); +} + +tactic * linxi_mk_qfnra_large_solver(ast_manager& m, params_ref const& p) { + ptr_vector ts; + { + params_ref p_sc = p; + p_sc.set_bool("linxi_simple_check", true); + // p_sc.set_uint("seed", 997); + ts.push_back(try_for(and_then(mk_qfnra_nlsat_tactic(m, p_sc), mk_fail_if_undecided_tactic()), 50 * 1000)); + } + { + + params_ref p_order_4 = p; + p_order_4.set_uint("linxi_variable_ordering_strategy", 4); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_4), 15 * 1000)); + + + params_ref p_order_3 = p; + p_order_3.set_uint("linxi_variable_ordering_strategy", 3); + // p_order_3.set_uint("seed", 17); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_3), 30 * 1000)); + + params_ref p_order_1 = p; + p_order_1.set_uint("linxi_variable_ordering_strategy", 1); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_1), 40 * 1000)); + + + params_ref p_order_5 = p; + p_order_5.set_uint("linxi_variable_ordering_strategy", 5); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_5), 40 * 1000)); + + + params_ref p_order_2 = p; + p_order_2.set_uint("linxi_variable_ordering_strategy", 2); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_2), 50 * 1000)); + } + { + ts.push_back(mk_multilinear_ls_tactic(m, p, 90)); + } + { + params_ref p_l = p; + p_l.set_bool("arith.greatest_error_pivot", true); + ts.push_back(and_then(try_for(using_params(mk_smt_tactic(m), p_l), 400 * 1000), mk_fail_if_undecided_tactic())); + } + for (unsigned i = 0; i < 10; ++i) { // 20s * 10 = 200s + params_ref p_i = p; + p_i.set_uint("seed", i); + p_i.set_bool("shuffle_vars", true); + // if ((i & 1) == 0) + // p_i.set_bool("randomize", false); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_i), 20 * 1000)); + } + { + ts.push_back(mk_qfnra_nlsat_tactic(m, p)); + } + return or_else(ts.size(), ts.data()); +} + +tactic * linxi_mk_qfnra_very_large_solver(ast_manager& m, params_ref const& p) { + ptr_vector ts; + { + params_ref p_sc = p; + p_sc.set_bool("linxi_simple_check", true); + // p_sc.set_uint("seed", 997); + ts.push_back(try_for(and_then(mk_qfnra_nlsat_tactic(m, p_sc), mk_fail_if_undecided_tactic()), 100 * 1000)); + } + { + params_ref p_order_1 = p; + p_order_1.set_uint("linxi_variable_ordering_strategy", 1); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_1), 80 * 1000)); + + + params_ref p_order_5 = p; + p_order_5.set_uint("linxi_variable_ordering_strategy", 5); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_5), 80 * 1000)); + + + params_ref p_order_2 = p; + p_order_2.set_uint("linxi_variable_ordering_strategy", 2); + ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_2), 100 * 1000)); + } + { + ts.push_back(mk_multilinear_ls_tactic(m, p, 100)); + } + { + params_ref p_l = p; + p_l.set_bool("arith.greatest_error_pivot", true); + ts.push_back(and_then(try_for(using_params(mk_smt_tactic(m), p_l), 425 * 1000), mk_fail_if_undecided_tactic())); + } + { + ts.push_back(mk_qfnra_nlsat_tactic(m, p)); + } + return or_else(ts.size(), ts.data()); +} + +const double VERY_SMALL_THRESHOLD = 30.0; +const double SMALL_THRESHOLD = 80.0; +const double MIDDLE_THRESHOLD = 300.0; +const double LARGE_THRESHOLD = 600.0; +tactic * linxi_mk_qfnra_mixed_solver(ast_manager& m, params_ref const& p) { + return cond(mk_lt(mk_memory_probe(), mk_const_probe(VERY_SMALL_THRESHOLD)), + linxi_mk_qfnra_very_small_solver(m, p), + cond(mk_lt(mk_memory_probe(), mk_const_probe(SMALL_THRESHOLD)), + linxi_mk_qfnra_small_solver(m, p), + cond(mk_lt(mk_memory_probe(), mk_const_probe(MIDDLE_THRESHOLD)), + linxi_mk_qfnra_middle_solver(m, p), + cond(mk_lt(mk_memory_probe(), mk_const_probe(LARGE_THRESHOLD)), + linxi_mk_qfnra_large_solver(m, p), + linxi_mk_qfnra_very_large_solver(m, p) + ) + ) + ) + ); +} + tactic * mk_qfnra_tactic(ast_manager & m, params_ref const& p) { - params_ref p0 = p; - p0.set_bool("inline_vars", true); - params_ref p1 = p; - p1.set_uint("seed", 11); - p1.set_bool("factor", false); - params_ref p2 = p; - p2.set_uint("seed", 13); - p2.set_bool("factor", false); return and_then(mk_simplify_tactic(m, p), mk_propagate_values_tactic(m, p), - or_else(try_for(mk_qfnra_nlsat_tactic(m, p0), 5000), - try_for(mk_qfnra_nlsat_tactic(m, p1), 10000), - mk_qfnra_sat_solver(m, p, 4), - and_then(try_for(mk_smt_tactic(m), 5000), mk_fail_if_undecided_tactic()), - mk_qfnra_sat_solver(m, p, 6), - mk_qfnra_nlsat_tactic(m, p2))); + // mk_multilinear_ls_tactic(m, p) + linxi_mk_qfnra_mixed_solver(m, p) + ); } - - From 4b3a06a3c5175637aa0dd0de22392f32378302f8 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 8 Aug 2024 12:16:41 -1000 Subject: [PATCH 053/187] port hybridSMT Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_solver.cpp | 4219 ++++++++++++++++++++++++++++++++++++ 1 file changed, 4219 insertions(+) create mode 100644 src/nlsat/nlsat_solver.cpp diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp new file mode 100644 index 000000000..d50752460 --- /dev/null +++ b/src/nlsat/nlsat_solver.cpp @@ -0,0 +1,4219 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + nlsat_solver.cpp + +Abstract: + + Nonlinear arithmetic satisfiability procedure. The procedure is + complete for nonlinear real arithmetic, but it also has limited + support for integers. + +Author: + + Leonardo de Moura (leonardo) 2012-01-02. + +Revision History: + +--*/ +#include "util/z3_exception.h" +#include "util/chashtable.h" +#include "util/id_gen.h" +#include "util/map.h" +#include "util/dependency.h" +#include "util/permutation.h" +#include "math/polynomial/algebraic_numbers.h" +#include "math/polynomial/polynomial_cache.h" +#include "nlsat/nlsat_solver.h" +#include "nlsat/nlsat_clause.h" +#include "nlsat/nlsat_assignment.h" +#include "nlsat/nlsat_justification.h" +#include "nlsat/nlsat_evaluator.h" +#include "nlsat/nlsat_explain.h" +#include "nlsat/nlsat_params.hpp" +#include "nlsat/nlsat_simplify.h" +#include "nlsat/nlsat_simple_checker.h" +#include "nlsat/nlsat_variable_ordering_strategy.h" +#include "nlsat/nlsat_symmetry_checker.h" + +#define NLSAT_EXTRA_VERBOSE + +#ifdef NLSAT_EXTRA_VERBOSE +#define NLSAT_VERBOSE(CODE) IF_VERBOSE(10, CODE) +#else +#define NLSAT_VERBOSE(CODE) ((void)0) +#endif + +namespace nlsat { + + + typedef chashtable ineq_atom_table; + typedef chashtable root_atom_table; + + // for apply_permutation procedure + void swap(clause * & c1, clause * & c2) noexcept { + std::swap(c1, c2); + } + + struct solver::ctx { + params_ref m_params; + reslimit& m_rlimit; + small_object_allocator m_allocator; + unsynch_mpq_manager m_qm; + pmanager m_pm; + anum_manager m_am; + bool m_incremental; + ctx(reslimit& rlim, params_ref const & p, bool incremental): + m_params(p), + m_rlimit(rlim), + m_allocator("nlsat"), + m_pm(rlim, m_qm, &m_allocator), + m_am(rlim, m_qm, p, &m_allocator), + m_incremental(incremental) + {} + }; + + struct solver::imp { + + + struct dconfig { + typedef imp value_manager; + typedef small_object_allocator allocator; + typedef void* value; + static const bool ref_count = false; + }; + + typedef dependency_manager assumption_manager; + typedef assumption_manager::dependency* _assumption_set; + + typedef obj_ref assumption_set_ref; + + + typedef polynomial::cache cache; + typedef ptr_vector interval_set_vector; + + + + ctx& m_ctx; + solver& m_solver; + reslimit& m_rlimit; + small_object_allocator& m_allocator; + bool m_incremental; + unsynch_mpq_manager& m_qm; + pmanager& m_pm; + cache m_cache; + anum_manager& m_am; + mutable assumption_manager m_asm; + assignment m_assignment, m_lo, m_hi; // partial interpretation + evaluator m_evaluator; + interval_set_manager & m_ism; + ineq_atom_table m_ineq_atoms; + root_atom_table m_root_atoms; + + + vector m_bounds; + + id_gen m_cid_gen; + clause_vector m_clauses; // set of clauses + clause_vector m_learned; // set of learned clauses + clause_vector m_valids; + + unsigned m_num_bool_vars; + atom_vector m_atoms; // bool_var -> atom + svector m_bvalues; // boolean assignment + unsigned_vector m_levels; // bool_var -> level + svector m_justifications; + vector m_bwatches; // bool_var (that are not attached to atoms) -> clauses where it is maximal + bool_vector m_dead; // mark dead boolean variables + id_gen m_bid_gen; + + simplify m_simplify; + + bool_vector m_is_int; // m_is_int[x] is true if variable is integer + vector m_watches; // var -> clauses where variable is maximal + interval_set_vector m_infeasible; // var -> to a set of interval where the variable cannot be assigned to. + atom_vector m_var2eq; // var -> to asserted equality + var_vector m_perm; // var -> var permutation of the variables + var_vector m_inv_perm; + // m_perm: internal -> external + // m_inv_perm: external -> internal + struct perm_display_var_proc : public display_var_proc { + var_vector & m_perm; + display_var_proc m_default_display_var; + display_var_proc const * m_proc; // display external var ids + perm_display_var_proc(var_vector & perm): + m_perm(perm), + m_proc(nullptr) { + } + std::ostream& operator()(std::ostream & out, var x) const override { + if (m_proc == nullptr) + m_default_display_var(out, x); + else + (*m_proc)(out, m_perm[x]); + return out; + } + }; + perm_display_var_proc m_display_var; + + display_assumption_proc const* m_display_assumption; + struct display_literal_assumption : public display_assumption_proc { + imp& i; + literal_vector const& lits; + display_literal_assumption(imp& i, literal_vector const& lits): i(i), lits(lits) {} + std::ostream& operator()(std::ostream& out, assumption a) const override { + if (lits.begin() <= a && a < lits.end()) { + out << *((literal const*)a); + } + else if (i.m_display_assumption) { + (*i.m_display_assumption)(out, a); + } + return out; + } + + }; + struct scoped_display_assumptions { + imp& i; + display_assumption_proc const* m_save; + scoped_display_assumptions(imp& i, display_assumption_proc const& p): i(i), m_save(i.m_display_assumption) { + i.m_display_assumption = &p; + } + ~scoped_display_assumptions() { + i.m_display_assumption = m_save; + } + }; + + explain m_explain; + + bool_var m_bk; // current Boolean variable we are processing + var m_xk; // current arith variable we are processing + + unsigned m_scope_lvl; + + struct bvar_assignment {}; + struct stage {}; + struct trail { + enum kind { BVAR_ASSIGNMENT, INFEASIBLE_UPDT, NEW_LEVEL, NEW_STAGE, UPDT_EQ }; + kind m_kind; + union { + bool_var m_b; + interval_set * m_old_set; + atom * m_old_eq; + }; + trail(bool_var b, bvar_assignment):m_kind(BVAR_ASSIGNMENT), m_b(b) {} + trail(interval_set * old_set):m_kind(INFEASIBLE_UPDT), m_old_set(old_set) {} + trail(bool s, stage):m_kind(s ? NEW_STAGE : NEW_LEVEL) {} + trail(atom * a):m_kind(UPDT_EQ), m_old_eq(a) {} + }; + svector m_trail; + + anum m_zero; + + // configuration + unsigned long long m_max_memory; + unsigned m_lazy; // how lazy the solver is: 0 - satisfy all learned clauses, 1 - process only unit and empty learned clauses, 2 - use only conflict clauses for resolving conflicts + bool m_simplify_cores; + bool m_reorder; + bool m_randomize; + bool m_random_order; + unsigned m_random_seed; + bool m_inline_vars; + bool m_log_lemmas; + bool m_check_lemmas; + unsigned m_max_conflicts; + unsigned m_lemma_count; +//#linxi begin + bool m_linxi_simple_check; + unsigned m_linxi_variable_ordering_strategy; + bool m_linxi_symmetry_check; + bool m_linxi_set_0_more; + bool m_cell_sample; +//#linxi end + + struct stats { + unsigned m_simplifications; + unsigned m_restarts; + unsigned m_conflicts; + unsigned m_propagations; + unsigned m_decisions; + unsigned m_stages; + unsigned m_irrational_assignments; // number of irrational witnesses + void reset() { memset(this, 0, sizeof(*this)); } + stats() { reset(); } + }; + // statistics + stats m_stats; + + imp(solver& s, ctx& c): + m_ctx(c), + m_solver(s), + m_rlimit(c.m_rlimit), + m_allocator(c.m_allocator), + m_incremental(c.m_incremental), + m_qm(c.m_qm), + m_pm(c.m_pm), + m_cache(m_pm), + m_am(c.m_am), + m_asm(*this, m_allocator), + m_assignment(m_am), m_lo(m_am), m_hi(m_am), + m_evaluator(s, m_assignment, m_pm, m_allocator), + m_ism(m_evaluator.ism()), + m_num_bool_vars(0), + m_simplify(s, m_atoms, m_clauses, m_learned, m_pm), + m_display_var(m_perm), + m_display_assumption(nullptr), + m_explain(s, m_assignment, m_cache, m_atoms, m_var2eq, m_evaluator, nlsat_params(c.m_params).cell_sample()), + m_scope_lvl(0), + m_lemma(s), + m_lazy_clause(s), + m_lemma_assumptions(m_asm) { + updt_params(c.m_params); + reset_statistics(); + mk_true_bvar(); + m_lemma_count = 0; + } + + ~imp() { + clear(); + } + + void mk_true_bvar() { + bool_var b = mk_bool_var(); + SASSERT(b == true_bool_var); + literal true_lit(b, false); + mk_clause(1, &true_lit, false, nullptr); + } + + void updt_params(params_ref const & _p) { + nlsat_params p(_p); + m_max_memory = p.max_memory(); + m_lazy = p.lazy(); + m_simplify_cores = p.simplify_conflicts(); + bool min_cores = p.minimize_conflicts(); + m_reorder = p.reorder(); + m_randomize = p.randomize(); + m_max_conflicts = p.max_conflicts(); + m_random_order = p.shuffle_vars(); + m_random_seed = p.seed(); + m_inline_vars = p.inline_vars(); + m_log_lemmas = p.log_lemmas(); + m_check_lemmas = p.check_lemmas(); +//#linxi begin + m_linxi_simple_check = p.linxi_simple_check(); + m_linxi_variable_ordering_strategy = p.linxi_variable_ordering_strategy(); + m_linxi_symmetry_check = p.linxi_symmetry_check(); +//#linxi end + + + m_cell_sample = p.cell_sample(); + + + m_ism.set_seed(m_random_seed); + m_explain.set_simplify_cores(m_simplify_cores); + m_explain.set_minimize_cores(min_cores); + m_explain.set_factor(p.factor()); + m_am.updt_params(p.p); + } + + void reset() { + m_explain.reset(); + m_lemma.reset(); + m_lazy_clause.reset(); + undo_until_size(0); + del_clauses(); + del_unref_atoms(); + m_cache.reset(); + m_assignment.reset(); + m_lo.reset(); + m_hi.reset(); + } + + void clear() { + m_explain.reset(); + m_lemma.reset(); + m_lazy_clause.reset(); + undo_until_size(0); + del_clauses(); + del_unref_atoms(); + } + + void checkpoint() { + if (!m_rlimit.inc()) throw solver_exception(m_rlimit.get_cancel_msg()); + if (memory::get_allocation_size() > m_max_memory) throw solver_exception(Z3_MAX_MEMORY_MSG); + } + + // ----------------------- + // + // Basic + // + // ----------------------- + + unsigned num_bool_vars() const { + return m_num_bool_vars; + } + + unsigned num_vars() const { + return m_is_int.size(); + } + + bool is_int(var x) const { + return m_is_int[x]; + } + + void inc_ref(assumption) {} + + void dec_ref(assumption) {} + + void inc_ref(_assumption_set a) { + if (a != nullptr) m_asm.inc_ref(a); + } + + void dec_ref(_assumption_set a) { + if (a != nullptr) m_asm.dec_ref(a); + } + + void inc_ref(bool_var b) { + if (b == null_bool_var) + return; + atom * a = m_atoms[b]; + if (a == nullptr) + return; + TRACE("ref", display(tout << "inc: " << b << " " << a->ref_count() << " ", *a) << "\n";); + a->inc_ref(); + } + + void inc_ref(literal l) { + inc_ref(l.var()); + } + + void dec_ref(bool_var b) { + if (b == null_bool_var) + return; + atom * a = m_atoms[b]; + if (a == nullptr) + return; + SASSERT(a->ref_count() > 0); + a->dec_ref(); + TRACE("ref", display(tout << "dec: " << b << " " << a->ref_count() << " ", *a) << "\n";); + if (a->ref_count() == 0) + del(a); + } + + void dec_ref(literal l) { + dec_ref(l.var()); + } + + bool is_arith_atom(bool_var b) const { return m_atoms[b] != nullptr; } + + bool is_arith_literal(literal l) const { return is_arith_atom(l.var()); } + + var max_var(poly const * p) const { + return m_pm.max_var(p); + } + + var max_var(bool_var b) const { + if (!is_arith_atom(b)) + return null_var; + else + return m_atoms[b]->max_var(); + } + + var max_var(literal l) const { + return max_var(l.var()); + } + + /** + \brief Return the maximum variable occurring in cls. + */ + var max_var(unsigned sz, literal const * cls) const { + var x = null_var; + for (unsigned i = 0; i < sz; i++) { + literal l = cls[i]; + if (is_arith_literal(l)) { + var y = max_var(l); + if (x == null_var || y > x) + x = y; + } + } + return x; + } + + var max_var(clause const & cls) const { + return max_var(cls.size(), cls.data()); + } + + /** + \brief Return the maximum Boolean variable occurring in cls. + */ + bool_var max_bvar(clause const & cls) const { + bool_var b = null_bool_var; + for (literal l : cls) { + if (b == null_bool_var || l.var() > b) + b = l.var(); + } + return b; + } + + /** + \brief Return the degree of the maximal variable of the given atom + */ + unsigned degree(atom const * a) const { + if (a->is_ineq_atom()) { + unsigned max = 0; + unsigned sz = to_ineq_atom(a)->size(); + var x = a->max_var(); + for (unsigned i = 0; i < sz; i++) { + unsigned d = m_pm.degree(to_ineq_atom(a)->p(i), x); + if (d > max) + max = d; + } + return max; + } + else { + return m_pm.degree(to_root_atom(a)->p(), a->max_var()); + } + } + + /** + \brief Return the degree of the maximal variable in c + */ + unsigned degree(clause const & c) const { + var x = max_var(c); + if (x == null_var) + return 0; + unsigned max = 0; + for (literal l : c) { + atom const * a = m_atoms[l.var()]; + if (a == nullptr) + continue; + unsigned d = degree(a); + if (d > max) + max = d; + } + return max; + } + + // ----------------------- + // + // Variable, Atoms, Clauses & Assumption creation + // + // ----------------------- + + bool_var mk_bool_var_core() { + bool_var b = m_bid_gen.mk(); + m_num_bool_vars++; + m_atoms .setx(b, nullptr, nullptr); + m_bvalues .setx(b, l_undef, l_undef); + m_levels .setx(b, UINT_MAX, UINT_MAX); + m_justifications.setx(b, null_justification, null_justification); + m_bwatches .setx(b, clause_vector(), clause_vector()); + m_dead .setx(b, false, true); + return b; + } + + bool_var mk_bool_var() { + return mk_bool_var_core(); + } + + var mk_var(bool is_int) { + var x = m_pm.mk_var(); + register_var(x, is_int); + return x; + } + void register_var(var x, bool is_int) { + SASSERT(x == num_vars()); + m_is_int. push_back(is_int); + m_watches. push_back(clause_vector()); + m_infeasible.push_back(nullptr); + m_var2eq. push_back(nullptr); + m_perm. push_back(x); + m_inv_perm. push_back(x); + SASSERT(m_is_int.size() == m_watches.size()); + SASSERT(m_is_int.size() == m_infeasible.size()); + SASSERT(m_is_int.size() == m_var2eq.size()); + SASSERT(m_is_int.size() == m_perm.size()); + SASSERT(m_is_int.size() == m_inv_perm.size()); + } + + bool_vector m_found_vars; + void vars(literal l, var_vector& vs) { + vs.reset(); + atom * a = m_atoms[l.var()]; + if (a == nullptr) { + + } + else if (a->is_ineq_atom()) { + unsigned sz = to_ineq_atom(a)->size(); + var_vector new_vs; + for (unsigned j = 0; j < sz; j++) { + m_found_vars.reset(); + m_pm.vars(to_ineq_atom(a)->p(j), new_vs); + for (unsigned i = 0; i < new_vs.size(); ++i) { + if (!m_found_vars.get(new_vs[i], false)) { + m_found_vars.setx(new_vs[i], true, false); + vs.push_back(new_vs[i]); + } + } + } + } + else { + m_pm.vars(to_root_atom(a)->p(), vs); + //vs.erase(max_var(to_root_atom(a)->p())); + vs.push_back(to_root_atom(a)->x()); + } + } + + void deallocate(ineq_atom * a) { + unsigned obj_sz = ineq_atom::get_obj_size(a->size()); + a->~ineq_atom(); + m_allocator.deallocate(obj_sz, a); + } + + void deallocate(root_atom * a) { + a->~root_atom(); + m_allocator.deallocate(sizeof(root_atom), a); + } + + void del(bool_var b) { + SASSERT(m_bwatches[b].empty()); + //SASSERT(m_bvalues[b] == l_undef); + m_num_bool_vars--; + m_dead[b] = true; + m_atoms[b] = nullptr; + m_bvalues[b] = l_undef; + m_bid_gen.recycle(b); + } + + void del(ineq_atom * a) { + CTRACE("nlsat_solver", a->ref_count() > 0, display(tout, *a) << "\n";); + // this triggers in too many benign cases: + // SASSERT(a->ref_count() == 0); + m_ineq_atoms.erase(a); + del(a->bvar()); + unsigned sz = a->size(); + for (unsigned i = 0; i < sz; i++) + m_pm.dec_ref(a->p(i)); + deallocate(a); + } + + void del(root_atom * a) { + SASSERT(a->ref_count() == 0); + m_root_atoms.erase(a); + del(a->bvar()); + m_pm.dec_ref(a->p()); + deallocate(a); + } + + void del(atom * a) { + if (a == nullptr) + return; + TRACE("nlsat_verbose", display(tout << "del: b" << a->m_bool_var << " " << a->ref_count() << " ", *a) << "\n";); + if (a->is_ineq_atom()) + del(to_ineq_atom(a)); + else + del(to_root_atom(a)); + } + + // Delete atoms with ref_count == 0 + void del_unref_atoms() { + for (auto* a : m_atoms) { + del(a); + } + } + + + ineq_atom* mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool& is_new, bool simplify) { + SASSERT(sz >= 1); + SASSERT(k == atom::LT || k == atom::GT || k == atom::EQ); + int sign = 1; + polynomial_ref p(m_pm); + ptr_buffer uniq_ps; + var max = null_var; + for (unsigned i = 0; i < sz; i++) { + p = m_pm.flip_sign_if_lm_neg(ps[i]); + if (p.get() != ps[i] && !is_even[i]) { + sign = -sign; + } + var curr_max = max_var(p.get()); + if (curr_max > max || max == null_var) + max = curr_max; + if (sz == 1 && simplify) { + if (sign < 0) + k = atom::flip(k); + sign = 1; + polynomial::manager::ineq_type t; + switch (k) { + case atom::EQ: t = polynomial::manager::ineq_type::EQ; break; + case atom::LT: t = polynomial::manager::ineq_type::LT; break; + case atom::GT: t = polynomial::manager::ineq_type::GT; break; + default: UNREACHABLE(); break; + } + polynomial::var_vector vars; + m_pm.vars(p, vars); + bool all_int = all_of(vars, [&](var x) { return is_int(x); }); + if (!all_int) + t = polynomial::manager::ineq_type::EQ; + m_pm.gcd_simplify(p, t); + } + uniq_ps.push_back(m_cache.mk_unique(p)); + TRACE("nlsat_table_bug", tout << "p: " << p << ", uniq: " << uniq_ps.back() << "\n";); + //verbose_stream() << "p: " << p.get() << ", uniq: " << uniq_ps.back() << "\n"; + } + void * mem = m_allocator.allocate(ineq_atom::get_obj_size(sz)); + if (sign < 0) + k = atom::flip(k); + ineq_atom * tmp_atom = new (mem) ineq_atom(k, sz, uniq_ps.data(), is_even, max); + ineq_atom * atom = m_ineq_atoms.insert_if_not_there(tmp_atom); + CTRACE("nlsat_table_bug", tmp_atom != atom, ineq_atom::hash_proc h; + tout << "mk_ineq_atom hash: " << h(tmp_atom) << "\n"; display(tout, *tmp_atom, m_display_var) << "\n";); + CTRACE("nlsat_table_bug", atom->max_var() != max, display(tout << "nonmax: ", *atom, m_display_var) << "\n";); + SASSERT(atom->max_var() == max); + is_new = (atom == tmp_atom); + if (is_new) { + for (unsigned i = 0; i < sz; i++) { + m_pm.inc_ref(atom->p(i)); + } + } + else { + deallocate(tmp_atom); + } + return atom; + } + + bool_var mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify = false) { + bool is_new = false; + ineq_atom* atom = mk_ineq_atom(k, sz, ps, is_even, is_new, simplify); + if (!is_new) { + return atom->bvar(); + } + else { + bool_var b = mk_bool_var_core(); + m_atoms[b] = atom; + atom->m_bool_var = b; + TRACE("nlsat_verbose", display(tout << "create: b" << atom->m_bool_var << " ", *atom) << "\n";); + return b; + } + } + + literal mk_ineq_literal(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify = false) { + SASSERT(k == atom::LT || k == atom::GT || k == atom::EQ); + bool is_const = true; + polynomial::manager::scoped_numeral cnst(m_pm.m()); + m_pm.m().set(cnst, 1); + for (unsigned i = 0; i < sz; ++i) { + if (m_pm.is_const(ps[i])) { + if (m_pm.is_zero(ps[i])) { + m_pm.m().set(cnst, 0); + is_const = true; + break; + } + auto const& c = m_pm.coeff(ps[i], 0); + m_pm.m().mul(cnst, c, cnst); + if (is_even[i] && m_pm.m().is_neg(c)) { + m_pm.m().neg(cnst); + } + } + else { + is_const = false; + } + } + if (is_const) { + if (m_pm.m().is_pos(cnst) && k == atom::GT) return true_literal; + if (m_pm.m().is_neg(cnst) && k == atom::LT) return true_literal; + if (m_pm.m().is_zero(cnst) && k == atom::EQ) return true_literal; + return false_literal; + } + return literal(mk_ineq_atom(k, sz, ps, is_even, simplify), false); + } + + bool_var mk_root_atom(atom::kind k, var x, unsigned i, poly * p) { + polynomial_ref p1(m_pm), uniq_p(m_pm); + p1 = m_pm.flip_sign_if_lm_neg(p); // flipping the sign of the polynomial will not change its roots. + uniq_p = m_cache.mk_unique(p1); + TRACE("nlsat_solver", tout << x << " " << p1 << " " << uniq_p << "\n";); + SASSERT(i > 0); + SASSERT(x >= max_var(p)); + SASSERT(k == atom::ROOT_LT || k == atom::ROOT_GT || k == atom::ROOT_EQ || k == atom::ROOT_LE || k == atom::ROOT_GE); + + void * mem = m_allocator.allocate(sizeof(root_atom)); + root_atom * new_atom = new (mem) root_atom(k, x, i, uniq_p); + root_atom * old_atom = m_root_atoms.insert_if_not_there(new_atom); + SASSERT(old_atom->max_var() == x); + if (old_atom != new_atom) { + deallocate(new_atom); + return old_atom->bvar(); + } + bool_var b = mk_bool_var_core(); + m_atoms[b] = new_atom; + new_atom->m_bool_var = b; + m_pm.inc_ref(new_atom->p()); + return b; + } + + void attach_clause(clause & cls) { + var x = max_var(cls); + if (x != null_var) { + m_watches[x].push_back(&cls); + } + else { + bool_var b = max_bvar(cls); + m_bwatches[b].push_back(&cls); + } + } + + void deattach_clause(clause & cls) { + var x = max_var(cls); + if (x != null_var) { + m_watches[x].erase(&cls); + } + else { + bool_var b = max_bvar(cls); + m_bwatches[b].erase(&cls); + } + } + + void deallocate(clause * cls) { + size_t obj_sz = clause::get_obj_size(cls->size()); + cls->~clause(); + m_allocator.deallocate(obj_sz, cls); + } + + void del_clause(clause * cls) { + deattach_clause(*cls); + m_cid_gen.recycle(cls->id()); + unsigned sz = cls->size(); + for (unsigned i = 0; i < sz; i++) + dec_ref((*cls)[i]); + _assumption_set a = static_cast<_assumption_set>(cls->assumptions()); + dec_ref(a); + deallocate(cls); + } + + void del_clause(clause * cls, clause_vector& clauses) { + clauses.erase(cls); + del_clause(cls); + } + + void del_clauses(ptr_vector & cs) { + for (clause* cp : cs) + del_clause(cp); + cs.reset(); + } + + void del_clauses() { + del_clauses(m_clauses); + del_clauses(m_learned); + del_clauses(m_valids); + } + + // We use a simple heuristic to sort literals + // - bool literals < arith literals + // - sort literals based on max_var + // - sort literal with the same max_var using degree + // break ties using the fact that ineqs are usually cheaper to process than eqs. + struct lit_lt { + imp & m; + lit_lt(imp & _m):m(_m) {} + + bool operator()(literal l1, literal l2) const { + atom * a1 = m.m_atoms[l1.var()]; + atom * a2 = m.m_atoms[l2.var()]; + if (a1 == nullptr && a2 == nullptr) + return l1.index() < l2.index(); + if (a1 == nullptr) + return true; + if (a2 == nullptr) + return false; + var x1 = a1->max_var(); + var x2 = a2->max_var(); + if (x1 < x2) + return true; + if (x1 > x2) + return false; + SASSERT(x1 == x2); + unsigned d1 = m.degree(a1); + unsigned d2 = m.degree(a2); + if (d1 < d2) + return true; + if (d1 > d2) + return false; + if (!a1->is_eq() && a2->is_eq()) + return true; + if (a1->is_eq() && !a2->is_eq()) + return false; + return l1.index() < l2.index(); + } + }; + + class scoped_bool_vars { + imp& s; + svector vec; + public: + scoped_bool_vars(imp& s):s(s) {} + ~scoped_bool_vars() { + for (bool_var v : vec) { + s.dec_ref(v); + } + } + void push_back(bool_var v) { + s.inc_ref(v); + vec.push_back(v); + } + bool_var const* begin() const { return vec.begin(); } + bool_var const* end() const { return vec.end(); } + bool_var operator[](bool_var v) const { return vec[v]; } + }; + + void check_lemma(unsigned n, literal const* cls, bool is_valid, assumption_set a) { + TRACE("nlsat", display(tout << "check lemma: ", n, cls) << "\n"; + display(tout);); + IF_VERBOSE(2, display(verbose_stream() << "check lemma " << (is_valid?"valid: ":"consequence: "), n, cls) << "\n"); + for (clause* c : m_learned) IF_VERBOSE(1, display(verbose_stream() << "lemma: ", *c) << "\n"); + scoped_suspend_rlimit _limit(m_rlimit); + ctx c(m_rlimit, m_ctx.m_params, m_ctx.m_incremental); + solver solver2(c); + imp& checker = *(solver2.m_imp); + checker.m_check_lemmas = false; + checker.m_log_lemmas = false; + checker.m_inline_vars = false; + + auto pconvert = [&](poly* p) { + return convert(m_pm, p, checker.m_pm); + }; + + // need to translate Boolean variables and literals + scoped_bool_vars tr(checker); + for (var x = 0; x < m_is_int.size(); ++x) { + checker.register_var(x, is_int(x)); + } + bool_var bv = 0; + tr.push_back(bv); + for (bool_var b = 1; b < m_atoms.size(); ++b) { + atom* a = m_atoms[b]; + if (a == nullptr) { + bv = checker.mk_bool_var(); + } + else if (a->is_ineq_atom()) { + ineq_atom& ia = *to_ineq_atom(a); + unsigned sz = ia.size(); + polynomial_ref_vector ps(checker.m_pm); + bool_vector is_even; + for (unsigned i = 0; i < sz; ++i) { + ps.push_back(pconvert(ia.p(i))); + is_even.push_back(ia.is_even(i)); + } + bv = checker.mk_ineq_atom(ia.get_kind(), sz, ps.data(), is_even.data()); + } + else if (a->is_root_atom()) { + root_atom& r = *to_root_atom(a); + if (r.x() >= max_var(r.p())) { + // permutation may be reverted after check completes, + // but then root atoms are not used in lemmas. + bv = checker.mk_root_atom(r.get_kind(), r.x(), r.i(), pconvert(r.p())); + } + } + else { + UNREACHABLE(); + } + tr.push_back(bv); + } + if (!is_valid) { + for (clause* c : m_clauses) { + if (!a && c->assumptions()) { + continue; + } + literal_vector lits; + for (literal lit : *c) { + lits.push_back(literal(tr[lit.var()], lit.sign())); + } + checker.mk_external_clause(lits.size(), lits.data(), nullptr); + } + } + for (unsigned i = 0; i < n; ++i) { + literal lit = cls[i]; + literal nlit(tr[lit.var()], !lit.sign()); + checker.mk_external_clause(1, &nlit, nullptr); + } + lbool r = checker.check(); + if (r == l_true) { + for (bool_var b : tr) { + literal lit(b, false); + IF_VERBOSE(0, checker.display(verbose_stream(), lit) << " := " << checker.value(lit) << "\n"); + TRACE("nlsat", checker.display(tout, lit) << " := " << checker.value(lit) << "\n";); + } + for (clause* c : m_learned) { + bool found = false; + for (literal lit: *c) { + literal tlit(tr[lit.var()], lit.sign()); + found |= checker.value(tlit) == l_true; + } + if (!found) { + IF_VERBOSE(0, display(verbose_stream() << "violdated clause: ", *c) << "\n"); + TRACE("nlsat", display(tout << "violdated clause: ", *c) << "\n";); + } + } + for (clause* c : m_valids) { + bool found = false; + for (literal lit: *c) { + literal tlit(tr[lit.var()], lit.sign()); + found |= checker.value(tlit) == l_true; + } + if (!found) { + IF_VERBOSE(0, display(verbose_stream() << "violdated tautology clause: ", *c) << "\n"); + TRACE("nlsat", display(tout << "violdated tautology clause: ", *c) << "\n";); + } + } + throw default_exception("lemma did not check"); + UNREACHABLE(); + } + } + + void log_lemma(std::ostream& out, clause const& cls) { + log_lemma(out, cls.size(), cls.data(), false); + } + + void log_lemma(std::ostream& out, unsigned n, literal const* cls, bool is_valid) { + ++m_lemma_count; + out << "(set-logic NRA)\n"; + if (is_valid) { + display_smt2_bool_decls(out); + display_smt2_arith_decls(out); + } + else + display_smt2(out); + for (unsigned i = 0; i < n; ++i) + display_smt2(out << "(assert ", ~cls[i]) << ")\n"; + display(out << "(echo \"#" << m_lemma_count << " ", n, cls) << "\")\n"; + out << "(check-sat)\n(reset)\n"; + + TRACE("nlsat", display(tout << "(echo \"#" << m_lemma_count << " ", n, cls) << "\")\n"); + } + + clause * mk_clause_core(unsigned num_lits, literal const * lits, bool learned, _assumption_set a) { + SASSERT(num_lits > 0); + unsigned cid = m_cid_gen.mk(); + void * mem = m_allocator.allocate(clause::get_obj_size(num_lits)); + clause * cls = new (mem) clause(cid, num_lits, lits, learned, a); + for (unsigned i = 0; i < num_lits; i++) + inc_ref(lits[i]); + inc_ref(a); + return cls; + } + + clause * mk_clause(unsigned num_lits, literal const * lits, bool learned, _assumption_set a) { + if (num_lits == 0) { + num_lits = 1; + lits = &false_literal; + } + SASSERT(num_lits > 0); + clause * cls = mk_clause_core(num_lits, lits, learned, a); + TRACE("nlsat_sort", display(tout << "mk_clause:\n", *cls) << "\n";); + std::sort(cls->begin(), cls->end(), lit_lt(*this)); + TRACE("nlsat", display(tout << " after sort:\n", *cls) << "\n";); + if (learned && m_log_lemmas) { + log_lemma(verbose_stream(), *cls); + } + if (learned && m_check_lemmas && false) { + check_lemma(cls->size(), cls->data(), false, cls->assumptions()); + } + if (learned) + m_learned.push_back(cls); + else + m_clauses.push_back(cls); + attach_clause(*cls); + return cls; + } + + void mk_external_clause(unsigned num_lits, literal const * lits, assumption a) { + _assumption_set as = nullptr; + if (a != nullptr) + as = m_asm.mk_leaf(a); + if (num_lits == 0) { + num_lits = 1; + lits = &false_literal; + } + mk_clause(num_lits, lits, false, as); + } + + // ----------------------- + // + // Search + // + // ----------------------- + + void save_assign_trail(bool_var b) { + m_trail.push_back(trail(b, bvar_assignment())); + } + + void save_set_updt_trail(interval_set * old_set) { + m_trail.push_back(trail(old_set)); + } + + void save_updt_eq_trail(atom * old_eq) { + m_trail.push_back(trail(old_eq)); + } + + void save_new_stage_trail() { + m_trail.push_back(trail(true, stage())); + } + + void save_new_level_trail() { + m_trail.push_back(trail(false, stage())); + } + + void undo_bvar_assignment(bool_var b) { + m_bvalues[b] = l_undef; + m_levels[b] = UINT_MAX; + del_jst(m_allocator, m_justifications[b]); + m_justifications[b] = null_justification; + if (m_atoms[b] == nullptr && b < m_bk) + m_bk = b; + } + + void undo_set_updt(interval_set * old_set) { + if (m_xk == null_var) + return; + var x = m_xk; + if (x < m_infeasible.size()) { + m_ism.dec_ref(m_infeasible[x]); + m_infeasible[x] = old_set; + } + } + + void undo_new_stage() { + if (m_xk == 0) { + m_xk = null_var; + } + else if (m_xk != null_var) { + m_xk--; + m_assignment.reset(m_xk); + } + } + + void undo_new_level() { + SASSERT(m_scope_lvl > 0); + m_scope_lvl--; + m_evaluator.pop(1); + } + + void undo_updt_eq(atom * a) { + if (m_var2eq.size() > m_xk) + m_var2eq[m_xk] = a; + } + + template + void undo_until(Predicate const & pred) { + while (pred() && !m_trail.empty()) { + trail & t = m_trail.back(); + switch (t.m_kind) { + case trail::BVAR_ASSIGNMENT: + undo_bvar_assignment(t.m_b); + break; + case trail::INFEASIBLE_UPDT: + undo_set_updt(t.m_old_set); + break; + case trail::NEW_STAGE: + undo_new_stage(); + break; + case trail::NEW_LEVEL: + undo_new_level(); + break; + case trail::UPDT_EQ: + undo_updt_eq(t.m_old_eq); + break; + default: + break; + } + m_trail.pop_back(); + } + } + + struct size_pred { + svector & m_trail; + unsigned m_old_size; + size_pred(svector & trail, unsigned old_size):m_trail(trail), m_old_size(old_size) {} + bool operator()() const { return m_trail.size() > m_old_size; } + }; + + // Keep undoing until trail has the given size + void undo_until_size(unsigned old_size) { + SASSERT(m_trail.size() >= old_size); + undo_until(size_pred(m_trail, old_size)); + } + + struct stage_pred { + var const & m_xk; + var m_target; + stage_pred(var const & xk, var target):m_xk(xk), m_target(target) {} + bool operator()() const { return m_xk != m_target; } + }; + + // Keep undoing until stage is new_xk + void undo_until_stage(var new_xk) { + undo_until(stage_pred(m_xk, new_xk)); + } + + struct level_pred { + unsigned const & m_scope_lvl; + unsigned m_new_lvl; + level_pred(unsigned const & scope_lvl, unsigned new_lvl):m_scope_lvl(scope_lvl), m_new_lvl(new_lvl) {} + bool operator()() const { return m_scope_lvl > m_new_lvl; } + }; + + // Keep undoing until level is new_lvl + void undo_until_level(unsigned new_lvl) { + undo_until(level_pred(m_scope_lvl, new_lvl)); + } + + struct unassigned_pred { + bool_var m_b; + svector const & m_bvalues; + unassigned_pred(svector const & bvalues, bool_var b): + m_b(b), + m_bvalues(bvalues) {} + bool operator()() const { return m_bvalues[m_b] != l_undef; } + }; + + // Keep undoing until b is unassigned + void undo_until_unassigned(bool_var b) { + undo_until(unassigned_pred(m_bvalues, b)); + SASSERT(m_bvalues[b] == l_undef); + } + + struct true_pred { + bool operator()() const { return true; } + }; + + void undo_until_empty() { + undo_until(true_pred()); + } + + /** + \brief Create a new scope level + */ + void new_level() { + m_evaluator.push(); + m_scope_lvl++; + save_new_level_trail(); + } + + /** + \brief Return the value of the given literal that was assigned by the search + engine. + */ + lbool assigned_value(literal l) const { + bool_var b = l.var(); + if (l.sign()) + return ~m_bvalues[b]; + else + return m_bvalues[b]; + } + + /** + \brief Assign literal using the given justification + */ + void assign(literal l, justification j) { + TRACE("nlsat_assign", + display(tout << "assigning literal: ", l); + display(tout << " <- ", j);); + + SASSERT(assigned_value(l) == l_undef); + SASSERT(j != null_justification); + SASSERT(!j.is_null()); + if (j.is_decision()) + m_stats.m_decisions++; + else + m_stats.m_propagations++; + bool_var b = l.var(); + m_bvalues[b] = to_lbool(!l.sign()); + m_levels[b] = m_scope_lvl; + m_justifications[b] = j; + save_assign_trail(b); + updt_eq(b, j); + TRACE("nlsat_assign", tout << "b" << b << " -> " << m_bvalues[b] << "\n";); + } + + /** + \brief Create a "case-split" + */ + void decide(literal l) { + new_level(); + assign(l, decided_justification); + } + + /** + \brief Return the value of a literal as defined in Dejan and Leo's paper. + */ + lbool value(literal l) { + lbool val = assigned_value(l); + if (val != l_undef) { + TRACE("nlsat_verbose", display(tout << " assigned value " << val << " for ", l) << "\n";); + return val; + } + bool_var b = l.var(); + atom * a = m_atoms[b]; + if (a == nullptr) { + TRACE("nlsat_verbose", display(tout << " no atom for ", l) << "\n";); + return l_undef; + } + var max = a->max_var(); + if (!m_assignment.is_assigned(max)) { + TRACE("nlsat_verbose", display(tout << " maximal variable not assigned ", l) << "\n";); + return l_undef; + } + val = to_lbool(m_evaluator.eval(a, l.sign())); + TRACE("nlsat_verbose", display(tout << " evaluated value " << val << " for ", l) << "\n";); + TRACE("value_bug", tout << "value of: "; display(tout, l); tout << " := " << val << "\n"; + tout << "xk: " << m_xk << ", a->max_var(): " << a->max_var() << "\n"; + display_assignment(tout);); + return val; + } + + /** + \brief Return true if the given clause is already satisfied in the current partial interpretation. + */ + bool is_satisfied(clause const & cls) const { + for (literal l : cls) { + if (const_cast(this)->value(l) == l_true) { + TRACE("value_bug:", tout << l << " := true\n";); + return true; + } + } + return false; + } + + /** + \brief Return true if the given clause is false in the current partial interpretation. + */ + bool is_inconsistent(unsigned sz, literal const * cls) { + for (unsigned i = 0; i < sz; i++) { + if (value(cls[i]) != l_false) { + TRACE("is_inconsistent", tout << "literal is not false:\n"; display(tout, cls[i]); tout << "\n";); + return false; + } + } + return true; + } + + /** + \brief Process a clauses that contains only Boolean literals. + */ + bool process_boolean_clause(clause const & cls) { + SASSERT(m_xk == null_var); + unsigned num_undef = 0; + unsigned first_undef = UINT_MAX; + unsigned sz = cls.size(); + for (unsigned i = 0; i < sz; i++) { + literal l = cls[i]; + SASSERT(m_atoms[l.var()] == nullptr); + SASSERT(value(l) != l_true); + if (value(l) == l_false) + continue; + SASSERT(value(l) == l_undef); + num_undef++; + if (first_undef == UINT_MAX) + first_undef = i; + } + if (num_undef == 0) + return false; + SASSERT(first_undef != UINT_MAX); + if (num_undef == 1) + assign(cls[first_undef], mk_clause_jst(&cls)); // unit clause + else + decide(cls[first_undef]); + return true; + } + + /** + \brief assign l to true, because l + (justification of) s is infeasible in RCF in the current interpretation. + */ + literal_vector core; + ptr_vector clauses; + void R_propagate(literal l, interval_set const * s, bool include_l = true) { + m_ism.get_justifications(s, core, clauses); + if (include_l) + core.push_back(~l); + auto j = mk_lazy_jst(m_allocator, core.size(), core.data(), clauses.size(), clauses.data()); + TRACE("nlsat_resolve", display(tout, j); display_eval(tout << "evaluated:", j)); + assign(l, j); + SASSERT(value(l) == l_true); + } + + /** + \brief m_infeasible[m_xk] <- m_infeasible[m_xk] Union s + */ + void updt_infeasible(interval_set const * s) { + SASSERT(m_xk != null_var); + interval_set * xk_set = m_infeasible[m_xk]; + save_set_updt_trail(xk_set); + interval_set_ref new_set(m_ism); + TRACE("nlsat_inf_set", tout << "updating infeasible set\n"; m_ism.display(tout, xk_set) << "\n"; m_ism.display(tout, s) << "\n";); + new_set = m_ism.mk_union(s, xk_set); + TRACE("nlsat_inf_set", tout << "new infeasible set:\n"; m_ism.display(tout, new_set) << "\n";); + SASSERT(!m_ism.is_full(new_set)); + m_ism.inc_ref(new_set); + m_infeasible[m_xk] = new_set; + } + + /** + \brief Update m_var2eq mapping. + */ + void updt_eq(bool_var b, justification j) { + if (!m_simplify_cores) + return; + if (m_bvalues[b] != l_true) + return; + atom * a = m_atoms[b]; + if (a == nullptr || a->get_kind() != atom::EQ || to_ineq_atom(a)->size() > 1 || to_ineq_atom(a)->is_even(0)) + return; + switch (j.get_kind()) { + case justification::CLAUSE: + if (j.get_clause()->assumptions() != nullptr) return; + break; + case justification::LAZY: + if (j.get_lazy()->num_clauses() > 0) return; + if (j.get_lazy()->num_lits() > 0) return; + break; + default: + break; + } + var x = m_xk; + SASSERT(a->max_var() == x); + SASSERT(x != null_var); + if (m_var2eq[x] != 0 && degree(m_var2eq[x]) <= degree(a)) + return; // we only update m_var2eq if the new equality has smaller degree + TRACE("nlsat_simplify_core", tout << "Saving equality for "; m_display_var(tout, x) << " (x" << x << ") "; + tout << "scope-lvl: " << scope_lvl() << "\n"; display(tout, literal(b, false)) << "\n"; + display(tout, j); + ); + save_updt_eq_trail(m_var2eq[x]); + m_var2eq[x] = a; + } + + /** + \brief Process a clause that contains nonlinear arithmetic literals + + If satisfy_learned is true, then learned clauses are satisfied even if m_lazy > 0 + */ + bool process_arith_clause(clause const & cls, bool satisfy_learned) { + if (!satisfy_learned && m_lazy >= 2 && cls.is_learned()) { + TRACE("nlsat", tout << "skip learned\n";); + return true; // ignore lemmas in super lazy mode + } + SASSERT(m_xk == max_var(cls)); + unsigned num_undef = 0; // number of undefined literals + unsigned first_undef = UINT_MAX; // position of the first undefined literal + interval_set_ref first_undef_set(m_ism); // infeasible region of the first undefined literal + interval_set * xk_set = m_infeasible[m_xk]; // current set of infeasible interval for current variable + SASSERT(!m_ism.is_full(xk_set)); + for (unsigned idx = 0; idx < cls.size(); ++idx) { + literal l = cls[idx]; + checkpoint(); + if (value(l) == l_false) + continue; + if (value(l) == l_true) + return true; // could happen if clause is a tautology + CTRACE("nlsat", max_var(l) != m_xk || value(l) != l_undef, display(tout); + tout << "xk: " << m_xk << ", max_var(l): " << max_var(l) << ", l: "; display(tout, l) << "\n"; + display(tout, cls) << "\n";); + SASSERT(value(l) == l_undef); + SASSERT(max_var(l) == m_xk); + bool_var b = l.var(); + atom * a = m_atoms[b]; + SASSERT(a != nullptr); + interval_set_ref curr_set(m_ism); + curr_set = m_evaluator.infeasible_intervals(a, l.sign(), &cls); + TRACE("nlsat_inf_set", tout << "infeasible set for literal: "; display(tout, l); tout << "\n"; m_ism.display(tout, curr_set); tout << "\n"; + display(tout, cls) << "\n";); + if (m_ism.is_empty(curr_set)) { + TRACE("nlsat_inf_set", tout << "infeasible set is empty, found literal\n";); + R_propagate(l, nullptr); + SASSERT(is_satisfied(cls)); + return true; + } + if (m_ism.is_full(curr_set)) { + TRACE("nlsat_inf_set", tout << "infeasible set is R, skip literal\n";); + R_propagate(~l, nullptr); + continue; + } + if (m_ism.subset(curr_set, xk_set)) { + TRACE("nlsat_inf_set", tout << "infeasible set is a subset of current set, found literal\n";); + R_propagate(l, xk_set); + return true; + } + interval_set_ref tmp(m_ism); + tmp = m_ism.mk_union(curr_set, xk_set); + if (m_ism.is_full(tmp)) { + TRACE("nlsat_inf_set", tout << "infeasible set + current set = R, skip literal\n"; + display(tout, cls) << "\n"; + m_ism.display(tout, tmp); tout << "\n"; + ); + R_propagate(~l, tmp, false); + continue; + } + num_undef++; + if (first_undef == UINT_MAX) { + first_undef = idx; + first_undef_set = curr_set; + } + } + TRACE("nlsat_inf_set", tout << "num_undef: " << num_undef << "\n";); + if (num_undef == 0) + return false; + SASSERT(first_undef != UINT_MAX); + if (num_undef == 1) { + // unit clause + assign(cls[first_undef], mk_clause_jst(&cls)); + updt_infeasible(first_undef_set); + } + else if ( satisfy_learned || + !cls.is_learned() /* must always satisfy input clauses */ || + m_lazy == 0 /* if not in lazy mode, we also satiffy lemmas */) { + decide(cls[first_undef]); + updt_infeasible(first_undef_set); + } + else { + TRACE("nlsat_lazy", tout << "skipping clause, satisfy_learned: " << satisfy_learned << ", cls.is_learned(): " << cls.is_learned() + << ", lazy: " << m_lazy << "\n";); + } + return true; + } + + /** + \brief Try to satisfy the given clause. Return true if succeeded. + + If satisfy_learned is true, then (arithmetic) learned clauses are satisfied even if m_lazy > 0 + */ + bool process_clause(clause const & cls, bool satisfy_learned) { + if (is_satisfied(cls)) + return true; + if (m_xk == null_var) + return process_boolean_clause(cls); + else + return process_arith_clause(cls, satisfy_learned); + } + + /** + \brief Try to satisfy the given "set" of clauses. + Return 0, if the set was satisfied, or the violating clause otherwise + */ + clause * process_clauses(clause_vector const & cs) { + for (clause* c : cs) { + if (!process_clause(*c, false)) + return c; + } + return nullptr; // succeeded + } + + /** + \brief Make sure m_bk is the first unassigned pure Boolean variable. + Set m_bk == null_bool_var if there is no unassigned pure Boolean variable. + */ + void peek_next_bool_var() { + while (m_bk < m_atoms.size()) { + if (!m_dead[m_bk] && m_atoms[m_bk] == nullptr && m_bvalues[m_bk] == l_undef) { + return; + } + m_bk++; + } + m_bk = null_bool_var; + } + + /** + \brief Create a new stage. See Dejan and Leo's paper. + */ + void new_stage() { + m_stats.m_stages++; + save_new_stage_trail(); + if (m_xk == null_var) + m_xk = 0; + else + m_xk++; + } + + /** + \brief Assign m_xk + */ + void select_witness() { + scoped_anum w(m_am); + SASSERT(!m_ism.is_full(m_infeasible[m_xk])); + m_ism.pick_in_complement(m_infeasible[m_xk], is_int(m_xk), w, m_randomize); + TRACE("nlsat", + tout << "infeasible intervals: "; m_ism.display(tout, m_infeasible[m_xk]); tout << "\n"; + tout << "assigning "; m_display_var(tout, m_xk) << "(x" << m_xk << ") -> " << w << "\n";); + TRACE("nlsat_root", tout << "value as root object: "; m_am.display_root(tout, w); tout << "\n";); + if (!m_am.is_rational(w)) + m_stats.m_irrational_assignments++; + m_assignment.set_core(m_xk, w); + } + + + + bool is_satisfied() { + if (m_bk == null_bool_var && m_xk >= num_vars()) { + TRACE("nlsat", tout << "found model\n"; display_assignment(tout);); + fix_patch(); + SASSERT(check_satisfied(m_clauses)); + return true; // all variables were assigned, and all clauses were satisfied. + } + else { + return false; + } + } + + + /** + \brief main procedure + */ + lbool search() { + TRACE("nlsat", tout << "starting search...\n"; display(tout); tout << "\nvar order:\n"; display_vars(tout);); + TRACE("nlsat_proof", tout << "ASSERTED\n"; display(tout);); + TRACE("nlsat_proof_sk", tout << "ASSERTED\n"; display_abst(tout);); + TRACE("nlsat_mathematica", display_mathematica(tout);); + TRACE("nlsat", display_smt2(tout);); + m_bk = 0; + m_xk = null_var; + + while (true) { + if (should_reorder()) + do_reorder(); + +#if 0 + if (should_gc()) + do_gc(); +#endif + + if (should_simplify()) + do_simplify(); + + CASSERT("nlsat", check_satisfied()); + if (m_xk == null_var) { + peek_next_bool_var(); + if (m_bk == null_bool_var) + new_stage(); // move to arith vars + } + else { + new_stage(); // peek next arith var + } + TRACE("nlsat_bug", tout << "xk: x" << m_xk << " bk: b" << m_bk << "\n";); + if (is_satisfied()) { + return l_true; + } + while (true) { + TRACE("nlsat_verbose", tout << "processing variable "; + if (m_xk != null_var) { + m_display_var(tout, m_xk); tout << " " << m_watches[m_xk].size(); + } + else { + tout << m_bwatches[m_bk].size() << " boolean b" << m_bk; + } + tout << "\n";); + checkpoint(); + clause * conflict_clause; + if (m_xk == null_var) + conflict_clause = process_clauses(m_bwatches[m_bk]); + else + conflict_clause = process_clauses(m_watches[m_xk]); + if (conflict_clause == nullptr) + break; + if (!resolve(*conflict_clause)) + return l_false; + if (m_stats.m_conflicts >= m_max_conflicts) + return l_undef; + log(); + } + + if (m_xk == null_var) { + if (m_bvalues[m_bk] == l_undef) { + decide(literal(m_bk, true)); + m_bk++; + } + } + else { + select_witness(); + } + } + } + + void gc() { + if (m_learned.size() <= 4*m_clauses.size()) + return; + reset_watches(); + reinit_cache(); + unsigned j = 0; + for (unsigned i = 0; i < m_learned.size(); ++i) { + auto cls = m_learned[i]; + if (i - j < m_clauses.size() && cls->size() > 1 && !cls->is_active()) + del_clause(cls); + else { + m_learned[j++] = cls; + cls->set_active(false); + } + } + m_learned.shrink(j); + reattach_arith_clauses(m_clauses); + reattach_arith_clauses(m_learned); + } + + + bool should_gc() { + return m_learned.size() > 10 * m_clauses.size(); + } + + void do_gc() { + undo_to_base(); + gc(); + } + + void undo_to_base() { + init_search(); + m_bk = 0; + m_xk = null_var; + } + + unsigned m_restart_threshold = 10000; + bool should_reorder() { + return m_stats.m_conflicts > 0 && m_stats.m_conflicts % m_restart_threshold == 0; + } + + void do_reorder() { + undo_to_base(); + m_stats.m_restarts++; + m_stats.m_conflicts++; + if (m_reordered) + restore_order(); + apply_reorder(); + } + + bool m_did_simplify = false; + bool should_simplify() { + return + !m_did_simplify && m_inline_vars && + !m_incremental && m_stats.m_conflicts > 100; + } + + void do_simplify() { + undo_to_base(); + m_did_simplify = true; + m_simplify(); + } + + unsigned m_next_conflict = 100; + void log() { + if (m_stats.m_conflicts != 1 && m_stats.m_conflicts < m_next_conflict) + return; + m_next_conflict += 100; + IF_VERBOSE(2, verbose_stream() << "(nlsat :conflicts " << m_stats.m_conflicts + << " :decisions " << m_stats.m_decisions + << " :propagations " << m_stats.m_propagations + << " :clauses " << m_clauses.size() + << " :learned " << m_learned.size() << ")\n"); + } + + + lbool search_check() { + lbool r = l_undef; + m_stats.m_conflicts = 0; + m_stats.m_restarts = 0; + m_next_conflict = 0; + while (true) { + r = search(); + if (r != l_true) + break; + ++m_stats.m_restarts; + vector> bounds; + + for (var x = 0; x < num_vars(); x++) { + if (is_int(x) && m_assignment.is_assigned(x) && !m_am.is_int(m_assignment.value(x))) { + scoped_anum v(m_am), vlo(m_am); + v = m_assignment.value(x); + rational lo; + m_am.int_lt(v, vlo); + if (!m_am.is_int(vlo)) + continue; + m_am.to_rational(vlo, lo); + // derive tight bounds. + while (true) { + lo++; + if (!m_am.gt(v, lo.to_mpq())) { + lo--; + break; + } + } + bounds.push_back(std::make_pair(x, lo)); + } + } + if (bounds.empty()) + break; + + gc(); + if (m_stats.m_restarts % 10 == 0) { + if (m_reordered) + restore_order(); + apply_reorder(); + } + + init_search(); + IF_VERBOSE(2, verbose_stream() << "(nlsat-b&b :conflicts " << m_stats.m_conflicts + << " :decisions " << m_stats.m_decisions + << " :propagations " << m_stats.m_propagations + << " :clauses " << m_clauses.size() + << " :learned " << m_learned.size() << ")\n"); + for (auto const& b : bounds) { + var x = b.first; + rational lo = b.second; + rational hi = lo + 1; // rational::one(); + bool is_even = false; + polynomial_ref p(m_pm); + rational one(1); + m_lemma.reset(); + p = m_pm.mk_linear(1, &one, &x, -lo); + poly* p1 = p.get(); + m_lemma.push_back(~mk_ineq_literal(atom::GT, 1, &p1, &is_even)); + p = m_pm.mk_linear(1, &one, &x, -hi); + poly* p2 = p.get(); + m_lemma.push_back(~mk_ineq_literal(atom::LT, 1, &p2, &is_even)); + + // perform branch and bound + clause * cls = mk_clause(m_lemma.size(), m_lemma.data(), true, nullptr); + IF_VERBOSE(4, display(verbose_stream(), *cls) << "\n"); + if (cls) { + TRACE("nlsat", display(tout << "conflict " << lo << " " << hi, *cls); tout << "\n";); + } + } + } + return r; + } + + bool m_reordered = false; +//#linxi begin Simple Check +// test + void test_anum() { + scoped_anum x(m_am), y(m_am); + m_am.set(x, 3); + m_am.set(y, 5); + TRACE("linxi_simple_checker", + tout << x << " " << y << std::endl; + ); + } + bool simple_check() { + // test_anum(); + literal_vector learned_unit; + // Simple_Checker checker(m_solver, m_pm, m_am, m_clauses, m_learned, m_atoms, m_is_int.size()); + Simple_Checker checker(m_pm, m_am, m_clauses, learned_unit, m_atoms, m_is_int.size()); + // TRACE("linxi_simple_checker", + // tout << "here" << std::endl; + // ); + if (!checker()) + return false; + for (unsigned i = 0, sz = learned_unit.size(); i < sz; ++i) { + clause *cla = mk_clause(1, &learned_unit[i], true, nullptr); + if (m_atoms[learned_unit[i].var()] == nullptr) { + assign(learned_unit[i], mk_clause_jst(cla)); + } + // decide(learned_unit[i]); + } + return true; + } + +//#linxi end Simple Check + +//#linxi begin Variable Ordering Strategy + void run_variable_ordering_strategy() { + TRACE("linxi_reorder", tout << "runing vos: " << m_linxi_variable_ordering_strategy << '\n';); + + unsigned num = num_vars(); + VOS_Var_Info_Collector vos_collector(m_pm, m_atoms, num, m_linxi_variable_ordering_strategy); + vos_collector.collect(m_clauses); + vos_collector.collect(m_learned); + // TRACE("linxi_reorder", vos_collector.display(tout, m_display_var);); + + var_vector perm; + vos_collector(perm); + reorder(perm.size(), perm.data()); + } + +//#linxi end Variable Ordering Strategy + +//#linxi begin symmetry check + void symmetry_check() { + std::cout << "sym called\n"; + unsigned arith_num = m_is_int.size(); + if (arith_num > 10000) + return ; + Symmetry_Checker checker(m_pm, m_qm, m_clauses, m_atoms, m_is_int, arith_num); + for (var x = 0; x < arith_num; ++x) { + for (var y = x + 1; y < arith_num; ++y) { + if (checker.check_symmetry(x, y)) { + TRACE("linxi_symmetry_checker", + tout << "symmetry: " << x << ", " << y << "\n"; + ); + + rational zero(0); + vector as; + vector xs; + as.push_back(rational(1)); + xs.push_back(x); + as.push_back(rational(-1)); + xs.push_back(y); + polynomial_ref pr(m_pm); + pr = m_pm.mk_linear(2, as.data(), xs.data(), zero); + poly* p = pr.get(); + bool is_even = false; + literal lit = ~mk_ineq_literal(atom::GT, 1, &p, &is_even); + clause *cla = mk_clause(1, &lit, true, nullptr); + } + } + } + TRACE("linxi_symmetry_checker", + display(tout); + ); + + } +//#linxi end symmetry check + void apply_reorder() { + m_reordered = false; + if (!can_reorder()) + ; + else if (m_random_order) { + shuffle_vars(); + m_reordered = true; + } + else if (m_reorder) { + heuristic_reorder(); + m_reordered = true; + } + } + + lbool check() { + +//#linxi begin symmetry check + if (m_linxi_symmetry_check) { + symmetry_check(); + } + // exit(0); +//#linxi end symmetry check + +//#linxi begin simple check + if (m_linxi_simple_check) { + if (!simple_check()) { + TRACE("linxi_simple_check", tout << "real unsat\n";); + return l_false; + } + TRACE("linxi_simple_checker_learned", + tout << "simple check done\n"; + ); + // exit(0); + // return l_undef; + } + // exit(0); + // return l_false; +//#linxi end simple check + + TRACE("nlsat_smt2", display_smt2(tout);); + TRACE("nlsat_fd", tout << "is_full_dimensional: " << is_full_dimensional() << "\n";); + init_search(); + m_explain.set_full_dimensional(is_full_dimensional()); + bool reordered = false; + + + if (!can_reorder()) { + + } +//#linxi begin Variable Ordering Strategy + else if (m_linxi_variable_ordering_strategy > 0) { + std::cout << "m_linxi_variable_ordering_strategy=" << m_linxi_variable_ordering_strategy << "\n"; + run_variable_ordering_strategy(); + reordered = true; + } +//#linxi end Variable Ordering Strategy + else if (m_random_order) { + shuffle_vars(); + reordered = true; + } + else if (m_reorder) { + heuristic_reorder(); + reordered = true; + } + sort_watched_clauses(); + lbool r = search_check(); + CTRACE("nlsat_model", r == l_true, tout << "model before restore order\n"; display_assignment(tout);); + if (reordered) { + restore_order(); + } + CTRACE("nlsat_model", r == l_true, tout << "model\n"; display_assignment(tout);); + CTRACE("nlsat", r == l_false, display(tout << "unsat\n");); + SASSERT(r != l_true || check_satisfied(m_clauses)); + return r; + } + + void init_search() { + undo_until_empty(); + while (m_scope_lvl > 0) { + undo_new_level(); + } + m_xk = null_var; + for (unsigned i = 0; i < m_bvalues.size(); ++i) { + m_bvalues[i] = l_undef; + } + m_assignment.reset(); + } + + lbool check(literal_vector& assumptions) { + literal_vector result; + unsigned sz = assumptions.size(); + literal const* ptr = assumptions.data(); + for (unsigned i = 0; i < sz; ++i) { + mk_external_clause(1, ptr+i, (assumption)(ptr+i)); + } + display_literal_assumption dla(*this, assumptions); + scoped_display_assumptions _scoped_display(*this, dla); + lbool r = check(); + + if (r == l_false) { + // collect used literals from m_lemma_assumptions + vector deps; + get_core(deps); + for (unsigned i = 0; i < deps.size(); ++i) { + literal const* lp = (literal const*)(deps[i]); + if (ptr <= lp && lp < ptr + sz) { + result.push_back(*lp); + } + } + } + collect(assumptions, m_clauses); + collect(assumptions, m_learned); + del_clauses(m_valids); + if (m_check_lemmas) { + for (clause* c : m_learned) { + check_lemma(c->size(), c->data(), false, nullptr); + } + } + +#if 0 + for (clause* c : m_learned) { + IF_VERBOSE(0, display(verbose_stream() << "KEEP: ", c->size(), c->c_ptr()) << "\n"); + } +#endif + assumptions.reset(); + assumptions.append(result); + return r; + } + + void get_core(vector& deps) { + m_asm.linearize(m_lemma_assumptions.get(), deps); + } + + void collect(literal_vector const& assumptions, clause_vector& clauses) { + unsigned j = 0; + for (clause * c : clauses) { + if (collect(assumptions, *c)) { + del_clause(c); + } + else { + clauses[j++] = c; + } + } + clauses.shrink(j); + } + + bool collect(literal_vector const& assumptions, clause const& c) { + unsigned sz = assumptions.size(); + literal const* ptr = assumptions.data(); + _assumption_set asms = static_cast<_assumption_set>(c.assumptions()); + if (asms == nullptr) { + return false; + } + vector deps; + m_asm.linearize(asms, deps); + for (auto dep : deps) { + if (ptr <= dep && dep < ptr + sz) { + return true; + } + } + return false; + } + + // ----------------------- + // + // Conflict Resolution + // + // ----------------------- + svector m_marks; // bool_var -> bool temp mark used during conflict resolution + unsigned m_num_marks; + scoped_literal_vector m_lemma; + scoped_literal_vector m_lazy_clause; + assumption_set_ref m_lemma_assumptions; // assumption tracking + + // Conflict resolution invariant: a marked literal is in m_lemma or on the trail stack. + + bool check_marks() { + for (unsigned m : m_marks) { + (void)m; + SASSERT(m == 0); + } + return true; + } + + unsigned scope_lvl() const { return m_scope_lvl; } + + bool is_marked(bool_var b) const { return m_marks.get(b, 0) == 1; } + + void mark(bool_var b) { m_marks.setx(b, 1, 0); } + + void reset_mark(bool_var b) { m_marks[b] = 0; } + + void reset_marks() { + for (auto const& l : m_lemma) { + reset_mark(l.var()); + } + } + + void process_antecedent(literal antecedent) { + checkpoint(); + bool_var b = antecedent.var(); + TRACE("nlsat_resolve", display(tout << "resolving antecedent: ", antecedent) << "\n";); + if (assigned_value(antecedent) == l_undef) { + checkpoint(); + // antecedent must be false in the current arith interpretation + SASSERT(value(antecedent) == l_false || m_rlimit.is_canceled()); + if (!is_marked(b)) { + SASSERT(is_arith_atom(b) && max_var(b) < m_xk); // must be in a previous stage + TRACE("nlsat_resolve", tout << "literal is unassigned, but it is false in arithmetic interpretation, adding it to lemma\n";); + mark(b); + m_lemma.push_back(antecedent); + } + return; + } + + unsigned b_lvl = m_levels[b]; + TRACE("nlsat_resolve", tout << "b_lvl: " << b_lvl << ", is_marked(b): " << is_marked(b) << ", m_num_marks: " << m_num_marks << "\n";); + if (!is_marked(b)) { + mark(b); + if (b_lvl == scope_lvl() /* same level */ && max_var(b) == m_xk /* same stage */) { + TRACE("nlsat_resolve", tout << "literal is in the same level and stage, increasing marks\n";); + m_num_marks++; + } + else { + TRACE("nlsat_resolve", tout << "previous level or stage, adding literal to lemma\n"; + tout << "max_var(b): " << max_var(b) << ", m_xk: " << m_xk << ", lvl: " << b_lvl << ", scope_lvl: " << scope_lvl() << "\n";); + m_lemma.push_back(antecedent); + } + } + } + + void resolve_clause(bool_var b, unsigned sz, literal const * c) { + TRACE("nlsat_proof", tout << "resolving "; if (b != null_bool_var) display_atom(tout, b) << "\n"; display(tout, sz, c); tout << "\n";); + TRACE("nlsat_proof_sk", tout << "resolving "; if (b != null_bool_var) tout << "b" << b; tout << "\n"; display_abst(tout, sz, c); tout << "\n";); + + for (unsigned i = 0; i < sz; i++) { + if (c[i].var() != b) + process_antecedent(c[i]); + } + } + + void resolve_clause(bool_var b, clause & c) { + TRACE("nlsat_resolve", tout << "resolving clause "; if (b != null_bool_var) tout << "for b: " << b << "\n"; display(tout, c) << "\n";); + c.set_active(true); + resolve_clause(b, c.size(), c.data()); + m_lemma_assumptions = m_asm.mk_join(static_cast<_assumption_set>(c.assumptions()), m_lemma_assumptions); + } + + void resolve_lazy_justification(bool_var b, lazy_justification const & jst) { + TRACE("nlsat_resolve", tout << "resolving lazy_justification for b" << b << "\n";); + unsigned sz = jst.num_lits(); + + // Dump lemma as Mathematica formula that must be true, + // if the current interpretation (really) makes the core in jst infeasible. + TRACE("nlsat_mathematica", + tout << "assignment lemma\n"; + literal_vector core; + for (unsigned i = 0; i < sz; i++) { + core.push_back(~jst.lit(i)); + } + display_mathematica_lemma(tout, core.size(), core.data(), true);); + + m_lazy_clause.reset(); + m_explain(jst.num_lits(), jst.lits(), m_lazy_clause); + for (unsigned i = 0; i < sz; i++) + m_lazy_clause.push_back(~jst.lit(i)); + + // lazy clause is a valid clause + TRACE("nlsat_mathematica", display_mathematica_lemma(tout, m_lazy_clause.size(), m_lazy_clause.data());); + TRACE("nlsat_proof_sk", tout << "theory lemma\n"; display_abst(tout, m_lazy_clause.size(), m_lazy_clause.data()); tout << "\n";); + TRACE("nlsat_resolve", + tout << "m_xk: " << m_xk << ", "; m_display_var(tout, m_xk) << "\n"; + tout << "new valid clause:\n"; + display(tout, m_lazy_clause.size(), m_lazy_clause.data()) << "\n";); + + + if (m_log_lemmas) + log_lemma(verbose_stream(), m_lazy_clause.size(), m_lazy_clause.data(), true); + + if (m_check_lemmas) { + check_lemma(m_lazy_clause.size(), m_lazy_clause.data(), true, nullptr); + m_valids.push_back(mk_clause_core(m_lazy_clause.size(), m_lazy_clause.data(), false, nullptr)); + } + +#ifdef Z3DEBUG + { + unsigned sz = m_lazy_clause.size(); + for (unsigned i = 0; i < sz; i++) { + literal l = m_lazy_clause[i]; + if (l.var() != b) { + if (value(l) != l_false) + display(verbose_stream() << value(l) << " ", 1, &l); + SASSERT(value(l) == l_false || m_rlimit.is_canceled()); + } + else { + SASSERT(value(l) == l_true || m_rlimit.is_canceled()); + SASSERT(!l.sign() || m_bvalues[b] == l_false); + SASSERT(l.sign() || m_bvalues[b] == l_true); + } + } + } +#endif + checkpoint(); + resolve_clause(b, m_lazy_clause.size(), m_lazy_clause.data()); + + for (unsigned i = 0; i < jst.num_clauses(); ++i) { + clause const& c = jst.clause(i); + TRACE("nlsat", display(tout << "adding clause assumptions ", c) << "\n";); + m_lemma_assumptions = m_asm.mk_join(static_cast<_assumption_set>(c.assumptions()), m_lemma_assumptions); + } + } + + /** + \brief Return true if all literals in ls are from previous stages. + */ + bool only_literals_from_previous_stages(unsigned num, literal const * ls) const { + for (unsigned i = 0; i < num; i++) { + if (max_var(ls[i]) == m_xk) + return false; + } + return true; + } + + /** + \brief Return the maximum scope level in ls. + + \pre This method assumes value(ls[i]) is l_false for i in [0, num) + */ + unsigned max_scope_lvl(unsigned num, literal const * ls) { + unsigned max = 0; + for (unsigned i = 0; i < num; i++) { + literal l = ls[i]; + bool_var b = l.var(); + SASSERT(value(ls[i]) == l_false); + if (assigned_value(l) == l_false) { + unsigned lvl = m_levels[b]; + if (lvl > max) + max = lvl; + } + else { + // l must be a literal from a previous stage that is false in the current interpretation + SASSERT(assigned_value(l) == l_undef); + SASSERT(max_var(b) != null_var); + SASSERT(m_xk != null_var); + SASSERT(max_var(b) < m_xk); + } + } + return max; + } + + /** + \brief Remove literals of the given lvl (that are in the current stage) from lemma. + + \pre This method assumes value(ls[i]) is l_false for i in [0, num) + */ + void remove_literals_from_lvl(scoped_literal_vector & lemma, unsigned lvl) { + TRACE("nlsat_resolve", tout << "removing literals from lvl: " << lvl << " and stage " << m_xk << "\n";); + unsigned sz = lemma.size(); + unsigned j = 0; + for (unsigned i = 0; i < sz; i++) { + literal l = lemma[i]; + bool_var b = l.var(); + SASSERT(is_marked(b)); + SASSERT(value(lemma[i]) == l_false); + if (assigned_value(l) == l_false && m_levels[b] == lvl && max_var(b) == m_xk) { + m_num_marks++; + continue; + } + lemma.set(j, l); + j++; + } + lemma.shrink(j); + } + + /** + \brief Return true if it is a Boolean lemma. + */ + bool is_bool_lemma(unsigned sz, literal const * ls) const { + for (unsigned i = 0; i < sz; i++) { + if (m_atoms[ls[i].var()] != nullptr) + return false; + } + return true; + } + + + /** + Return the maximal decision level in lemma for literals in the first sz-1 positions that + are at the same stage. If all these literals are from previous stages, + we just backtrack the current level. + */ + unsigned find_new_level_arith_lemma(unsigned sz, literal const * lemma) { + SASSERT(!is_bool_lemma(sz, lemma)); + unsigned new_lvl = 0; + bool found_lvl = false; + for (unsigned i = 0; i < sz - 1; i++) { + literal l = lemma[i]; + if (max_var(l) == m_xk) { + bool_var b = l.var(); + if (!found_lvl) { + found_lvl = true; + new_lvl = m_levels[b]; + } + else { + if (m_levels[b] > new_lvl) + new_lvl = m_levels[b]; + } + } + } + SASSERT(!found_lvl || new_lvl < scope_lvl()); + if (!found_lvl) { + TRACE("nlsat_resolve", tout << "fail to find new lvl, using previous one\n";); + new_lvl = scope_lvl() - 1; + } + return new_lvl; + } + + struct scoped_reset_marks { + imp& i; + scoped_reset_marks(imp& i):i(i) {} + ~scoped_reset_marks() { if (i.m_num_marks > 0) { i.m_num_marks = 0; for (char& m : i.m_marks) m = 0; } } + }; + + + /** + \brief Return true if the conflict was solved. + */ + bool resolve(clause & conflict) { + clause * conflict_clause = &conflict; + m_lemma_assumptions = nullptr; + start: + SASSERT(check_marks()); + TRACE("nlsat_proof", tout << "STARTING RESOLUTION\n";); + TRACE("nlsat_proof_sk", tout << "STARTING RESOLUTION\n";); + m_stats.m_conflicts++; + TRACE("nlsat", tout << "resolve, conflicting clause:\n"; display(tout, *conflict_clause) << "\n"; + tout << "xk: "; if (m_xk != null_var) m_display_var(tout, m_xk); else tout << ""; tout << "\n"; + tout << "scope_lvl: " << scope_lvl() << "\n"; + tout << "current assignment\n"; display_assignment(tout);); + + m_num_marks = 0; + m_lemma.reset(); + m_lemma_assumptions = nullptr; + scoped_reset_marks _sr(*this); + resolve_clause(null_bool_var, *conflict_clause); + + unsigned top = m_trail.size(); + bool found_decision; + while (true) { + found_decision = false; + while (m_num_marks > 0) { + checkpoint(); + SASSERT(top > 0); + trail & t = m_trail[top-1]; + SASSERT(t.m_kind != trail::NEW_STAGE); // we only mark literals that are in the same stage + if (t.m_kind == trail::BVAR_ASSIGNMENT) { + bool_var b = t.m_b; + if (is_marked(b)) { + TRACE("nlsat_resolve", tout << "found marked: b" << b << "\n"; display_atom(tout, b) << "\n";); + m_num_marks--; + reset_mark(b); + justification jst = m_justifications[b]; + switch (jst.get_kind()) { + case justification::CLAUSE: + resolve_clause(b, *(jst.get_clause())); + break; + case justification::LAZY: + resolve_lazy_justification(b, *(jst.get_lazy())); + break; + case justification::DECISION: + SASSERT(m_num_marks == 0); + found_decision = true; + TRACE("nlsat_resolve", tout << "found decision\n";); + m_lemma.push_back(literal(b, m_bvalues[b] == l_true)); + break; + default: + UNREACHABLE(); + break; + } + } + } + top--; + } + + // m_lemma is an implicating clause after backtracking current scope level. + if (found_decision) + break; + + // If lemma only contains literals from previous stages, then we can stop. + // We make progress by returning to a previous stage with additional information (new lemma) + // that forces us to select a new partial interpretation + if (only_literals_from_previous_stages(m_lemma.size(), m_lemma.data())) + break; + + // Conflict does not depend on the current decision, and it is still in the current stage. + // We should find + // - the maximal scope level in the lemma + // - remove literal assigned in the scope level from m_lemma + // - backtrack to this level + // - and continue conflict resolution from there + // - we must bump m_num_marks for literals removed from m_lemma + unsigned max_lvl = max_scope_lvl(m_lemma.size(), m_lemma.data()); + TRACE("nlsat_resolve", tout << "conflict does not depend on current decision, backtracking to level: " << max_lvl << "\n";); + SASSERT(max_lvl < scope_lvl()); + remove_literals_from_lvl(m_lemma, max_lvl); + undo_until_level(max_lvl); + top = m_trail.size(); + TRACE("nlsat_resolve", tout << "scope_lvl: " << scope_lvl() << " num marks: " << m_num_marks << "\n";); + SASSERT(scope_lvl() == max_lvl); + } + + TRACE("nlsat_proof", tout << "New lemma\n"; display(tout, m_lemma); tout << "\n=========================\n";); + TRACE("nlsat_proof_sk", tout << "New lemma\n"; display_abst(tout, m_lemma); tout << "\n=========================\n";); + + if (m_lemma.empty()) { + TRACE("nlsat", tout << "empty clause generated\n";); + return false; // problem is unsat, empty clause was generated + } + + reset_marks(); // remove marks from the literals in m_lemmas. + TRACE("nlsat", tout << "new lemma:\n"; display(tout, m_lemma.size(), m_lemma.data()); tout << "\n"; + tout << "found_decision: " << found_decision << "\n";); + + if (m_check_lemmas) { + check_lemma(m_lemma.size(), m_lemma.data(), false, m_lemma_assumptions.get()); + } + + if (m_log_lemmas) + log_lemma(verbose_stream(), m_lemma.size(), m_lemma.data(), false); + + // There are two possibilities: + // 1) m_lemma contains only literals from previous stages, and they + // are false in the current interpretation. We make progress + // by returning to a previous stage with additional information (new clause) + // that forces us to select a new partial interpretation + // >>> Return to some previous stage (we may also backjump many decisions and stages). + // + // 2) m_lemma contains at most one literal from the current level (the last literal). + // Moreover, this literal was a decision, but the new lemma forces it to + // be assigned to a different value. + // >>> In this case, we remain in the same stage but, we add a new asserted literal + // in a previous scope level. We may backjump many decisions. + // + unsigned sz = m_lemma.size(); + clause * new_cls = nullptr; + if (!found_decision) { + // Case 1) + // We just have to find the maximal variable in m_lemma, and return to that stage + // Remark: the lemma may contain only boolean literals, in this case new_max_var == null_var; + var new_max_var = max_var(sz, m_lemma.data()); + TRACE("nlsat_resolve", tout << "backtracking to stage: " << new_max_var << ", curr: " << m_xk << "\n";); + undo_until_stage(new_max_var); + SASSERT(m_xk == new_max_var); + new_cls = mk_clause(sz, m_lemma.data(), true, m_lemma_assumptions.get()); + TRACE("nlsat", tout << "new_level: " << scope_lvl() << "\nnew_stage: " << new_max_var << "\n"; + if (new_max_var != null_var) m_display_var(tout, new_max_var) << "\n";); + } + else { + SASSERT(scope_lvl() >= 1); + // Case 2) + if (is_bool_lemma(m_lemma.size(), m_lemma.data())) { + // boolean lemma, we just backtrack until the last literal is unassigned. + bool_var max_bool_var = m_lemma[m_lemma.size()-1].var(); + undo_until_unassigned(max_bool_var); + } + else { + // We must find the maximal decision level in literals in the first sz-1 positions that + // are at the same stage. If all these literals are from previous stages, + // we just backtrack the current level. + unsigned new_lvl = find_new_level_arith_lemma(m_lemma.size(), m_lemma.data()); + TRACE("nlsat", tout << "backtracking to new level: " << new_lvl << ", curr: " << m_scope_lvl << "\n";); + undo_until_level(new_lvl); + } + + if (lemma_is_clause(*conflict_clause)) { + TRACE("nlsat", tout << "found decision literal in conflict clause\n";); + VERIFY(process_clause(*conflict_clause, true)); + return true; + } + new_cls = mk_clause(sz, m_lemma.data(), true, m_lemma_assumptions.get()); + } + NLSAT_VERBOSE(display(verbose_stream(), *new_cls) << "\n";); + if (!process_clause(*new_cls, true)) { + TRACE("nlsat", tout << "new clause triggered another conflict, restarting conflict resolution...\n"; + display(tout, *new_cls) << "\n"; + ); + // we are still in conflict + conflict_clause = new_cls; + goto start; + } + TRACE("nlsat_resolve_done", display_assignment(tout);); + return true; + } + + bool lemma_is_clause(clause const& cls) const { + bool same = (m_lemma.size() == cls.size()); + for (unsigned i = 0; same && i < m_lemma.size(); ++i) { + same = m_lemma[i] == cls[i]; + } + return same; + } + + + // ----------------------- + // + // Debugging + // + // ----------------------- + + bool check_watches() const { +#ifdef Z3DEBUG + for (var x = 0; x < num_vars(); x++) { + clause_vector const & cs = m_watches[x]; + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) { + SASSERT(max_var(*(cs[i])) == x); + } + } +#endif + return true; + } + + bool check_bwatches() const { +#ifdef Z3DEBUG + for (bool_var b = 0; b < m_bwatches.size(); b++) { + clause_vector const & cs = m_bwatches[b]; + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) { + clause const & c = *(cs[i]); + SASSERT(max_var(c) == null_var); + SASSERT(max_bvar(c) == b); + } + } +#endif + return true; + } + + bool check_invariant() const { + SASSERT(check_watches()); + SASSERT(check_bwatches()); + return true; + } + + bool check_satisfied(clause_vector const & cs) const { + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) { + clause const & c = *(cs[i]); + if (!is_satisfied(c)) { + TRACE("nlsat", tout << "not satisfied\n"; display(tout, c); tout << "\n";); + return false; + } + } + return true; + } + + bool check_satisfied() const { + TRACE("nlsat", tout << "bk: b" << m_bk << ", xk: x" << m_xk << "\n"; if (m_xk != null_var) { m_display_var(tout, m_xk); tout << "\n"; }); + unsigned num = m_atoms.size(); + if (m_bk != null_bool_var) + num = m_bk; + for (bool_var b = 0; b < num; b++) { + if (!check_satisfied(m_bwatches[b])) { + UNREACHABLE(); + return false; + } + } + if (m_xk != null_var) { + for (var x = 0; x < m_xk; x++) { + if (!check_satisfied(m_watches[x])) { + UNREACHABLE(); + return false; + } + } + } + return true; + } + + // ----------------------- + // + // Statistics + // + // ----------------------- + + void collect_statistics(statistics & st) { + st.update("nlsat conflicts", m_stats.m_conflicts); + st.update("nlsat propagations", m_stats.m_propagations); + st.update("nlsat decisions", m_stats.m_decisions); + st.update("nlsat restarts", m_stats.m_restarts); + st.update("nlsat stages", m_stats.m_stages); + st.update("nlsat simplifications", m_stats.m_simplifications); + st.update("nlsat irrational assignments", m_stats.m_irrational_assignments); + } + + void reset_statistics() { + m_stats.reset(); + } + + // ----------------------- + // + // Variable reordering + // + // ----------------------- + + struct var_info_collector { + pmanager & pm; + atom_vector const & m_atoms; + var_vector m_shuffle; + unsigned_vector m_max_degree; + unsigned_vector m_num_occs; + + var_info_collector(pmanager & _pm, atom_vector const & atoms, unsigned num_vars): + pm(_pm), + m_atoms(atoms) { + m_max_degree.resize(num_vars, 0); + m_num_occs.resize(num_vars, 0); + } + + var_vector m_vars; + void collect(poly * p) { + m_vars.reset(); + pm.vars(p, m_vars); + unsigned sz = m_vars.size(); + for (unsigned i = 0; i < sz; i++) { + var x = m_vars[i]; + unsigned k = pm.degree(p, x); + m_num_occs[x]++; + if (k > m_max_degree[x]) + m_max_degree[x] = k; + } + } + + void collect(literal l) { + bool_var b = l.var(); + atom * a = m_atoms[b]; + if (a == nullptr) + return; + if (a->is_ineq_atom()) { + unsigned sz = to_ineq_atom(a)->size(); + for (unsigned i = 0; i < sz; i++) { + collect(to_ineq_atom(a)->p(i)); + } + } + else { + collect(to_root_atom(a)->p()); + } + } + + void collect(clause const & c) { + unsigned sz = c.size(); + for (unsigned i = 0; i < sz; i++) + collect(c[i]); + } + + void collect(clause_vector const & cs) { + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) + collect(*(cs[i])); + } + + std::ostream& display(std::ostream & out, display_var_proc const & proc) { + unsigned sz = m_num_occs.size(); + for (unsigned i = 0; i < sz; i++) { + proc(out, i); out << " -> " << m_max_degree[i] << " : " << m_num_occs[i] << "\n"; + } + return out; + } + }; + + struct reorder_lt { + var_info_collector const & m_info; + reorder_lt(var_info_collector const & info):m_info(info) {} + bool operator()(var x, var y) const { + // high degree first + if (m_info.m_max_degree[x] < m_info.m_max_degree[y]) + return false; + if (m_info.m_max_degree[x] > m_info.m_max_degree[y]) + return true; + // more constrained first + if (m_info.m_num_occs[x] < m_info.m_num_occs[y]) + return false; + if (m_info.m_num_occs[x] > m_info.m_num_occs[y]) + return true; + return m_info.m_shuffle[x] < m_info.m_shuffle[y]; + } + }; + + // Order variables by degree and number of occurrences + void heuristic_reorder() { + unsigned num = num_vars(); + var_info_collector collector(m_pm, m_atoms, num); + collector.collect(m_clauses); + collector.collect(m_learned); + init_shuffle(collector.m_shuffle); + TRACE("nlsat_reorder", collector.display(tout, m_display_var);); + var_vector new_order; + for (var x = 0; x < num; x++) + new_order.push_back(x); + + std::sort(new_order.begin(), new_order.end(), reorder_lt(collector)); + TRACE("nlsat_reorder", + tout << "new order: "; for (unsigned i = 0; i < num; i++) tout << new_order[i] << " "; tout << "\n";); + var_vector perm; + perm.resize(num, 0); + for (var x = 0; x < num; x++) { + perm[new_order[x]] = x; + } + reorder(perm.size(), perm.data()); + SASSERT(check_invariant()); + } + + void init_shuffle(var_vector& p) { + unsigned num = num_vars(); + for (var x = 0; x < num; x++) + p.push_back(x); + + random_gen r(++m_random_seed); + shuffle(p.size(), p.data(), r); + } + + void shuffle_vars() { + var_vector p; + init_shuffle(p); + reorder(p.size(), p.data()); + } + + bool can_reorder() const { + return all_of(m_learned, [&](clause* c) { return !has_root_atom(*c); }) + && all_of(m_clauses, [&](clause* c) { return !has_root_atom(*c); }); + } + + /** + \brief Reorder variables using the giving permutation. + p maps internal variables to their new positions + */ + + + void reorder(unsigned sz, var const * p) { + + remove_learned_roots(); + SASSERT(can_reorder()); + TRACE("nlsat_reorder", tout << "solver before variable reorder\n"; display(tout); + display_vars(tout); + tout << "\npermutation:\n"; + for (unsigned i = 0; i < sz; i++) tout << p[i] << " "; tout << "\n"; + ); + // verbose_stream() << "\npermutation: " << p[0] << " count " << count << " " << m_rlimit.is_canceled() << "\n"; + reinit_cache(); + SASSERT(num_vars() == sz); + TRACE("nlsat_bool_assignment_bug", tout << "before reset watches\n"; display_bool_assignment(tout);); + reset_watches(); + assignment new_assignment(m_am); + for (var x = 0; x < num_vars(); x++) { + if (m_assignment.is_assigned(x)) + new_assignment.set(p[x], m_assignment.value(x)); + } + var_vector new_inv_perm; + new_inv_perm.resize(sz); + // the undo_until_size(0) statement erases the Boolean assignment. + // undo_until_size(0) + undo_until_stage(null_var); + m_cache.reset(); +#ifdef Z3DEBUG + for (var x = 0; x < num_vars(); x++) { + SASSERT(m_watches[x].empty()); + } +#endif + // update m_perm mapping + for (unsigned ext_x = 0; ext_x < sz; ext_x++) { + // p: internal -> new pos + // m_perm: internal -> external + // m_inv_perm: external -> internal + new_inv_perm[ext_x] = p[m_inv_perm[ext_x]]; + m_perm.set(new_inv_perm[ext_x], ext_x); + } + bool_vector is_int; + is_int.swap(m_is_int); + for (var x = 0; x < sz; x++) { + m_is_int.setx(p[x], is_int[x], false); + SASSERT(m_infeasible[x] == 0); + } + m_inv_perm.swap(new_inv_perm); +#ifdef Z3DEBUG + for (var x = 0; x < num_vars(); x++) { + SASSERT(x == m_inv_perm[m_perm[x]]); + SASSERT(m_watches[x].empty()); + } +#endif + m_pm.rename(sz, p); + for (auto& b : m_bounds) + b.x = p[b.x]; + TRACE("nlsat_bool_assignment_bug", tout << "before reinit cache\n"; display_bool_assignment(tout);); + reinit_cache(); + m_assignment.swap(new_assignment); + reattach_arith_clauses(m_clauses); + reattach_arith_clauses(m_learned); + TRACE("nlsat_reorder", tout << "solver after variable reorder\n"; display(tout); display_vars(tout);); + } + + + /** + \brief Restore variable order. + */ + void restore_order() { + // m_perm: internal -> external + // m_inv_perm: external -> internal + var_vector p; + p.append(m_perm); + reorder(p.size(), p.data()); +#ifdef Z3DEBUG + for (var x = 0; x < num_vars(); x++) { + SASSERT(m_perm[x] == x); + SASSERT(m_inv_perm[x] == x); + } +#endif + } + + /** + \brief After variable reordering some lemmas containing root atoms may be ill-formed. + */ + void remove_learned_roots() { + unsigned j = 0; + for (clause* c : m_learned) { + if (has_root_atom(*c)) { + del_clause(c); + } + else { + m_learned[j++] = c; + } + } + m_learned.shrink(j); + } + + /** + \brief Return true if the clause contains an ill formed root atom + */ + bool has_root_atom(clause const & c) const { + for (literal lit : c) { + bool_var b = lit.var(); + atom * a = m_atoms[b]; + if (a && a->is_root_atom()) + return true; + } + return false; + } + + /** + \brief reinsert all polynomials in the unique cache + */ + void reinit_cache() { + reinit_cache(m_clauses); + reinit_cache(m_learned); + for (atom* a : m_atoms) + reinit_cache(a); + } + void reinit_cache(clause_vector const & cs) { + for (clause* c : cs) + reinit_cache(*c); + } + void reinit_cache(clause const & c) { + for (literal l : c) + reinit_cache(l); + } + void reinit_cache(literal l) { + bool_var b = l.var(); + reinit_cache(m_atoms[b]); + } + void reinit_cache(atom* a) { + if (a == nullptr) { + + } + else if (a->is_ineq_atom()) { + var max = 0; + unsigned sz = to_ineq_atom(a)->size(); + for (unsigned i = 0; i < sz; i++) { + poly * p = to_ineq_atom(a)->p(i); + VERIFY(m_cache.mk_unique(p) == p); + var x = m_pm.max_var(p); + if (x > max) + max = x; + } + a->m_max_var = max; + } + else { + poly * p = to_root_atom(a)->p(); + VERIFY(m_cache.mk_unique(p) == p); + a->m_max_var = m_pm.max_var(p); + } + } + + void reset_watches() { + unsigned num = num_vars(); + for (var x = 0; x < num; x++) { + m_watches[x].reset(); + } + } + + void reattach_arith_clauses(clause_vector const & cs) { + for (clause* cp : cs) { + var x = max_var(*cp); + if (x != null_var) + m_watches[x].push_back(cp); + } + } + + // ----------------------- + // + // Solver initialization + // + // ----------------------- + + struct degree_lt { + unsigned_vector & m_degrees; + degree_lt(unsigned_vector & ds):m_degrees(ds) {} + bool operator()(unsigned i1, unsigned i2) const { + if (m_degrees[i1] < m_degrees[i2]) + return true; + if (m_degrees[i1] > m_degrees[i2]) + return false; + return i1 < i2; + } + }; + + unsigned_vector m_cs_degrees; + unsigned_vector m_cs_p; + void sort_clauses_by_degree(unsigned sz, clause ** cs) { + if (sz <= 1) + return; + TRACE("nlsat_reorder_clauses", tout << "before:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); + m_cs_degrees.reset(); + m_cs_p.reset(); + for (unsigned i = 0; i < sz; i++) { + m_cs_p.push_back(i); + m_cs_degrees.push_back(degree(*(cs[i]))); + } + std::sort(m_cs_p.begin(), m_cs_p.end(), degree_lt(m_cs_degrees)); + TRACE("nlsat_reorder_clauses", tout << "permutation: "; ::display(tout, m_cs_p.begin(), m_cs_p.end()); tout << "\n";); + apply_permutation(sz, cs, m_cs_p.data()); + TRACE("nlsat_reorder_clauses", tout << "after:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); + } + +//#linxi begin + + struct degree_lit_num_lt { + unsigned_vector & m_degrees; + unsigned_vector & m_lit_num; + degree_lit_num_lt(unsigned_vector & ds, unsigned_vector ln) : + m_degrees(ds), + m_lit_num(ln) { + } + bool operator()(unsigned i1, unsigned i2) const { + if (m_lit_num[i1] == 1 && m_lit_num[i2] > 1) + return true; + if (m_lit_num[i1] > 1 && m_lit_num[i2] == 1) + return false; + if (m_degrees[i1] != m_degrees[i2]) + return m_degrees[i1] < m_degrees[i2]; + if (m_lit_num[i1] != m_lit_num[i2]) + return m_lit_num[i1] < m_lit_num[i2]; + return i1 < i2; + } + }; + + unsigned_vector m_dl_degrees; + unsigned_vector m_dl_lit_num; + unsigned_vector m_dl_p; + void sort_clauses_by_degree_lit_num(unsigned sz, clause ** cs) { + if (sz <= 1) + return; + TRACE("nlsat_reorder_clauses", tout << "before:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); + m_dl_degrees.reset(); + m_dl_lit_num.reset(); + m_dl_p.reset(); + for (unsigned i = 0; i < sz; i++) { + m_dl_degrees.push_back(degree(*(cs[i]))); + m_dl_lit_num.push_back(cs[i]->size()); + m_dl_p.push_back(i); + } + std::sort(m_dl_p.begin(), m_dl_p.end(), degree_lit_num_lt(m_dl_degrees, m_dl_lit_num)); + TRACE("nlsat_reorder_clauses", tout << "permutation: "; ::display(tout, m_dl_p.begin(), m_dl_p.end()); tout << "\n";); + apply_permutation(sz, cs, m_dl_p.data()); + TRACE("nlsat_reorder_clauses", tout << "after:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); + } + +//#linxi end + void sort_watched_clauses() { + unsigned num = num_vars(); + for (unsigned i = 0; i < num; i++) { + clause_vector & ws = m_watches[i]; +//#linxi begin + // sort_clauses_by_degree(ws.size(), ws.data()); + if (m_linxi_simple_check) { + sort_clauses_by_degree_lit_num(ws.size(), ws.data()); + } + else { + sort_clauses_by_degree(ws.size(), ws.data()); + } +//#linxi end + } + } + + // ----------------------- + // + // Full dimensional + // + // A problem is in the full dimensional fragment if it does + // not contain equalities or non-strict inequalities. + // + // ----------------------- + + bool is_full_dimensional(literal l) const { + atom * a = m_atoms[l.var()]; + if (a == nullptr) + return true; + switch (a->get_kind()) { + case atom::EQ: return l.sign(); + case atom::LT: return !l.sign(); + case atom::GT: return !l.sign(); + case atom::ROOT_EQ: return l.sign(); + case atom::ROOT_LT: return !l.sign(); + case atom::ROOT_GT: return !l.sign(); + case atom::ROOT_LE: return l.sign(); + case atom::ROOT_GE: return l.sign(); + default: + UNREACHABLE(); + return false; + } + } + + bool is_full_dimensional(clause const & c) const { + for (literal l : c) { + if (!is_full_dimensional(l)) + return false; + } + return true; + } + + bool is_full_dimensional(clause_vector const & cs) const { + for (clause* c : cs) { + if (!is_full_dimensional(*c)) + return false; + } + return true; + } + + bool is_full_dimensional() const { + return is_full_dimensional(m_clauses); + } + + + // ----------------------- + // + // Simplification + // + // ----------------------- + + // solve simple equalities + // TBD WU-Reit decomposition? + + // - elim_unconstrained + // - solve_eqs + // - fm + + /** + \brief isolate variables in unit equalities. + Assume a clause is c == v*p + q + and the context implies p > 0 + + replace v by -q/p + remove clause c, + The for other occurrences of v, + replace v*r + v*v*r' > 0 by + by p*p*v*r + p*p*v*v*r' > 0 + by p*q*r + q*q*r' > 0 + + The method ignores lemmas and assumes constraints don't use roots. + */ + + + + // Eliminated variables are tracked in m_bounds. + // Each element in m_bounds tracks the eliminated variable and an upper or lower bound + // that has to be satisfied. Variables that are eliminated through equalities are tracked + // by non-strict bounds. A satisfiable solution is required to provide an evaluation that + // is consistent with the bounds. For equalities, the non-strict lower or upper bound can + // always be assigned as a value to the variable. + + void fix_patch() { + m_lo.reset(); m_hi.reset(); + for (auto& b : m_bounds) + m_assignment.reset(b.x); + for (unsigned i = m_bounds.size(); i-- > 0; ) + fix_patch(m_bounds[i]); + } + + // x is unassigned, lo < x -> x <- lo + 1 + // x is unassigned, x < hi -> x <- hi - 1 + // x is unassigned, lo <= x -> x <- lo + // x is unassigned, x <= hi -> x <- hi + // x is assigned above hi, lo is strict lo < x < hi -> set x <- (lo + hi)/2 + // x is assigned below hi, above lo -> no-op + // x is assigned below lo, hi is strict lo < x < hi -> set x <-> (lo + hi)/2 + // x is assigned above hi, x <= hi -> x <- hi + // x is assigned blow lo, lo <= x -> x <- lo + void fix_patch(bound_constraint& b) { + var x = b.x; + scoped_anum Av(m_am), Bv(m_am), val(m_am); + m_pm.eval(b.A, m_assignment, Av); + m_pm.eval(b.B, m_assignment, Bv); + m_am.neg(Bv); + val = Bv / Av; + // Ax >= B + // is-lower : A > 0 + // is-upper: A < 0 + // x <- B / A + bool is_lower = m_am.is_pos(Av); + TRACE("nlsat", + m_display_var(tout << "patch v" << x << " ", x) << "\n"; + if (m_assignment.is_assigned(x)) m_am.display(tout << "previous value: ", m_assignment.value(x)); tout << "\n"; + m_am.display(tout << "updated value: ", val); tout << "\n"; + ); + + if (!m_assignment.is_assigned(x)) { + if (!b.is_strict) + m_assignment.set_core(x, val); + else if (is_lower) + m_assignment.set_core(x, val + 1); + else + m_assignment.set_core(x, val - 1); + } + else { + auto& aval = m_assignment.value(x); + if (is_lower) { + // lo < value(x), lo < x -> x is unchanged + if (b.is_strict && m_am.lt(val, aval)) + ; + else if (!b.is_strict && m_am.le(val, aval)) + ; + else if (!b.is_strict) + m_assignment.set_core(x, val); + // aval < lo < x, hi is unassigned: x <- lo + 1 + else if (!m_hi.is_assigned(x)) + m_assignment.set_core(x, val + 1); + // aval < lo < x, hi is assigned: x <- (lo + hi) / 2 + else { + scoped_anum mid(m_am); + m_am.add(m_hi.value(x), val, mid); + mid = mid / 2; + m_assignment.set_core(x, mid); + } + } + else { + // dual to lower bounds + if (b.is_strict && m_am.lt(aval, val)) + ; + else if (!b.is_strict && m_am.le(aval, val)) + ; + else if (!b.is_strict) + m_assignment.set_core(x, val); + else if (!m_lo.is_assigned(x)) + m_assignment.set_core(x, val - 1); + else { + scoped_anum mid(m_am); + m_am.add(m_lo.value(x), val, mid); + mid = mid / 2; + m_assignment.set_core(x, mid); + } + } + } + + if (is_lower) { + if (!m_lo.is_assigned(x) || m_am.lt(m_lo.value(x), val)) + m_lo.set_core(x, val); + } + else { + if (!m_hi.is_assigned(x) || m_am.gt(m_hi.value(x), val)) + m_hi.set_core(x, val); + } + } + + bool is_unit_ineq(clause const& c) const { + return + c.size() == 1 && + m_atoms[c[0].var()] && + m_atoms[c[0].var()]->is_ineq_atom(); + } + + bool is_unit_eq(clause const& c) const { + return + is_unit_ineq(c) && + !c[0].sign() && + m_atoms[c[0].var()]->is_eq(); + } + + /** + \brief determine whether the clause is a comparison v > k or v < k', where k >= 0 or k' <= 0. + */ + lbool is_cmp0(clause const& c, var& v) { + if (!is_unit_ineq(c)) + return l_undef; + literal lit = c[0]; + ineq_atom const& a = *to_ineq_atom(m_atoms[lit.var()]); + bool sign = lit.sign(); + poly * p0; + if (!is_single_poly(a, p0)) + return l_undef; + if (m_pm.is_var(p0, v)) { + if (!sign && a.get_kind() == atom::GT) { + return l_true; + } + if (!sign && a.get_kind() == atom::LT) { + return l_false; + } + return l_undef; + } + polynomial::scoped_numeral n(m_pm.m()); + if (m_pm.is_var_num(p0, v, n)) { + // x - k > 0 + if (!sign && a.get_kind() == atom::GT && m_pm.m().is_nonneg(n)) { + return l_true; + } + // x + k < 0 + if (!sign && a.get_kind() == atom::LT && m_pm.m().is_nonpos(n)) { + return l_false; + } + // !(x + k > 0) + if (sign && a.get_kind() == atom::GT && m_pm.m().is_pos(n)) { + return l_false; + } + // !(x - k < 0) + if (sign && a.get_kind() == atom::LT && m_pm.m().is_neg(n)) { + return l_true; + } + } + return l_undef; + } + + bool is_single_poly(ineq_atom const& a, poly*& p) { + unsigned sz = a.size(); + return sz == 1 && a.is_odd(0) && (p = a.p(0), true); + } + + bool is_unit(polynomial_ref const& p) { + if (!m_pm.is_const(p)) + return false; + auto const& c = m_pm.coeff(p, 0); + return m_pm.m().is_one(c) || m_pm.m().is_minus_one(c); + } + + // ----------------------- + // + // Pretty printing + // + // ----------------------- + + std::ostream& display_num_assignment(std::ostream & out, display_var_proc const & proc) const { + for (var x = 0; x < num_vars(); x++) { + if (m_assignment.is_assigned(x)) { + proc(out, x); + out << " -> "; + m_am.display_decimal(out, m_assignment.value(x)); + out << "\n"; + } + } + return out; + } + + std::ostream& display_bool_assignment(std::ostream & out) const { + unsigned sz = m_atoms.size(); + for (bool_var b = 0; b < sz; b++) { + if (m_atoms[b] == nullptr && m_bvalues[b] != l_undef) { + out << "b" << b << " -> " << (m_bvalues[b] == l_true ? "true" : "false") << " @" << m_levels[b] << "\n"; + } + else if (m_atoms[b] != nullptr && m_bvalues[b] != l_undef) { + display(out << "b" << b << " ", *m_atoms[b]) << " -> " << (m_bvalues[b] == l_true ? "true" : "false") << " @" << m_levels[b] << "\n"; + } + } + TRACE("nlsat_bool_assignment", + for (bool_var b = 0; b < sz; b++) { + out << "b" << b << " -> " << m_bvalues[b] << " "; + if (m_atoms[b]) display(out, *m_atoms[b]); + out << "\n"; + }); + return out; + } + + bool display_mathematica_assignment(std::ostream & out) const { + bool first = true; + for (var x = 0; x < num_vars(); x++) { + if (m_assignment.is_assigned(x)) { + if (first) + first = false; + else + out << " && "; + out << "x" << x << " == "; + m_am.display_mathematica(out, m_assignment.value(x)); + } + } + return !first; + } + + std::ostream& display_num_assignment(std::ostream & out) const { + return display_num_assignment(out, m_display_var); + } + + std::ostream& display_assignment(std::ostream& out) const { + display_bool_assignment(out); + display_num_assignment(out); + return out; + } + + std::ostream& display(std::ostream& out, justification j) const { + switch (j.get_kind()) { + case justification::CLAUSE: + display(out, *j.get_clause()) << "\n"; + break; + case justification::LAZY: { + lazy_justification const& lz = *j.get_lazy(); + display_not(out, lz.num_lits(), lz.lits()) << "\n"; + for (unsigned i = 0; i < lz.num_clauses(); ++i) { + display(out, lz.clause(i)) << "\n"; + } + break; + } + default: + out << j.get_kind() << "\n"; + break; + } + return out; + } + + bool m_display_eval = false; + std::ostream& display_eval(std::ostream& out, justification j) { + flet _display(m_display_eval, true); + return display(out, j); + } + + std::ostream& display_ineq(std::ostream & out, ineq_atom const & a, display_var_proc const & proc, bool use_star = false) const { + unsigned sz = a.size(); + for (unsigned i = 0; i < sz; i++) { + if (use_star && i > 0) + out << "*"; + bool is_even = a.is_even(i); + if (is_even || sz > 1) + out << "("; + display_polynomial(out, a.p(i), proc, use_star); + if (is_even || sz > 1) + out << ")"; + if (is_even) + out << "^2"; + } + switch (a.get_kind()) { + case atom::LT: out << " < 0"; break; + case atom::GT: out << " > 0"; break; + case atom::EQ: out << " = 0"; break; + default: UNREACHABLE(); break; + } + return out; + } + + std::ostream& display_mathematica(std::ostream & out, ineq_atom const & a) const { + unsigned sz = a.size(); + for (unsigned i = 0; i < sz; i++) { + if (i > 0) + out << "*"; + bool is_even = a.is_even(i); + if (sz > 1) + out << "("; + if (is_even) + out << "("; + m_pm.display(out, a.p(i), display_var_proc(), true); + if (is_even) + out << "^2)"; + if (sz > 1) + out << ")"; + } + switch (a.get_kind()) { + case atom::LT: out << " < 0"; break; + case atom::GT: out << " > 0"; break; + case atom::EQ: out << " == 0"; break; + default: UNREACHABLE(); break; + } + return out; + } + + std::ostream& display_polynomial_smt2(std::ostream & out, poly const* p, display_var_proc const & proc) const { + return m_pm.display_smt2(out, p, proc); + } + + std::ostream& display_ineq_smt2(std::ostream & out, ineq_atom const & a, display_var_proc const & proc) const { + switch (a.get_kind()) { + case atom::LT: out << "(< "; break; + case atom::GT: out << "(> "; break; + case atom::EQ: out << "(= "; break; + default: UNREACHABLE(); break; + } + unsigned sz = a.size(); + if (sz > 1) + out << "(* "; + for (unsigned i = 0; i < sz; i++) { + if (i > 0) out << " "; + if (a.is_even(i)) { + out << "(* "; + display_polynomial_smt2(out, a.p(i), proc); + out << " "; + display_polynomial_smt2(out, a.p(i), proc); + out << ")"; + } + else { + display_polynomial_smt2(out, a.p(i), proc); + } + } + if (sz > 1) + out << ")"; + out << " 0)"; + return out; + } + + std::ostream& display_poly_root(std::ostream& out, char const* y, root_atom const& a, display_var_proc const& proc) const { + out << "(exists (("; proc(out,a.x()); out << " Real))\n"; + out << "(and (= " << y << " "; + proc(out, a.x()); + out << ") (= 0 "; + display_polynomial_smt2(out, a.p(), proc); + out << ")))\n"; + return out; + } + + std::ostream& display_binary_smt2(std::ostream& out, poly const* p1, char const* rel, poly const* p2, display_var_proc const& proc) const { + out << "(" << rel << " "; + display_polynomial_smt2(out, p1, proc); + out << " "; + display_polynomial_smt2(out, p2, proc); + out << ")"; + return out; + } + + + std::ostream& display_linear_root_smt2(std::ostream & out, root_atom const & a, display_var_proc const & proc) const { + polynomial_ref A(m_pm), B(m_pm), Z(m_pm), Ax(m_pm); + polynomial::scoped_numeral zero(m_qm); + m_pm.m().set(zero, 0); + A = m_pm.derivative(a.p(), a.x()); + B = m_pm.neg(m_pm.substitute(a.p(), a.x(), zero)); + Z = m_pm.mk_zero(); + + Ax = m_pm.mul(m_pm.mk_polynomial(a.x()), A); + + // x < root[1](ax + b) == (a > 0 => ax + b < 0) & (a < 0 => ax + b > 0) + // x < root[1](ax + b) == (a > 0 => ax < -b) & (a < 0 => ax > -b) + + char const* rel1 = "<", *rel2 = ">"; + switch (a.get_kind()) { + case atom::ROOT_LT: rel1 = "<"; rel2 = ">"; break; + case atom::ROOT_GT: rel1 = ">"; rel2 = "<"; break; + case atom::ROOT_LE: rel1 = "<="; rel2 = ">="; break; + case atom::ROOT_GE: rel1 = ">="; rel2 = "<="; break; + case atom::ROOT_EQ: rel1 = rel2 = "="; break; + default: UNREACHABLE(); break; + } + + out << "(and "; + out << "(=> "; display_binary_smt2(out, A, ">", Z, proc); display_binary_smt2(out, Ax, rel1, B, proc); out << ") "; + out << "(=> "; display_binary_smt2(out, A, "<", Z, proc); display_binary_smt2(out, Ax, rel2, B, proc); out << ") "; + out << ")"; + + return out; + } + + + std::ostream& display_root_smt2(std::ostream& out, root_atom const& a, display_var_proc const& proc) const { + if (a.i() == 1 && m_pm.degree(a.p(), a.x()) == 1) + return display_linear_root_smt2(out, a, proc); +#if 1 + out << "(exists ("; + for (unsigned j = 0; j < a.i(); ++j) { + std::string y = std::string("y") + std::to_string(j); + out << "(" << y << " Real) "; + } + out << ")\n"; + out << "(and\n"; + for (unsigned j = 0; j < a.i(); ++j) { + std::string y = std::string("y") + std::to_string(j); + display_poly_root(out, y.c_str(), a, proc); + } + for (unsigned j = 0; j + 1 < a.i(); ++j) { + std::string y1 = std::string("y") + std::to_string(j); + std::string y2 = std::string("y") + std::to_string(j+1); + out << "(< " << y1 << " " << y2 << ")\n"; + } + + std::string yn = "y" + std::to_string(a.i() - 1); + + // TODO we need (forall z : z < yn . p(z) => z = y1 or ... z = y_{n-1}) + // to say y1, .., yn are the first n distinct roots. + // + out << "(forall ((z Real)) (=> (and (< z " << yn << ") "; display_poly_root(out, "z", a, proc) << ") "; + if (a.i() == 1) { + out << "false))\n"; + } + else { + out << "(or "; + for (unsigned j = 0; j + 1 < a.i(); ++j) { + std::string y1 = std::string("y") + std::to_string(j); + out << "(= z " << y1 << ") "; + } + out << ")))\n"; + } + switch (a.get_kind()) { + case atom::ROOT_LT: out << "(< "; proc(out, a.x()); out << " " << yn << ")"; break; + case atom::ROOT_GT: out << "(> "; proc(out, a.x()); out << " " << yn << ")"; break; + case atom::ROOT_LE: out << "(<= "; proc(out, a.x()); out << " " << yn << ")"; break; + case atom::ROOT_GE: out << "(>= "; proc(out, a.x()); out << " " << yn << ")"; break; + case atom::ROOT_EQ: out << "(= "; proc(out, a.x()); out << " " << yn << ")"; NOT_IMPLEMENTED_YET(); break; + default: UNREACHABLE(); break; + } + out << "))"; + return out; +#endif + + + return display_root(out, a, proc); + } + + std::ostream& display_root(std::ostream & out, root_atom const & a, display_var_proc const & proc) const { + proc(out, a.x()); + switch (a.get_kind()) { + case atom::ROOT_LT: out << " < "; break; + case atom::ROOT_GT: out << " > "; break; + case atom::ROOT_LE: out << " <= "; break; + case atom::ROOT_GE: out << " >= "; break; + case atom::ROOT_EQ: out << " = "; break; + default: UNREACHABLE(); break; + } + out << "root[" << a.i() << "]("; + display_polynomial(out, a.p(), proc); + out << ")"; + return out; + } + + struct mathematica_var_proc : public display_var_proc { + var m_x; + public: + mathematica_var_proc(var x):m_x(x) {} + std::ostream& operator()(std::ostream & out, var x) const override { + if (m_x == x) + return out << "#1"; + else + return out << "x" << x; + } + }; + + std::ostream& display_mathematica(std::ostream & out, root_atom const & a) const { + out << "x" << a.x(); + switch (a.get_kind()) { + case atom::ROOT_LT: out << " < "; break; + case atom::ROOT_GT: out << " > "; break; + case atom::ROOT_LE: out << " <= "; break; + case atom::ROOT_GE: out << " >= "; break; + case atom::ROOT_EQ: out << " == "; break; + default: UNREACHABLE(); break; + } + out << "Root["; + display_polynomial(out, a.p(), mathematica_var_proc(a.x()), true); + out << " &, " << a.i() << "]"; + return out; + } + + std::ostream& display(std::ostream & out, atom const & a, display_var_proc const & proc) const { + if (a.is_ineq_atom()) + return display_ineq(out, static_cast(a), proc); + else + return display_root(out, static_cast(a), proc); + } + + std::ostream& display(std::ostream & out, atom const & a) const { + return display(out, a, m_display_var); + } + + std::ostream& display_mathematica(std::ostream & out, atom const & a) const { + if (a.is_ineq_atom()) + return display_mathematica(out, static_cast(a)); + else + return display_mathematica(out, static_cast(a)); + } + + std::ostream& display_smt2(std::ostream & out, atom const & a, display_var_proc const & proc) const { + if (a.is_ineq_atom()) + return display_ineq_smt2(out, static_cast(a), proc); + else + return display_root_smt2(out, static_cast(a), proc); + } + + std::ostream& display_atom(std::ostream & out, bool_var b, display_var_proc const & proc) const { + if (b == 0) + out << "true"; + else if (m_atoms[b] == 0) + out << "b" << b; + else + display(out, *(m_atoms[b]), proc); + return out; + } + + std::ostream& display_atom(std::ostream & out, bool_var b) const { + return display_atom(out, b, m_display_var); + } + + std::ostream& display_mathematica_atom(std::ostream & out, bool_var b) const { + if (b == 0) + out << "(0 < 1)"; + else if (m_atoms[b] == 0) + out << "b" << b; + else + display_mathematica(out, *(m_atoms[b])); + return out; + } + + std::ostream& display_smt2_atom(std::ostream & out, bool_var b, display_var_proc const & proc) const { + if (b == 0) + out << "true"; + else if (m_atoms[b] == 0) + out << "b" << b; + else + display_smt2(out, *(m_atoms[b]), proc); + return out; + } + + std::ostream& display(std::ostream & out, literal l, display_var_proc const & proc) const { + if (l.sign()) { + bool_var b = l.var(); + out << "!"; + if (m_atoms[b] != 0) + out << "("; + display_atom(out, b, proc); + if (m_atoms[b] != 0) + out << ")"; + } + else { + display_atom(out, l.var(), proc); + } + return out; + } + + std::ostream& display(std::ostream & out, literal l) const { + return display(out, l, m_display_var); + } + + std::ostream& display_smt2(std::ostream & out, literal l) const { + return display_smt2(out, l, m_display_var); + } + + std::ostream& display_mathematica(std::ostream & out, literal l) const { + if (l.sign()) { + bool_var b = l.var(); + out << "!"; + if (m_atoms[b] != 0) + out << "("; + display_mathematica_atom(out, b); + if (m_atoms[b] != 0) + out << ")"; + } + else { + display_mathematica_atom(out, l.var()); + } + return out; + } + + std::ostream& display_smt2(std::ostream & out, literal l, display_var_proc const & proc) const { + if (l.sign()) { + bool_var b = l.var(); + out << "(not "; + display_smt2_atom(out, b, proc); + out << ")"; + } + else { + display_smt2_atom(out, l.var(), proc); + } + return out; + } + + std::ostream& display_assumptions(std::ostream & out, _assumption_set s) const { + if (!m_display_assumption) + return out; + vector deps; + m_asm.linearize(s, deps); + bool first = true; + for (auto dep : deps) { + if (first) first = false; else out << " "; + (*m_display_assumption)(out, dep); + } + return out; + } + + std::ostream& display(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { + for (unsigned i = 0; i < num; i++) { + if (i > 0) + out << " or "; + display(out, ls[i], proc); + } + return out; + } + + std::ostream& display(std::ostream & out, unsigned num, literal const * ls) const { + return display(out, num, ls, m_display_var); + } + + std::ostream& display_not(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { + for (unsigned i = 0; i < num; i++) { + if (i > 0) + out << " or "; + display(out, ~ls[i], proc); + } + return out; + } + + std::ostream& display_not(std::ostream & out, unsigned num, literal const * ls) const { + return display_not(out, num, ls, m_display_var); + } + + std::ostream& display(std::ostream & out, scoped_literal_vector const & cs) { + return display(out, cs.size(), cs.data(), m_display_var); + } + + std::ostream& display(std::ostream & out, clause const & c, display_var_proc const & proc) const { + if (c.assumptions() != nullptr) { + display_assumptions(out, static_cast<_assumption_set>(c.assumptions())); + out << " |- "; + } + return display(out, c.size(), c.data(), proc); + } + + std::ostream& display(std::ostream & out, clause const & c) const { + return display(out, c, m_display_var); + } + + + std::ostream& display_polynomial(std::ostream& out, poly* p, display_var_proc const & proc, bool use_star = false) const { + if (m_display_eval) { + polynomial_ref q(m_pm); + q = p; + for (var x = 0; x < num_vars(); x++) + if (m_assignment.is_assigned(x)) { + auto& a = m_assignment.value(x); + if (!m_am.is_rational(a)) + continue; + mpq r; + m_am.to_rational(a, r); + q = m_pm.substitute(q, 1, &x, &r); + } + m_pm.display(out, q, proc, use_star); + } + else + m_pm.display(out, p, proc, use_star); + return out; + } + + // -- + + std::ostream& display_smt2(std::ostream & out, unsigned n, literal const* ls) const { + return display_smt2(out, n, ls, display_var_proc()); + } + + + std::ostream& display_smt2(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { + if (num == 0) { + out << "false"; + } + else if (num == 1) { + display_smt2(out, ls[0], proc); + } + else { + out << "(or"; + for (unsigned i = 0; i < num; i++) { + out << " "; + display_smt2(out, ls[i], proc); + } + out << ")"; + } + return out; + } + + std::ostream& display_smt2(std::ostream & out, clause const & c, display_var_proc const & proc = display_var_proc()) const { + return display_smt2(out, c.size(), c.data(), proc); + } + + std::ostream& display_abst(std::ostream & out, literal l) const { + if (l.sign()) { + bool_var b = l.var(); + out << "!"; + if (b == true_bool_var) + out << "true"; + else + out << "b" << b; + } + else { + out << "b" << l.var(); + } + return out; + } + + std::ostream& display_abst(std::ostream & out, unsigned num, literal const * ls) const { + for (unsigned i = 0; i < num; i++) { + if (i > 0) + out << " or "; + display_abst(out, ls[i]); + } + return out; + } + + std::ostream& display_abst(std::ostream & out, scoped_literal_vector const & cs) const { + return display_abst(out, cs.size(), cs.data()); + } + + std::ostream& display_abst(std::ostream & out, clause const & c) const { + return display_abst(out, c.size(), c.data()); + } + + std::ostream& display_mathematica(std::ostream & out, clause const & c) const { + out << "("; + unsigned sz = c.size(); + for (unsigned i = 0; i < sz; i++) { + if (i > 0) + out << " || "; + display_mathematica(out, c[i]); + } + out << ")"; + return out; + } + + // Debugging support: + // Display generated lemma in Mathematica format. + // Mathematica must reduce lemma to True (modulo resource constraints). + std::ostream& display_mathematica_lemma(std::ostream & out, unsigned num, literal const * ls, bool include_assignment = false) const { + out << "Resolve[ForAll[{"; + // var definition + for (unsigned i = 0; i < num_vars(); i++) { + if (i > 0) + out << ", "; + out << "x" << i; + } + out << "}, "; + if (include_assignment) { + out << "!("; + if (!display_mathematica_assignment(out)) + out << "0 < 1"; // nothing was printed + out << ") || "; + } + for (unsigned i = 0; i < num; i++) { + if (i > 0) + out << " || "; + display_mathematica(out, ls[i]); + } + out << "], Reals]\n"; // end of exists + return out; + } + + std::ostream& display(std::ostream & out, clause_vector const & cs, display_var_proc const & proc) const { + for (clause* c : cs) { + display(out, *c, proc) << "\n"; + } + return out; + } + + std::ostream& display(std::ostream & out, clause_vector const & cs) const { + return display(out, cs, m_display_var); + } + + std::ostream& display_mathematica(std::ostream & out, clause_vector const & cs) const { + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) { + if (i > 0) out << ",\n"; + display_mathematica(out << " ", *(cs[i])); + } + return out; + } + + std::ostream& display_abst(std::ostream & out, clause_vector const & cs) const { + for (clause* c : cs) { + display_abst(out, *c) << "\n"; + } + return out; + } + + std::ostream& display(std::ostream & out, display_var_proc const & proc) const { + display(out, m_clauses, proc); + if (!m_learned.empty()) { + display(out << "Lemmas:\n", m_learned, proc); + } + return out; + } + + std::ostream& display_mathematica(std::ostream & out) const { + return display_mathematica(out << "{\n", m_clauses) << "}\n"; + } + + std::ostream& display_abst(std::ostream & out) const { + display_abst(out, m_clauses); + if (!m_learned.empty()) { + display_abst(out << "Lemmas:\n", m_learned); + } + return out; + } + + std::ostream& display(std::ostream & out) const { + display(out, m_display_var); + display_assignment(out << "assignment:\n"); + return out << "---\n"; + } + + std::ostream& display_vars(std::ostream & out) const { + for (unsigned i = 0; i < num_vars(); i++) { + out << i << " -> "; m_display_var(out, i); out << "\n"; + } + return out; + } + + std::ostream& display_smt2_arith_decls(std::ostream & out) const { + unsigned sz = m_is_int.size(); + for (unsigned i = 0; i < sz; i++) { + if (is_int(i)) { + out << "(declare-fun "; m_display_var(out, i) << " () Int)\n"; + } + else { + out << "(declare-fun "; m_display_var(out, i) << " () Real)\n"; + } + } + return out; + } + + std::ostream& display_smt2_bool_decls(std::ostream & out) const { + unsigned sz = m_atoms.size(); + for (unsigned i = 0; i < sz; i++) { + if (m_atoms[i] == nullptr) + out << "(declare-fun b" << i << " () Bool)\n"; + } + return out; + } + + std::ostream& display_smt2(std::ostream & out) const { + display_smt2_bool_decls(out); + display_smt2_arith_decls(out); + out << "(assert (and true\n"; + for (clause* c : m_clauses) { + display_smt2(out, *c, m_display_var) << "\n"; + } + out << "))\n" << std::endl; + return out; + } + }; + + solver::solver(reslimit& rlim, params_ref const & p, bool incremental) { + m_ctx = alloc(ctx, rlim, p, incremental); + m_imp = alloc(imp, *this, *m_ctx); + } + + solver::solver(ctx& ctx) { + m_ctx = nullptr; + m_imp = alloc(imp, *this, ctx); + } + + solver::~solver() { + dealloc(m_imp); + dealloc(m_ctx); + } + + lbool solver::check() { + return m_imp->check(); + } + + lbool solver::check(literal_vector& assumptions) { + return m_imp->check(assumptions); + } + + void solver::get_core(vector& assumptions) { + return m_imp->get_core(assumptions); + } + + void solver::reset() { + m_imp->reset(); + } + + + void solver::updt_params(params_ref const & p) { + m_imp->updt_params(p); + } + + + void solver::collect_param_descrs(param_descrs & d) { + algebraic_numbers::manager::collect_param_descrs(d); + nlsat_params::collect_param_descrs(d); + } + + unsynch_mpq_manager & solver::qm() { + return m_imp->m_qm; + } + + anum_manager & solver::am() { + return m_imp->m_am; + } + + pmanager & solver::pm() { + return m_imp->m_pm; + } + + void solver::set_display_var(display_var_proc const & proc) { + m_imp->m_display_var.m_proc = &proc; + } + + void solver::set_display_assumption(display_assumption_proc const& proc) { + m_imp->m_display_assumption = &proc; + } + + + unsigned solver::num_vars() const { + return m_imp->num_vars(); + } + + bool solver::is_int(var x) const { + return m_imp->is_int(x); + } + + bool_var solver::mk_bool_var() { + return m_imp->mk_bool_var(); + } + + literal solver::mk_true() { + return literal(0, false); + } + + atom * solver::bool_var2atom(bool_var b) { + return m_imp->m_atoms[b]; + } + + void solver::vars(literal l, var_vector& vs) { + m_imp->vars(l, vs); + } + + atom_vector const& solver::get_atoms() { + return m_imp->m_atoms; + } + + atom_vector const& solver::get_var2eq() { + return m_imp->m_var2eq; + } + + evaluator& solver::get_evaluator() { + return m_imp->m_evaluator; + } + + explain& solver::get_explain() { + return m_imp->m_explain; + } + + void solver::reorder(unsigned sz, var const* p) { + m_imp->reorder(sz, p); + } + + void solver::restore_order() { + m_imp->restore_order(); + } + + void solver::set_rvalues(assignment const& as) { + m_imp->m_assignment.copy(as); + } + + void solver::get_rvalues(assignment& as) { + as.copy(m_imp->m_assignment); + } + + void solver::get_bvalues(svector const& bvars, svector& vs) { + vs.reset(); + for (bool_var b : bvars) { + vs.reserve(b + 1, l_undef); + if (!m_imp->m_atoms[b]) { + vs[b] = m_imp->m_bvalues[b]; + } + } + TRACE("nlsat", display(tout);); + } + + void solver::set_bvalues(svector const& vs) { + TRACE("nlsat", display(tout);); + for (bool_var b = 0; b < vs.size(); ++b) { + if (vs[b] != l_undef) { + m_imp->m_bvalues[b] = vs[b]; + SASSERT(!m_imp->m_atoms[b]); + } + } +#if 0 + m_imp->m_bvalues.reset(); + m_imp->m_bvalues.append(vs); + m_imp->m_bvalues.resize(m_imp->m_atoms.size(), l_undef); + for (unsigned i = 0; i < m_imp->m_atoms.size(); ++i) { + atom* a = m_imp->m_atoms[i]; + SASSERT(!a); + if (a) { + m_imp->m_bvalues[i] = to_lbool(m_imp->m_evaluator.eval(a, false)); + } + } +#endif + TRACE("nlsat", display(tout);); + } + + void solver::del_clause(clause* c) { + m_imp->del_clause(c); + } + + var solver::mk_var(bool is_int) { + return m_imp->mk_var(is_int); + } + + bool_var solver::mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even) { + return m_imp->mk_ineq_atom(k, sz, ps, is_even); + } + + literal solver::mk_ineq_literal(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify) { + return m_imp->mk_ineq_literal(k, sz, ps, is_even, simplify); + } + + bool_var solver::mk_root_atom(atom::kind k, var x, unsigned i, poly * p) { + return m_imp->mk_root_atom(k, x, i, p); + } + + void solver::inc_ref(bool_var b) { + m_imp->inc_ref(b); + } + + void solver::dec_ref(bool_var b) { + m_imp->dec_ref(b); + } + + void solver::inc_ref(assumption a) { + m_imp->inc_ref(static_cast(a)); + } + + void solver::dec_ref(assumption a) { + m_imp->dec_ref(static_cast(a)); + } + + void solver::mk_clause(unsigned num_lits, literal * lits, assumption a) { + return m_imp->mk_external_clause(num_lits, lits, a); + } + + std::ostream& solver::display(std::ostream & out) const { + return m_imp->display(out); + } + + std::ostream& solver::display(std::ostream & out, literal l) const { + return m_imp->display(out, l); + } + + std::ostream& solver::display(std::ostream & out, unsigned n, literal const* ls) const { + for (unsigned i = 0; i < n; ++i) { + display(out, ls[i]); + out << "; "; + } + return out; + } + + std::ostream& solver::display(std::ostream & out, literal_vector const& ls) const { + return display(out, ls.size(), ls.data()); + } + + std::ostream& solver::display_smt2(std::ostream & out, literal l) const { + return m_imp->display_smt2(out, l); + } + + std::ostream& solver::display_smt2(std::ostream & out, unsigned n, literal const* ls) const { + for (unsigned i = 0; i < n; ++i) { + display_smt2(out, ls[i]); + out << " "; + } + return out; + } + + std::ostream& solver::display(std::ostream& out, clause const& c) const { + return m_imp->display(out, c); + } + + std::ostream& solver::display_smt2(std::ostream & out) const { + return m_imp->display_smt2(out); + } + + std::ostream& solver::display_smt2(std::ostream & out, literal_vector const& ls) const { + return display_smt2(out, ls.size(), ls.data()); + } + + std::ostream& solver::display(std::ostream & out, var x) const { + return m_imp->m_display_var(out, x); + } + + std::ostream& solver::display(std::ostream & out, atom const& a) const { + return m_imp->display(out, a, m_imp->m_display_var); + } + + display_var_proc const & solver::display_proc() const { + return m_imp->m_display_var; + } + + anum const & solver::value(var x) const { + if (m_imp->m_assignment.is_assigned(x)) + return m_imp->m_assignment.value(x); + return m_imp->m_zero; + } + + lbool solver::bvalue(bool_var b) const { + return m_imp->m_bvalues[b]; + } + + lbool solver::value(literal l) const { + return m_imp->value(l); + } + + bool solver::is_interpreted(bool_var b) const { + return m_imp->m_atoms[b] != 0; + } + + void solver::reset_statistics() { + return m_imp->reset_statistics(); + } + + void solver::collect_statistics(statistics & st) { + return m_imp->collect_statistics(st); + } + + clause* solver::mk_clause(unsigned n, literal const* lits, bool learned, internal_assumption a) { + return m_imp->mk_clause(n, lits, learned, static_cast(a)); + } + + void solver::inc_simplify() { + m_imp->m_stats.m_simplifications++; + } + + bool solver::has_root_atom(clause const& c) const { + return m_imp->has_root_atom(c); + } + + void solver::add_bound(bound_constraint const& c) { + m_imp->m_bounds.push_back(c); + } + + assumption solver::join(assumption a, assumption b) { + return (m_imp->m_asm.mk_join(static_cast(a), static_cast(b))); + } + +}; From 518a8b2bdb662e141f40d13a6712522a439cee71 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 8 Aug 2024 12:42:30 -1000 Subject: [PATCH 054/187] fix the build Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_simple_checker.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nlsat/nlsat_simple_checker.cpp b/src/nlsat/nlsat_simple_checker.cpp index 047b67e0e..f4bb5e648 100644 --- a/src/nlsat/nlsat_simple_checker.cpp +++ b/src/nlsat/nlsat_simple_checker.cpp @@ -301,6 +301,7 @@ namespace nlsat { if (kd == atom::GT) return GT; UNREACHABLE(); + return EQ; } bool update_interval_intersection(Domain_Interval &ia, const Domain_Interval &ib) { TRACE("linxi_simple_checker", @@ -2059,4 +2060,4 @@ else { // ( == 0) + (c > 0) -> > 0 LINXI_DEBUG; return m_imp->operator()(); } -} \ No newline at end of file +} From f7905a5d6914e863e76e5a5f609935fcde1470d3 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 8 Aug 2024 14:50:17 -1000 Subject: [PATCH 055/187] remove printouts --- src/nlsat/nlsat_solver.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index d50752460..486d88cc6 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -1838,7 +1838,6 @@ namespace nlsat { //#linxi begin symmetry check void symmetry_check() { - std::cout << "sym called\n"; unsigned arith_num = m_is_int.size(); if (arith_num > 10000) return ; @@ -1923,7 +1922,6 @@ namespace nlsat { } //#linxi begin Variable Ordering Strategy else if (m_linxi_variable_ordering_strategy > 0) { - std::cout << "m_linxi_variable_ordering_strategy=" << m_linxi_variable_ordering_strategy << "\n"; run_variable_ordering_strategy(); reordered = true; } From f81303f2f3c99d6afb6ceeb96e300f660bd95106 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 8 Aug 2024 15:06:33 -1000 Subject: [PATCH 056/187] delete unused nlsat_symmetry_checker Signed-off-by: Lev Nachmanson --- src/nlsat/CMakeLists.txt | 1 - src/nlsat/nlsat_params.pyg | 1 - src/nlsat/nlsat_solver.cpp | 44 ---- src/nlsat/nlsat_symmetry_checker.cpp | 356 --------------------------- src/nlsat/nlsat_symmetry_checker.h | 13 - 5 files changed, 415 deletions(-) delete mode 100644 src/nlsat/nlsat_symmetry_checker.cpp delete mode 100644 src/nlsat/nlsat_symmetry_checker.h diff --git a/src/nlsat/CMakeLists.txt b/src/nlsat/CMakeLists.txt index 7aa1d83c5..077c420f9 100644 --- a/src/nlsat/CMakeLists.txt +++ b/src/nlsat/CMakeLists.txt @@ -9,7 +9,6 @@ z3_add_component(nlsat nlsat_types.cpp nlsat_simple_checker.cpp nlsat_variable_ordering_strategy.cpp - nlsat_symmetry_checker.cpp COMPONENT_DEPENDENCIES polynomial sat diff --git a/src/nlsat/nlsat_params.pyg b/src/nlsat/nlsat_params.pyg index 73067d48b..00d179901 100644 --- a/src/nlsat/nlsat_params.pyg +++ b/src/nlsat/nlsat_params.pyg @@ -6,7 +6,6 @@ def_module_params('nlsat', ('linxi_simple_check', BOOL, False, "linxi precheck about variables sign"), ('linxi_variable_ordering_strategy', UINT, 0, "linxi Variable Ordering Strategy, 0 for none, 1 for BROWN, 2 for TRIANGULAR, 3 for ONLYPOLY"), ('cell_sample', BOOL, True, "cell sample projection"), - ('linxi_symmetry_check', BOOL, False, "linxi symmetry check and learning"), ('lazy', UINT, 0, "how lazy the solver is."), ('reorder', BOOL, True, "reorder variables."), ('log_lemmas', BOOL, False, "display lemmas as self-contained SMT formulas"), diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index 486d88cc6..30ca55e31 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -36,7 +36,6 @@ Revision History: #include "nlsat/nlsat_simplify.h" #include "nlsat/nlsat_simple_checker.h" #include "nlsat/nlsat_variable_ordering_strategy.h" -#include "nlsat/nlsat_symmetry_checker.h" #define NLSAT_EXTRA_VERBOSE @@ -226,7 +225,6 @@ namespace nlsat { //#linxi begin bool m_linxi_simple_check; unsigned m_linxi_variable_ordering_strategy; - bool m_linxi_symmetry_check; bool m_linxi_set_0_more; bool m_cell_sample; //#linxi end @@ -302,7 +300,6 @@ namespace nlsat { //#linxi begin m_linxi_simple_check = p.linxi_simple_check(); m_linxi_variable_ordering_strategy = p.linxi_variable_ordering_strategy(); - m_linxi_symmetry_check = p.linxi_symmetry_check(); //#linxi end @@ -1836,41 +1833,7 @@ namespace nlsat { //#linxi end Variable Ordering Strategy -//#linxi begin symmetry check - void symmetry_check() { - unsigned arith_num = m_is_int.size(); - if (arith_num > 10000) - return ; - Symmetry_Checker checker(m_pm, m_qm, m_clauses, m_atoms, m_is_int, arith_num); - for (var x = 0; x < arith_num; ++x) { - for (var y = x + 1; y < arith_num; ++y) { - if (checker.check_symmetry(x, y)) { - TRACE("linxi_symmetry_checker", - tout << "symmetry: " << x << ", " << y << "\n"; - ); - rational zero(0); - vector as; - vector xs; - as.push_back(rational(1)); - xs.push_back(x); - as.push_back(rational(-1)); - xs.push_back(y); - polynomial_ref pr(m_pm); - pr = m_pm.mk_linear(2, as.data(), xs.data(), zero); - poly* p = pr.get(); - bool is_even = false; - literal lit = ~mk_ineq_literal(atom::GT, 1, &p, &is_even); - clause *cla = mk_clause(1, &lit, true, nullptr); - } - } - } - TRACE("linxi_symmetry_checker", - display(tout); - ); - - } -//#linxi end symmetry check void apply_reorder() { m_reordered = false; if (!can_reorder()) @@ -1887,13 +1850,6 @@ namespace nlsat { lbool check() { -//#linxi begin symmetry check - if (m_linxi_symmetry_check) { - symmetry_check(); - } - // exit(0); -//#linxi end symmetry check - //#linxi begin simple check if (m_linxi_simple_check) { if (!simple_check()) { diff --git a/src/nlsat/nlsat_symmetry_checker.cpp b/src/nlsat/nlsat_symmetry_checker.cpp deleted file mode 100644 index 8d0ee8766..000000000 --- a/src/nlsat/nlsat_symmetry_checker.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#include "nlsat/nlsat_symmetry_checker.h" - -struct Debug_Tracer { - std::string tag_str; - Debug_Tracer(std::string _tag_str) { - tag_str = _tag_str; - TRACE("linxi_symmetry_checker", - tout << "Debug_Tracer begin\n"; - tout << tag_str << "\n"; - ); - } - ~Debug_Tracer() { - TRACE("linxi_symmetry_checker", - tout << "Debug_Tracer end\n"; - tout << tag_str << "\n"; - ); - } -}; - -// #define _LINXI_DEBUG - -#ifdef _LINXI_DEBUG -#define LINXI_DEBUG_CORE(x) std::stringstream DEBUG_ss_##x; DEBUG_ss_##x << __FUNCTION__ << " " << __FILE__ << ":" << __LINE__; Debug_Tracer DEBUG_dt_##x(DEBUG_ss_##x.str()); -#define LINXI_DEBUG_TRANS(x) LINXI_DEBUG_CORE(x); -#define LINXI_DEBUG LINXI_DEBUG_TRANS(__LINE__); -#define LINXI_HERE TRACE("linxi_symmetry_checker", tout << "here\n";); -#else -#define LINXI_DEBUG { }((void) 0 ); -#define LINXI_HERE { }((void) 0 ); -#endif - - - -namespace nlsat { - struct Symmetry_Checker::imp { - // solver / - pmanager ± - unsynch_mpq_manager &qm; - const clause_vector &clauses; - const atom_vector &atoms; - const bool_vector &is_int; - const unsigned arith_var_num; - // vector vars_hash; - vector> vars_occur; - bool is_check; - var tx, ty; - struct Variable_Information { - unsigned long long hash_value; - unsigned deg; - var x; - bool is_int; - bool operator< (const Variable_Information &rhs) const { - return hash_value < rhs.hash_value; - } - bool operator== (const Variable_Information &rhs) const { - if (hash_value != rhs.hash_value) - return false; - if (deg != rhs.deg) - return false; - if (x != rhs.x) - return false; - if (is_int != rhs.is_int) - return false; - return true; - } - bool operator!= (const Variable_Information &rhs) const { - return !(*this == rhs); - } - }; - unsigned long long VAR_BASE = 601; - void collect_var_info(Variable_Information &var_info, var x, unsigned deg) { - LINXI_DEBUG; - if (is_check) { - if (x == tx) { - x = ty; - } - else if (x == ty) { - x = tx; - } - else { - // do nothing - } - } - else { - vars_occur[x].push_back(deg); - } - var_info.deg = deg; - var_info.x = x; - var_info.is_int = is_int[x]; - var_info.hash_value = 0; - for (unsigned i = 0; i < deg; ++i) { - var_info.hash_value = var_info.hash_value*VAR_BASE + (unsigned long long)x; - } - var_info.hash_value = var_info.hash_value*VAR_BASE + (unsigned long long)var_info.is_int; - } - struct Monomial_Information { - unsigned long long hash_value; - unsigned long long coef; - vector vars_info; - bool operator< (const Monomial_Information &rhs) const { - return hash_value < rhs.hash_value; - } - bool operator== (const Monomial_Information &rhs) const { - if (hash_value != rhs.hash_value) - return false; - if (coef != rhs.coef) - return false; - if (vars_info.size() != rhs.vars_info.size()) - return false; - for (unsigned i = 0, sz = vars_info.size(); i < sz; ++i) { - if (vars_info[i] != rhs.vars_info[i]) - return false; - } - return true; - } - bool operator!= (const Monomial_Information &rhs) const { - return !(*this == rhs); - } - }; - unsigned long long MONO_BASE = 99991; - - void collect_mono_info(Monomial_Information &mono_info, monomial *m, unsigned long long coef) { - LINXI_DEBUG; - unsigned sz = pm.size(m); - mono_info.vars_info.resize(sz); - for (unsigned i = 0; i < sz; ++i) { - collect_var_info(mono_info.vars_info[i], pm.get_var(m, i), pm.degree(m, i)); - } - mono_info.coef = coef; - mono_info.hash_value = coef; - std::sort(mono_info.vars_info.begin(), mono_info.vars_info.end()); - for (unsigned i = 0; i < sz; ++i) { - mono_info.hash_value = mono_info.hash_value*MONO_BASE + mono_info.vars_info[i].hash_value; - } - } - struct Polynomial_Information { - unsigned long long hash_value; - bool is_even; - vector monos_info; - bool operator< (const Polynomial_Information &rhs) const { - return hash_value < rhs.hash_value; - } - bool operator== (const Polynomial_Information &rhs) const { - if (hash_value != rhs.hash_value) - return false; - if (is_even != rhs.is_even) - return false; - if (monos_info.size() != rhs.monos_info.size()) - return false; - for (unsigned i = 0, sz = monos_info.size(); i < sz; ++i) { - if (monos_info[i] != rhs.monos_info[i]) - return false; - } - return true; - } - bool operator!= (const Polynomial_Information &rhs) const { - return !(*this == rhs); - } - }; - unsigned long long POLY_BASE = 99991; - void collect_poly_info(Polynomial_Information &poly_info, poly *p, bool is_even) { - LINXI_DEBUG; - unsigned sz = pm.size(p); - poly_info.monos_info.resize(sz); - for (unsigned i = 0; i < sz; ++i) { - collect_mono_info(poly_info.monos_info[i], pm.get_monomial(p, i), qm.get_uint64(pm.coeff(p, i))); - } - poly_info.hash_value = 0; - std::sort(poly_info.monos_info.begin(), poly_info.monos_info.end()); - for (unsigned i = 0; i < sz; ++i) { - poly_info.hash_value = poly_info.hash_value*POLY_BASE + poly_info.monos_info[i].hash_value; - } - poly_info.is_even = is_even; - if (is_even) { - poly_info.hash_value = poly_info.hash_value*poly_info.hash_value; - } - } - struct Atom_Information { - unsigned long long hash_value; - atom::kind akd; - vector polys_info; - bool operator< (const Atom_Information &rhs) const { - return hash_value < rhs.hash_value; - } - bool operator== (const Atom_Information &rhs) const { - if (hash_value != rhs.hash_value) - return false; - if (akd != rhs.akd) - return false; - if (polys_info.size() != rhs.polys_info.size()) - return false; - for (unsigned i = 0, sz = polys_info.size(); i < sz; ++i) { - if (polys_info[i] != rhs.polys_info[i]) - return false; - } - return true; - } - bool operator!= (const Atom_Information &rhs) const { - return !(*this == rhs); - } - }; - unsigned long long ATOM_BASE = 233; - void collect_atom_info(Atom_Information &atom_info, ineq_atom *iat) { - LINXI_DEBUG; - unsigned sz = iat->size(); - atom_info.polys_info.resize(sz); - for (unsigned i = 0; i < sz; ++i) { - collect_poly_info(atom_info.polys_info[i], iat->p(i), iat->is_even(i)); - } - atom_info.hash_value = 0; - std::sort(atom_info.polys_info.begin(), atom_info.polys_info.end()); - for (unsigned i = 0; i < sz; ++i) { - atom_info.hash_value = atom_info.hash_value*ATOM_BASE + atom_info.polys_info[i].hash_value; - } - atom_info.akd = iat->get_kind(); - atom_info.hash_value = atom_info.hash_value*ATOM_BASE + (unsigned long long)atom_info.akd; - } - struct Literal_Information { - unsigned long long hash_value; - vector atom_info; // not atoms - bool operator< (const Literal_Information &rhs) const { - return hash_value < rhs.hash_value; - } - bool operator== (const Literal_Information &rhs) const { - if (hash_value != rhs.hash_value) - return false; - if (atom_info.size() != rhs.atom_info.size()) - return false; - for (unsigned i = 0, sz = atom_info.size(); i < sz; ++i) { - if (atom_info[i] != rhs.atom_info[i]) - return false; - } - return true; - } - bool operator!= (const Literal_Information &rhs) const { - return !(*this == rhs); - } - }; - void collect_lit_info(Literal_Information &lit_info, literal lit) { - LINXI_DEBUG; - atom *at = atoms[lit.var()]; - if (at == nullptr || !at->is_ineq_atom()) { - lit_info.hash_value = lit.to_uint(); - } - else { - lit_info.atom_info.resize(1); - collect_atom_info(lit_info.atom_info[0], to_ineq_atom(at)); - lit_info.hash_value = lit_info.atom_info[0].hash_value; - } - } - struct Clause_Information { - unsigned long long hash_value; - vector lits_info; - bool operator< (const Clause_Information &rhs) const { - return hash_value < rhs.hash_value; - } - bool operator== (const Clause_Information &rhs) const { - if (hash_value != rhs.hash_value) - return false; - if (lits_info.size() != rhs.lits_info.size()) - return false; - for (unsigned i = 0, sz = lits_info.size(); i < sz; ++i) { - if (lits_info[i] != rhs.lits_info[i]) - return false; - } - return true; - } - bool operator!= (const Clause_Information &rhs) const { - return !(*this == rhs); - } - }; - unsigned long long CLA_BASE = 9973; - void collect_cla_info(Clause_Information &cla_info, clause *cla) { - LINXI_DEBUG; - unsigned sz = cla->size(); - cla_info.lits_info.resize(sz); - for (unsigned i = 0; i < sz; ++i) { - literal lit = (*cla)[i]; - collect_lit_info(cla_info.lits_info[i], lit); - } - cla_info.hash_value = 0; - std::sort(cla_info.lits_info.begin(), cla_info.lits_info.end()); - for (unsigned i = 0; i < sz; ++i) { - cla_info.hash_value = cla_info.hash_value*CLA_BASE + cla_info.lits_info[i].hash_value; - } - } - - void collect_clas_info(vector &clas_info) { - LINXI_DEBUG; - unsigned sz = clauses.size(); - clas_info.resize(sz); - for (unsigned i = 0; i < sz; ++i) { - collect_cla_info(clas_info[i], clauses[i]); - } - std::sort(clas_info.begin(), clas_info.end()); - if (!is_check) { - for (unsigned i = 0; i < arith_var_num; ++i) { - std::sort(vars_occur[i].begin(), vars_occur[i].begin()); - } - } - } - vector ori_clas_info; - imp(pmanager &_pm, unsynch_mpq_manager &_qm, const clause_vector &_clauses, const atom_vector &_atoms, const bool_vector &_is_int, const unsigned &_arith_var_num) : - // sol(_sol), - pm(_pm), - qm(_qm), - clauses(_clauses), - atoms(_atoms), - is_int(_is_int), - arith_var_num(_arith_var_num), - is_check(false) { - vars_occur.resize(arith_var_num); - collect_clas_info(ori_clas_info); - // vars_hash.resize(arith_var_num, 0); - } - vector check_clas_info; - bool check_occur_same(var x, var y) { - if (vars_occur[x].size() != vars_occur[y].size()) - return false; - for (unsigned i = 0, sz = vars_occur[x].size(); i < sz; ++i) { - if (vars_occur[x][i] != vars_occur[y][i]) - return false; - } - return true; - } - bool check_symmetry(var x, var y) { - if (!check_occur_same(x, y)) { - return false; - } - is_check = true; - tx = x, ty = y; - collect_clas_info(check_clas_info); - for (unsigned i = 0, sz = clauses.size(); i < sz; ++i) { - if (ori_clas_info[i] != check_clas_info[i]) - return false; - } - return true; - } - }; - Symmetry_Checker::Symmetry_Checker(pmanager &_pm, unsynch_mpq_manager &_qm, const clause_vector &_clauses, const atom_vector &_atoms, const bool_vector &_is_int, const unsigned &_arith_var_num) { - LINXI_DEBUG; - // m_imp = alloc(imp, _sol, _pm, _am, _clauses, _learned, _atoms, _arith_var_num); - m_imp = alloc(imp, _pm, _qm, _clauses, _atoms, _is_int, _arith_var_num); - } - Symmetry_Checker::~Symmetry_Checker() { - LINXI_DEBUG; - dealloc(m_imp); - } - // bool Symmetry_Checker::operator()() { - // LINXI_DEBUG; - - // } - bool Symmetry_Checker::check_symmetry(var x, var y) { - return m_imp->check_symmetry(x, y); - } -} \ No newline at end of file diff --git a/src/nlsat/nlsat_symmetry_checker.h b/src/nlsat/nlsat_symmetry_checker.h deleted file mode 100644 index 1db5cb24b..000000000 --- a/src/nlsat/nlsat_symmetry_checker.h +++ /dev/null @@ -1,13 +0,0 @@ -#include "nlsat/nlsat_clause.h" - -namespace nlsat { - class Symmetry_Checker { - struct imp; - imp * m_imp; - public: - // Simple_Checker(solver &_sol, pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, clause_vector &_learned, const atom_vector &_atoms, const unsigned &_arith_var_num); - Symmetry_Checker(pmanager &_pm, unsynch_mpq_manager &_qm, const clause_vector &_clauses, const atom_vector &_atoms, const bool_vector &_is_int, const unsigned &_arith_var_num); - ~Symmetry_Checker(); - bool check_symmetry(var x, var y); - }; -} \ No newline at end of file From 752c999e0a3ef95936986d20f9f84ef64c8bcd3b Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Fri, 9 Aug 2024 08:16:35 -1000 Subject: [PATCH 057/187] cleanup Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_params.pyg | 5 +- src/nlsat/nlsat_simple_checker.cpp | 564 ++---------------- src/nlsat/nlsat_solver.cpp | 59 +- .../nlsat_variable_ordering_strategy.cpp | 2 +- src/tactic/smtlogics/qfnra_tactic.cpp | 86 ++- 5 files changed, 95 insertions(+), 621 deletions(-) diff --git a/src/nlsat/nlsat_params.pyg b/src/nlsat/nlsat_params.pyg index 00d179901..01229a527 100644 --- a/src/nlsat/nlsat_params.pyg +++ b/src/nlsat/nlsat_params.pyg @@ -3,8 +3,8 @@ def_module_params('nlsat', description='nonlinear solver', export=True, params=(max_memory_param(), - ('linxi_simple_check', BOOL, False, "linxi precheck about variables sign"), - ('linxi_variable_ordering_strategy', UINT, 0, "linxi Variable Ordering Strategy, 0 for none, 1 for BROWN, 2 for TRIANGULAR, 3 for ONLYPOLY"), + ('simple_check', BOOL, False, "precheck polynomials using variables sign"), + ('variable_ordering_strategy', UINT, 0, "Variable Ordering Strategy, 0 for none, 1 for BROWN, 2 for TRIANGULAR, 3 for ONLYPOLY"), ('cell_sample', BOOL, True, "cell sample projection"), ('lazy', UINT, 0, "how lazy the solver is."), ('reorder', BOOL, True, "reorder variables."), @@ -19,4 +19,3 @@ def_module_params('nlsat', ('seed', UINT, 0, "random seed."), ('factor', BOOL, True, "factor polynomials produced during conflict resolution.") )) - diff --git a/src/nlsat/nlsat_simple_checker.cpp b/src/nlsat/nlsat_simple_checker.cpp index f4bb5e648..3e1e8dd1c 100644 --- a/src/nlsat/nlsat_simple_checker.cpp +++ b/src/nlsat/nlsat_simple_checker.cpp @@ -4,33 +4,19 @@ struct Debug_Tracer { std::string tag_str; Debug_Tracer(std::string _tag_str) { tag_str = _tag_str; - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "Debug_Tracer begin\n"; tout << tag_str << "\n"; ); } ~Debug_Tracer() { - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "Debug_Tracer end\n"; tout << tag_str << "\n"; ); } }; -// #define _LINXI_DEBUG - -#ifdef _LINXI_DEBUG -// #define LINXI_DEBUG std::stringstream DEBUG_ss; DEBUG_ss << __FUNCTION__ << " " << __FILE__ << ":" << __LINE__; Debug_Tracer DEBUG_dt(DEBUG_ss.str()); -// #define LINXI_HERE TRACE("linxi_simple_checker", tout << "here\n";); -#define LINXI_DEBUG { }((void) 0 ); -#define LINXI_HERE { }((void) 0 ); - -#else -#define LINXI_DEBUG { }((void) 0 ); -#define LINXI_HERE { }((void) 0 ); -#endif - - namespace nlsat { struct Simple_Checker::imp { @@ -277,7 +263,6 @@ namespace nlsat { bool improved; enum special_ineq_kind {UNK = 0, AXBC, AXBSC, NK}; // None Kind vector> literal_special_kind; - // imp(solver &_sol, pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, clause_vector &_learned, const atom_vector &_atoms, const unsigned &_arith_var_num) : imp(pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, literal_vector &_learned_unit, const atom_vector &_atoms, const unsigned &_arith_var_num) : // sol(_sol), pm(_pm), @@ -304,7 +289,7 @@ namespace nlsat { return EQ; } bool update_interval_intersection(Domain_Interval &ia, const Domain_Interval &ib) { - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "ia: "; display(tout, am, ia); tout << "\nib: "; @@ -326,70 +311,8 @@ namespace nlsat { return false; - // if (ia.m_lower_inf == 0 && ib.m_upper_inf == 0) { - // if (ia.m_lower > ib.m_upper) - // return false; - // if (ia.m_lower == ib.m_upper && (ia.m_lower_open || ib.m_upper_open)) - // return false; - // } - // if (ib.m_lower_inf == 0 && ia.m_upper_inf == 0) { - // if (ib.m_lower > ia.m_upper) - // return false; - // if (ib.m_lower == ia.m_upper && (ib.m_lower_open || ia.m_upper_open)) - // return false; - // } - // if (ia.m_lower_inf && ib.m_lower_inf) { - // // do nothing - // } - // else { - // if (ia.m_lower_inf) { - // ia.m_lower_inf = 0; - // ia.m_lower_open = ib.m_lower_open; - // am.set(ia.m_lower, ib.m_lower); - // } - // else if (ib.m_lower_inf) { - // // do nothing - // } - // else { - // if (ia.m_lower == ib.m_lower) { - // ia.m_lower_open = (ia.m_lower_open | ib.m_lower_open); - // } - // else if (ia.m_lower < ib.m_lower) { - // ia.m_lower_open = ib.m_lower_open; - // am.set(ia.m_lower, ib.m_lower); - // } - // else { - // // do nothing - // } - // } - // } - // if (ia.m_upper_inf && ib.m_upper_inf) { - // // do nothing - // } - // else { - // if (ia.m_upper_inf) { - // ia.m_upper_inf = 0; - // ia.m_upper_open = ib.m_upper_open; - // am.set(ia.m_upper, ib.m_upper); - // } - // else if (ib.m_upper_inf) { - // // do nothing - // } - // else { - // if (ia.m_upper == ib.m_upper) { - // ia.m_upper_open = (ia.m_upper_open | ib.m_upper_open); - // } - // else if (ia.m_upper < ib.m_upper) { - // // do nothing - // } - // else { - // ia.m_upper_open = ib.m_upper_open; - // am.set(ia.m_upper, ib.m_upper); - // } - // } - // } - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "after update: "; display(tout, am, ia); tout << "\n"; @@ -401,7 +324,7 @@ namespace nlsat { return update_interval_intersection(vd.ori_val, di); } bool update_var_mag_domain_interval_by_ori(Var_Domain &vd, const Domain_Interval &di) { - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "vd mag val: "; display(tout, am, vd.mag_val); tout << "\n"; @@ -410,8 +333,7 @@ namespace nlsat { tout << "\n"; ); Domain_Interval mag_di(am, 0, 0, 1, 1); - // am.set(mag_di.m_lower.m_val, 0); - + if (di.m_lower.m_inf) { mag_di.m_upper.m_inf = 1; mag_di.m_upper.m_open = 1; @@ -477,7 +399,7 @@ namespace nlsat { } } } - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "mag di: "; display(tout, am, mag_di); tout << "\n"; @@ -485,7 +407,6 @@ namespace nlsat { return update_interval_intersection(vd.mag_val, mag_di); } void calc_formula(scoped_anum &num, const scoped_anum &a, unsigned b, const scoped_anum &c) { - LINXI_DEBUG; scoped_anum frac(am); am.div(c, a, frac); am.neg(frac); @@ -495,11 +416,10 @@ namespace nlsat { am.set(num, frac); } bool process_odd_degree_formula(Var_Domain &vd, sign_kind nsk, const scoped_anum &a, unsigned b, const scoped_anum &c) { - LINXI_DEBUG; Domain_Interval now_di(am); scoped_anum num(am); calc_formula(num, a, b, c); - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "nsk: "; display(tout, nsk); tout << '\n'; @@ -537,7 +457,7 @@ namespace nlsat { else { UNREACHABLE(); } - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "now_di: "; display(tout, am, now_di); tout << "\n"; @@ -548,29 +468,8 @@ namespace nlsat { return false; return true; } -/* -if (nsk == EQ) { -return false; -} -else if (nsk == LT) { -return false; -} -else if (nsk == GT) { -return true; -} -else if (nsk == LE) { -return false; -} -else if (nsk == GE) { -return true; -} -else { -UNREACHABLE(); -} -*/ - bool process_even_degree_formula(Var_Domain &vd, sign_kind nsk, const scoped_anum &a, unsigned b, const scoped_anum &c) { - LINXI_DEBUG; + bool process_even_degree_formula(Var_Domain &vd, sign_kind nsk, const scoped_anum &a, unsigned b, const scoped_anum &c) { scoped_anum num(am), frac(am); am.div(c, a, frac); am.neg(frac); @@ -623,8 +522,6 @@ UNREACHABLE(); // di.m_upper_inf = 0; // am.set(di.m_lower, num); // am.set(di.m_upper, num); - // if (!update_interval_intersection(vd.ori_val, di)) - // return false; if (!update_interval_intersection(vd.mag_val, di)) return false; } @@ -692,7 +589,6 @@ UNREACHABLE(); } bool update_var_domain(sign_kind nsk, const scoped_anum &a, var x, unsigned b, const scoped_anum &c) { - LINXI_DEBUG; Var_Domain &vd = vars_domain[x]; if (am.is_neg(a)) { if (nsk == LT) @@ -722,22 +618,12 @@ UNREACHABLE(); bool check_is_axbc(const poly *p, scoped_anum &a, var &x, unsigned &b, scoped_anum& c) { // is a*(x^b) + c*1 form - // LINXI_DEBUG; - // LINXI_HERE; - // TRACE("linxi_simple_checker", - // tout << a << "x[" << x << "]^" << b << " "; - // tout << "+ " << c << " "; - // // display(tout, nsk); - // // tout << " 0\n"; - // ); if (pm.size(p) == 1 && pm.is_var(pm.get_monomial(p, 0), x)) { - LINXI_HERE; am.set(a, 1); b = 1; am.set(c, 0); return true; } - // LINXI_HERE; if (pm.size(p) != 2) return false; if (!pm.is_unit(pm.get_monomial(p, 1))) @@ -747,7 +633,7 @@ UNREACHABLE(); return false; x = pm.get_var(m, 0); b = pm.degree(m, 0); - // LINXI_HERE; + am.set(a, pm.coeff(p, 0)); am.set(c, pm.coeff(p, 1)); return true; @@ -755,7 +641,6 @@ UNREACHABLE(); bool collect_domain_axbc_form(unsigned cid, unsigned lid) { // is_var_num, a*(x^b) + c form - LINXI_DEBUG; literal lit = (*clauses[cid])[lid]; bool s = lit.sign(); ineq_atom *ia = to_ineq_atom(atoms[lit.var()]); @@ -786,14 +671,14 @@ UNREACHABLE(); else if (nsk == GT) nsk = LE; } - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << a << "x[" << x << "]^" << b << " + " << c << " "; display(tout, nsk); tout << " 0 \n"; ); if (!update_var_domain(nsk, a, x, b, c)) return false; - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "original: "; display(tout, am, vars_domain[x].ori_val); tout << "\nmagnitude: "; @@ -804,7 +689,6 @@ UNREACHABLE(); } bool check_is_axbsc(const poly *p, vector &as, vector &xs, vector &bs, scoped_anum& c, unsigned &cnt) { // [a*(x^b)] + ... + [a*(x^b)] + c form - LINXI_DEBUG; unsigned psz = pm.size(p); am.set(c, 0); for (unsigned i = 0; i < psz; ++i) { @@ -812,23 +696,9 @@ UNREACHABLE(); if (pm.size(m) > 1) return false; } - LINXI_HERE; cnt = 0; for (unsigned i = 0; i < psz; ++i) { monomial *m = pm.get_monomial(p, i); - // TRACE("linxi_simple_checker", - // tout << "monomial: "; - // pm.display(tout, m); - // tout << '\n'; - // // tout << "coefficient: " << pm.coeff(p, i) << "\n"; - // tout << "m size: " << pm.size(m) << '\n'; - // tout << "# "; - // for (unsigned j = 0, sz = pm.size(m); j < sz; ++j) { - // var v = pm.get_var(m, j); - // tout << " (" << j << ", " << pm.degree_of(m, v) << ")"; - // } - // tout << "\n"; - // ); if (pm.size(m) == 0) { am.set(c, pm.coeff(p, i)); } @@ -837,9 +707,6 @@ UNREACHABLE(); am.set(as[cnt++], pm.coeff(p, i)); xs.push_back(pm.get_var(m, 0)); bs.push_back(pm.degree(m, 0)); - // TRACE("linxi_simple_checker", - // tout << as.back() << "x[" << xs.back() << "]^" << bs.back() << "\n"; - // ); } } return true; @@ -875,9 +742,6 @@ UNREACHABLE(); else if (am.is_pos(vd.ori_val.m_lower.m_val)) { ret = GT; } - // else { - // ret = NONE; - // } if (am.is_zero(vd.ori_val.m_upper.m_val)) { if (vd.ori_val.m_upper.m_open) ret = LT; @@ -886,10 +750,7 @@ UNREACHABLE(); } else if (am.is_neg(vd.ori_val.m_upper.m_val)) { ret = LT; - } - // else { - // ret = NONE; - // } + } } else if (!vd.ori_val.m_lower.m_inf) { if (am.is_pos(vd.ori_val.m_lower.m_val)) { @@ -934,7 +795,7 @@ UNREACHABLE(); unsigned sz = as.size(); for (unsigned i = 1; i < sz; ++i) { sign_kind now = get_axb_sign(as[i], xs[i], bs[i]); - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "sta: "; display(tout, sta); tout << "\n"; @@ -959,43 +820,14 @@ UNREACHABLE(); if (sta != now) sta = GT; } - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "after merge\n"; tout << "sta: "; display(tout, sta); tout << "\n"; ); } - // if (am.is_zero(c)) { - // // sta = sta; - // } - // else if (am.is_neg(c)) { - // if (sta == EQ) - // sta = LT; - // // else if (sta == LT) - // // sta = LT; - // else if (sta == LE) - // sta = LT; - // else if (sta == GT) - // sta = NONE; - // else if (sta == GE) - // sta = NONE; - // } - // else { // a > 0 - // if (sta == EQ) - // sta = GT; - // else if (sta == LT) - // sta = NONE; - // else if (sta == LE) - // sta = NONE; - // // else if (sta == GT) - // // sta = GT; - // else if (sta == GE) - // sta = GT; - // } - // if (sta == NONE) - // return false; - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "sta: "; display(tout, sta); tout << "\n"; @@ -1016,7 +848,6 @@ else if (am.is_zero(c)) { // ( == 0) + (c == 0) -> == 0 else { // ( == 0) + (c > 0) -> > 0 } - */ if (sta == EQ) { if (am.is_neg(c)) { // ( == 0) + (c < 0) -> < 0 @@ -1158,7 +989,6 @@ else { // ( == 0) + (c > 0) -> > 0 return false; } bool collect_domain_sign_ineq_consistent_form(sign_kind nsk, vector &as, vector &xs, vector &bs, scoped_anum& c) { - LINXI_DEBUG; for (unsigned i = 0, sz = as.size(); i < sz; ++i) { if (!update_var_domain(nsk, as[i], xs[i], bs[i], c)) return false; @@ -1166,9 +996,8 @@ else { // ( == 0) + (c > 0) -> > 0 return true; } bool process_axbsc_form(sign_kind nsk, unsigned cid, vector &as, vector &xs, vector &bs, scoped_anum& c) { - LINXI_DEBUG; bool is_conflict(false); - TRACE("linxi_simple_checker", + TRACE("simple_checker", for (unsigned i = 0, sz = as.size(); i < sz; ++i) { if (i > 0) tout << "+ "; @@ -1180,7 +1009,7 @@ else { // ( == 0) + (c > 0) -> > 0 ); if (!check_is_sign_ineq_consistent(nsk, as, xs, bs, c, is_conflict)) return true; - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "is conflict: " << is_conflict << "\n" ); if (is_conflict) @@ -1191,7 +1020,6 @@ else { // ( == 0) + (c > 0) -> > 0 return true; } bool collect_domain_axbsc_form(unsigned cid, unsigned lid) { - LINXI_DEBUG; // [a*(x^k)] + ... + [a*(x^b)] + k form literal lit = (*clauses[cid])[lid]; bool s = lit.sign(); @@ -1216,7 +1044,7 @@ else { // ( == 0) + (c > 0) -> > 0 return true; } literal_special_kind[cid][lid] = AXBSC; - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "as size: " << as.size() << '\n'; ); while (as.size() > cnt) @@ -1231,7 +1059,7 @@ else { // ( == 0) + (c > 0) -> > 0 else if (nsk == GT) nsk = LE; } - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "ineq atom: " << '\n'; for (unsigned i = 0, sz = iat->size(); i < sz; ++i) { pm.display(tout, iat->p(i)); @@ -1254,16 +1082,8 @@ else { // ( == 0) + (c > 0) -> > 0 return false; return true; } - // bool update_all_mag_domain_by_ori() { - // LINXI_HERE; - // for (unsigned i = 0; i < arith_var_num; ++i) { - // if (!update_var_mag_domain_interval_by_ori(vars_domain[i], vars_domain[i].ori_val)) - // return false; - // } - // return true; - // } + bool collect_var_domain() { - LINXI_DEBUG; // vector vec_id; for (unsigned i = 0, sz = clauses.size(); i < sz; ++i) { if (clauses_visited[i].visited) @@ -1286,9 +1106,7 @@ else { // ( == 0) + (c > 0) -> > 0 if (!collect_domain_axbc_form(i, 0)) return false; } - // if (!update_all_mag_domain_by_ori()) - // return false; - TRACE("linxi_simple_checker", + TRACE("simple_checker", for (unsigned i = 0; i < arith_var_num; ++i) { tout << "====== arith[" << i << "] ======\n"; tout << "original value: "; @@ -1299,16 +1117,11 @@ else { // ( == 0) + (c > 0) -> > 0 tout << "====== arith[" << i << "] ======\n"; } ); - // TRACE("linxi_simple_checker", - // tout << "vec_id.size(): " << vec_id.size() << "\n"; - // ); for (unsigned i = 0, sz = clauses.size(); i < sz; ++i) { // unsigned id = vec_id[i]; if (!collect_domain_axbsc_form(i, 0)) return false; } - // if (!update_all_mag_domain_by_ori()) - // return false; return true; } void endpoint_multiply(const Endpoint &a, const Endpoint &b, Endpoint &c) { @@ -1341,7 +1154,7 @@ else { // ( == 0) + (c > 0) -> > 0 } } void merge_mul_domain(Domain_Interval &pre, const Domain_Interval &now) { - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "dom: "; display(tout, am, pre); tout << "\n"; @@ -1365,241 +1178,10 @@ else { // ( == 0) + (c > 0) -> > 0 pre.m_lower.m_is_lower = 1; pre.m_upper.copy(*pmx); pre.m_upper.m_is_lower = 0; - - // if (pre.m_lower_inf && pre.m_upper_inf) { - // if ((!now.m_lower_inf && am.is_zero(now.m_lower)) && - // (!now.m_upper_inf && am.is_zero(now.m_upper))) { - - // } - // else { - // return ; - // } - // } - // if ((!pre.m_lower_inf && am.is_zero(pre.m_lower)) && - // (!pre.m_upper_inf && am.is_zero(pre.m_upper))) - // return ; - // if (now.m_lower_inf && now.m_upper_inf) { - // pre.m_lower_inf = 1; - // pre.m_upper_inf = 1; - // return ; - // } - // if (pre.m_lower_inf == 0 && !am.is_neg(pre.m_lower)) { - // // {+, +/inf} - // if (now.m_lower_inf == 0 && !am.is_neg(now.m_lower)) { - // // {+, +/inf} * {+, +/inf} - // // {a, b} * {c, d} -> {ac, bd/inf} - // pre.m_lower_open = (pre.m_lower_open | now.m_lower_open); - // am.set(pre.m_lower, now.m_lower * pre.m_lower); - - // pre.m_upper_inf = (pre.m_upper_inf | now.m_upper_inf); - // if (pre.m_upper_inf == 0) { - // pre.m_upper_open = (pre.m_upper_open | now.m_upper_open); - // am.set(pre.m_upper, now.m_upper * pre.m_upper); - // } - // } - // else if (now.m_upper_inf == 0 && !am.is_pos(now.m_upper)) { - // // {+, +/inf} * {-/inf, -} - // // {a, b} * {c, d} -> {bc, ad} - // Domain_Interval tmp_di(am, false); - // tmp_di.m_lower_inf = (pre.m_upper_inf | now.m_lower_inf); - // if (tmp_di.m_lower_inf == 0) { - // tmp_di.m_lower_open = (pre.m_upper_open | now.m_lower_open); - // am.set(tmp_di.m_lower, pre.m_upper * now.m_lower); - // } - - // tmp_di.m_upper_inf = 0; - // tmp_di.m_upper_open = (pre.m_lower_open | now.m_upper_open); - // am.set(tmp_di.m_upper, pre.m_lower * now.m_upper); - - // pre.copy(tmp_di); - // } - // else { - // // {+, +/inf} * {-/inf, +/inf} - // if (pre.m_upper_inf) { - // // {+, +inf) * {-/inf, +/inf} -> (-inf, +inf) - // pre.m_lower_inf = 1; - // } - // else { - // // {+, +} * {-/inf, +/inf} - // // {a, b} * {c, d} -> {bc, bd} - // // order matters! - // pre.m_lower_inf = now.m_lower_inf; - // if (pre.m_lower_inf == 0) { - // pre.m_lower_open = (pre.m_upper_open | now.m_lower_open); - // am.set(pre.m_lower, now.m_lower * pre.m_upper); - // } - // pre.m_upper_inf = now.m_upper_inf; - // if (pre.m_upper_inf == 0) { - // pre.m_upper_open = (pre.m_upper_open | now.m_upper_open); - // am.set(pre.m_upper, now.m_upper * pre.m_upper); - // } - // } - // } - // } - // else if (pre.m_upper_inf == 0 && !am.is_pos(pre.m_upper)) { - // LINXI_HERE; - // // {-/inf, -} - // if (now.m_upper_inf == 0 && !am.is_pos(now.m_upper)) { - // LINXI_HERE; - // // {-/inf, -} * {-/inf, -} - // if (pre.m_lower_inf || now.m_lower_inf) { - // // (-inf, b} * {c, d} -> {bd, +inf) - // // {a, b} * (-inf, d} -> {bd, +inf) - // pre.m_upper_inf = 1; - - // pre.m_lower_open = (pre.m_upper_open | now.m_upper_open); - // am.set(pre.m_lower, now.m_upper * pre.m_upper); - // } - // else { - // // {a, b} * {c, d} -> {bd, ac} - // Domain_Interval tmp_di(am, false); - // tmp_di.m_lower_inf = 0; - // tmp_di.m_upper_inf = 0; - // tmp_di.m_lower_open = (pre.m_upper_open | now.m_upper_open); - // tmp_di.m_upper_open = (pre.m_lower_open | now.m_lower_open); - // am.set(tmp_di.m_lower, pre.m_upper * now.m_upper); - // am.set(tmp_di.m_upper, pre.m_lower * now.m_lower); - // pre.copy(tmp_di); - // } - // } - // else if (now.m_lower_inf == 0 && !am.is_neg(now.m_lower)) { - // LINXI_HERE; - // // {-/inf, -} * {+, +/inf} - // // {a, b} * {c, d} -> {ad, bc} - // Domain_Interval tmp_di(am, false); - // tmp_di.m_lower_inf = (pre.m_lower_inf | now.m_upper_inf); - // if (tmp_di.m_lower_inf == 0) { - // tmp_di.m_lower_open = (pre.m_lower_open | now.m_upper_open); - // am.set(tmp_di.m_lower, pre.m_lower * now.m_upper); - // } - - // tmp_di.m_upper_inf = 0; - // tmp_di.m_upper_open = (pre.m_upper_open | now.m_lower_open); - // am.set(tmp_di.m_upper, pre.m_upper * now.m_lower); - // TRACE("linxi_simple_checker", - // tout << "tmp_di: "; - // display(tout, am, tmp_di); - // tout << "\n"; - // ); - // pre.copy(tmp_di); - // } - // else { - // LINXI_HERE; - // // {-/inf, -} * {-/inf, +/inf} - // if (pre.m_lower_inf) { - // // (-inf, -} * {-/inf, +/inf} -> (-inf, +inf) - // pre.m_upper_inf = 1; - // } - // else { - // // {-, -} * {-/inf, +/inf} - // // {pl, pu} * {nl, nu} -> {pl nu, pl nl} - // // order matters! - // pre.m_lower_inf = now.m_upper_inf; - // if (pre.m_lower_inf == 0) { - // pre.m_lower_open = (pre.m_lower_open | now.m_upper_open); - // am.set(pre.m_lower, now.m_upper * pre.m_lower); - // } - // pre.m_upper_inf = now.m_lower_inf; - // if (pre.m_upper_inf == 0) { - // pre.m_upper_open = (pre.m_lower_open | now.m_lower_open); - // am.set(pre.m_upper, now.m_lower * pre.m_lower); - // } - // } - // } - // } - // else { - // // {-/inf, +/inf} - // if (now.m_lower_inf == 0 && !am.is_neg(now.m_lower)) { - // // {-/inf, +/inf} * {+, +/inf} - // if (now.m_upper_inf) { - // // {-/inf, +/inf} * {+, +inf) -> (-inf, +inf) - // pre.m_lower_inf = 1; - // pre.m_upper_inf = 1; - // } - // else { - // // {a, b} * {c, d} -> {ad, bd} - // // {-/inf, +/inf} * {+, +} - // if (pre.m_lower_inf == 0) { - // pre.m_lower_open = (now.m_upper_open | pre.m_lower_open); - // am.set(pre.m_lower, now.m_upper * pre.m_lower); - // } - // if (pre.m_upper_inf == 0) { - // pre.m_upper_open = (now.m_upper_open | pre.m_upper_open); - // am.set(pre.m_upper, now.m_upper * pre.m_upper); - // } - // } - // } - // else if (now.m_upper_inf == 0 && !am.is_pos(now.m_upper)) { - // // {-/inf, +/inf} * {-/inf, -} - // if (now.m_lower_inf) { - // // {-/inf, +/inf} * (-inf, -} -> (-inf, +inf) - // pre.m_lower_inf = 1; - // pre.m_upper_inf = 1; - // } - // else { - // // {-/inf, +/inf} * {-, -} - // // {pl, pu} * {nl, nu} -> {pu nl, pl nl} - // // order matters! - // if (pre.m_lower_inf == 0) { - // pre.m_lower_open = (pre.m_upper_open | now.m_lower_open); - // am.set(pre.m_lower, now.m_lower * pre.m_upper); - // } - // if (pre.m_upper_inf == 0) { - // pre.m_upper_open = (pre.m_lower_open | now.m_lower_open); - // am.set(pre.m_upper, now.m_lower * pre.m_lower); - // } - // } - // } - // else { - // // {-/inf, +/inf} * {-/inf, +/inf} - // if (pre.m_lower_inf || pre.m_upper_inf || - // now.m_lower_inf || now.m_upper_inf) { - // pre.m_lower_inf = 1; - // pre.m_upper_inf = 1; - // } - // else { - // // {-, +} * {-, +} - // scoped_anum plnl(am), punu(am); - // unsigned plo, puo; - // am.set(plnl, pre.m_lower * now.m_lower); - // am.set(punu, pre.m_upper * now.m_upper); - // scoped_anum plnu(am), punl(am); - // am.set(plnu, pre.m_lower * now.m_upper); - // am.set(punl, pre.m_upper * now.m_lower); - // if (plnl > punu) { - // puo = (pre.m_lower_open | now.m_lower_open); - // am.set(pre.m_upper, plnl); - // } - // else if (plnl == punu) { - // puo = ((pre.m_lower_open | now.m_lower_open) & - // (pre.m_upper_open | now.m_upper_open)); - // am.set(pre.m_upper, plnl); - // } - // else { - // puo = (pre.m_upper_open | now.m_upper_open); - // am.set(pre.m_upper, punu); - // } - // if (plnu < punl) { - // plo = (pre.m_lower_open | now.m_upper_open); - // am.set(pre.m_lower, plnu); - // } - // else if (plnu == punl) { - // plo = ((pre.m_lower_open | now.m_upper_open) & - // (pre.m_upper_open | now.m_lower_open)); - // am.set(pre.m_lower, plnu); - // } - // else { - // plo = (pre.m_upper_open | now.m_lower_open); - // am.set(pre.m_lower, punl); - // } - // } - // } - // } } void get_monomial_domain(monomial *m, const scoped_anum &a, Domain_Interval &dom) { - LINXI_DEBUG; - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "monomial: "; pm.display(tout, m); tout << '\n'; @@ -1618,7 +1200,7 @@ else { // ( == 0) + (c > 0) -> > 0 var v = pm.get_var(m, i); unsigned deg = pm.degree_of(m, v); const Domain_Interval &di = ((deg & 1) == 0 ? vars_domain[v].mag_val : vars_domain[v].ori_val); - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "dom: "; display(tout, am, dom); tout << "\n"; @@ -1630,7 +1212,7 @@ else { // ( == 0) + (c > 0) -> > 0 for (unsigned j = 0; j < deg; ++j) { merge_mul_domain(dom, di); } - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "after merge mul: "; display(tout, am, dom); tout << "\n"; @@ -1647,32 +1229,23 @@ else { // ( == 0) + (c > 0) -> > 0 a.m_open = (a.m_open | b.m_open); } } + void merge_add_domain(Domain_Interval &pre, const Domain_Interval &now) { endpoint_add(pre.m_lower, now.m_lower); endpoint_add(pre.m_upper, now.m_upper); - // pre.m_lower_inf = (pre.m_lower_inf | now.m_lower_inf); - // if (pre.m_lower_inf == 0) { - // am.set(pre.m_lower, pre.m_lower + now.m_lower); - // pre.m_lower_open = (pre.m_lower_open | now.m_lower_open); - // } - // pre.m_upper_inf = (pre.m_upper_inf | now.m_upper_inf); - // if (pre.m_upper_inf == 0) { - // am.set(pre.m_upper, pre.m_upper + now.m_upper); - // pre.m_upper_open = (pre.m_upper_open | now.m_upper_open); - // } } + sign_kind get_poly_sign(const poly *p) { - LINXI_DEBUG; scoped_anum a(am); am.set(a, pm.coeff(p, 0)); Domain_Interval pre(am); get_monomial_domain(pm.get_monomial(p, 0), a, pre); - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "poly: "; pm.display(tout, p); tout << "\n"; ); - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "pre: "; display(tout, am, pre); tout << "\n"; @@ -1681,7 +1254,7 @@ else { // ( == 0) + (c > 0) -> > 0 am.set(a, pm.coeff(p, i)); Domain_Interval now(am); get_monomial_domain(pm.get_monomial(p, i), a, now); - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "pre: "; display(tout, am, pre); tout << "\n"; @@ -1692,7 +1265,7 @@ else { // ( == 0) + (c > 0) -> > 0 if (now.m_lower.m_inf && now.m_upper.m_inf) return NONE; merge_add_domain(pre, now); - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "after merge: "; display(tout, am, pre); tout << "\n"; @@ -1700,8 +1273,6 @@ else { // ( == 0) + (c > 0) -> > 0 if (pre.m_lower.m_inf && pre.m_upper.m_inf) return NONE; } - // if (pre.m_lower_inf && pre.m_upper_inf) - // return NONE; if (pre.m_lower.m_inf) { if (am.is_neg(pre.m_upper.m_val)) { // (-inf, -} @@ -1767,7 +1338,6 @@ else { // ( == 0) + (c > 0) -> > 0 } sign_kind get_poly_sign_degree(const poly *p, bool is_even) { - LINXI_DEBUG; sign_kind ret = get_poly_sign(p); if (is_even) { if (ret == GE || ret == LE || ret == NONE) @@ -1775,7 +1345,7 @@ else { // ( == 0) + (c > 0) -> > 0 else if (ret != EQ) ret = GT; } - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "ret sign: "; display(tout, ret); tout << "\n"; @@ -1841,8 +1411,7 @@ else { // ( == 0) + (c > 0) -> > 0 } } bool check_ineq_atom_satisfiable(const ineq_atom *iat, bool s) { - LINXI_DEBUG; - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "s: " << s << "\n"; tout << "kd: " << iat->get_kind() << "\n"; ); @@ -1855,7 +1424,7 @@ else { // ( == 0) + (c > 0) -> > 0 else nsk = GE; } - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "ineq atom: " << '\n'; for (unsigned i = 0, sz = iat->size(); i < sz; ++i) { pm.display(tout, iat->p(i)); @@ -1870,25 +1439,14 @@ else { // ( == 0) + (c > 0) -> > 0 for (unsigned i = 1, sz = iat->size(); i < sz; ++i) { sign_kind now = get_poly_sign_degree(iat->p(i), iat->is_even(i)); - // TRACE("linxi_simple_checker", - // tout << "pre: "; - // display(tout, pre); - // tout << ", now: "; - // display(tout, now); - // tout << "\n"; - // ); merge_mul_sign(pre, now); - // TRACE("linxi_simple_checker", - // tout << "==> "; - // display(tout, pre); - // ); if (pre == NONE) return true; if ((nsk == EQ || nsk == GE || nsk == LE) && (pre == EQ || pre == GE || pre == LE)) return true; } - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "pre: "; display(tout, pre); tout << ", nsk: "; @@ -1910,7 +1468,6 @@ else { // ( == 0) + (c > 0) -> > 0 return true; } bool check_literal_satisfiable(unsigned cid, unsigned lit_id) { - LINXI_DEBUG; literal lit = (*clauses[cid])[lit_id]; const var &v = lit.var(); atom *at = atoms[v]; @@ -1922,16 +1479,15 @@ else { // ( == 0) + (c > 0) -> > 0 clauses_visited[cid].visited = true; return true; } - // TRACE("linxi_sign", + // TRACE("sign", // tout << "literal: " << lit << '\n'; // ); bool s = lit.sign(); return check_ineq_atom_satisfiable(to_ineq_atom(at), s); } bool check_clause_satisfiable(unsigned cid) { - LINXI_DEBUG; const clause *cla = clauses[cid]; - TRACE("linxi_simple_checker", + TRACE("simple_checker", tout << "clause size: " << cla->size() << '\n'; ); unsigned sz = cla->size(); @@ -1954,15 +1510,8 @@ else { // ( == 0) + (c > 0) -> > 0 clauses_visited[cid].literal_visited[i] = true; literal lit = (*clauses[cid])[i]; lit.neg(); - // if (atoms[lit.var()] != nullptr && atoms[lit.var()]->is_ineq_atom()) { - // ineq_atom *iat = to_ineq_atom(atoms[lit.var()]); - // if (to_sign_kind(iat->get_kind()) == EQ && lit.sign()) { - // continue; - // } - // } learned_unit.push_back(lit); - // sol.mk_clause(1, &lit); - TRACE("linxi_simple_checker_learned", + TRACE("simple_checker_learned", tout << "making new clauses!\n"; tout << "sign: " << lit.sign() << '\n'; if (atoms[lit.var()] != nullptr && atoms[lit.var()]->is_ineq_atom()) { @@ -1989,7 +1538,6 @@ else { // ( == 0) + (c > 0) -> > 0 return false; } bool check() { - LINXI_DEBUG; for (unsigned i = 0, sz = clauses.size(); i < sz; ++i) { if (clauses_visited[i].visited) continue; @@ -1999,14 +1547,6 @@ else { // ( == 0) + (c > 0) -> > 0 } return true; } - void test_anum() { - scoped_anum x(am), y(am); - am.set(x, 3); - am.set(y, 5); - TRACE("linxi_simple_checker", - tout << x << " " << y << std::endl; - ); - } bool operator()() { improved = true; @@ -2014,7 +1554,7 @@ else { // ( == 0) + (c > 0) -> > 0 improved = false; if (!check()) return false; - TRACE("linxi_simple_checker", + TRACE("simple_checker", for (unsigned i = 0; i < arith_var_num; ++i) { tout << "====== arith[" << i << "] ======\n"; tout << "original value: "; @@ -2026,38 +1566,16 @@ else { // ( == 0) + (c > 0) -> > 0 } ); } - // LINXI_DEBUG; - // // test_anum(); - // if (!collect_var_domain()) - // return false; - // TRACE("linxi_simple_checker", - // for (unsigned i = 0; i < arith_var_num; ++i) { - // tout << "====== arith[" << i << "] ======\n"; - // tout << "original value: "; - // display(tout, am, vars_domain[i].ori_val); - // tout << "\nmagitude value: "; - // display(tout, am, vars_domain[i].mag_val); - // tout << "\n"; - // tout << "====== arith[" << i << "] ======\n"; - // } - // ); - // if (!check()) - // return false; return true; } }; - // Simple_Checker::Simple_Checker(solver &_sol, pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, clause_vector &_learned, const atom_vector &_atoms, const unsigned &_arith_var_num) { Simple_Checker::Simple_Checker(pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, literal_vector &_learned_unit, const atom_vector &_atoms, const unsigned &_arith_var_num) { - LINXI_DEBUG; - // m_imp = alloc(imp, _sol, _pm, _am, _clauses, _learned, _atoms, _arith_var_num); m_imp = alloc(imp, _pm, _am, _clauses, _learned_unit, _atoms, _arith_var_num); } Simple_Checker::~Simple_Checker() { - LINXI_DEBUG; dealloc(m_imp); } bool Simple_Checker::operator()() { - LINXI_DEBUG; return m_imp->operator()(); } } diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index 30ca55e31..1c4aabe50 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -222,12 +222,10 @@ namespace nlsat { bool m_check_lemmas; unsigned m_max_conflicts; unsigned m_lemma_count; -//#linxi begin - bool m_linxi_simple_check; - unsigned m_linxi_variable_ordering_strategy; - bool m_linxi_set_0_more; + bool m_simple_check; + unsigned m_variable_ordering_strategy; + bool m_set_0_more; bool m_cell_sample; -//#linxi end struct stats { unsigned m_simplifications; @@ -297,10 +295,7 @@ namespace nlsat { m_inline_vars = p.inline_vars(); m_log_lemmas = p.log_lemmas(); m_check_lemmas = p.check_lemmas(); -//#linxi begin - m_linxi_simple_check = p.linxi_simple_check(); - m_linxi_variable_ordering_strategy = p.linxi_variable_ordering_strategy(); -//#linxi end + m_variable_ordering_strategy = p.variable_ordering_strategy(); m_cell_sample = p.cell_sample(); @@ -1784,24 +1779,11 @@ namespace nlsat { } bool m_reordered = false; -//#linxi begin Simple Check -// test - void test_anum() { - scoped_anum x(m_am), y(m_am); - m_am.set(x, 3); - m_am.set(y, 5); - TRACE("linxi_simple_checker", - tout << x << " " << y << std::endl; - ); - } bool simple_check() { // test_anum(); literal_vector learned_unit; // Simple_Checker checker(m_solver, m_pm, m_am, m_clauses, m_learned, m_atoms, m_is_int.size()); Simple_Checker checker(m_pm, m_am, m_clauses, learned_unit, m_atoms, m_is_int.size()); - // TRACE("linxi_simple_checker", - // tout << "here" << std::endl; - // ); if (!checker()) return false; for (unsigned i = 0, sz = learned_unit.size(); i < sz; ++i) { @@ -1809,31 +1791,24 @@ namespace nlsat { if (m_atoms[learned_unit[i].var()] == nullptr) { assign(learned_unit[i], mk_clause_jst(cla)); } - // decide(learned_unit[i]); } return true; } -//#linxi end Simple Check -//#linxi begin Variable Ordering Strategy void run_variable_ordering_strategy() { - TRACE("linxi_reorder", tout << "runing vos: " << m_linxi_variable_ordering_strategy << '\n';); + TRACE("reorder", tout << "runing vos: " << m_variable_ordering_strategy << '\n';); unsigned num = num_vars(); - VOS_Var_Info_Collector vos_collector(m_pm, m_atoms, num, m_linxi_variable_ordering_strategy); + VOS_Var_Info_Collector vos_collector(m_pm, m_atoms, num, m_variable_ordering_strategy); vos_collector.collect(m_clauses); vos_collector.collect(m_learned); - // TRACE("linxi_reorder", vos_collector.display(tout, m_display_var);); var_vector perm; vos_collector(perm); reorder(perm.size(), perm.data()); } -//#linxi end Variable Ordering Strategy - - void apply_reorder() { m_reordered = false; if (!can_reorder()) @@ -1850,21 +1825,15 @@ namespace nlsat { lbool check() { -//#linxi begin simple check - if (m_linxi_simple_check) { + if (m_simple_check) { if (!simple_check()) { - TRACE("linxi_simple_check", tout << "real unsat\n";); + TRACE("simple_check", tout << "real unsat\n";); return l_false; } - TRACE("linxi_simple_checker_learned", + TRACE("simple_checker_learned", tout << "simple check done\n"; ); - // exit(0); - // return l_undef; } - // exit(0); - // return l_false; -//#linxi end simple check TRACE("nlsat_smt2", display_smt2(tout);); TRACE("nlsat_fd", tout << "is_full_dimensional: " << is_full_dimensional() << "\n";); @@ -1876,12 +1845,10 @@ namespace nlsat { if (!can_reorder()) { } -//#linxi begin Variable Ordering Strategy - else if (m_linxi_variable_ordering_strategy > 0) { + else if (m_variable_ordering_strategy > 0) { run_variable_ordering_strategy(); reordered = true; } -//#linxi end Variable Ordering Strategy else if (m_random_order) { shuffle_vars(); reordered = true; @@ -2866,7 +2833,6 @@ namespace nlsat { TRACE("nlsat_reorder_clauses", tout << "after:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); } -//#linxi begin struct degree_lit_num_lt { unsigned_vector & m_degrees; @@ -2909,20 +2875,17 @@ namespace nlsat { TRACE("nlsat_reorder_clauses", tout << "after:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); } -//#linxi end void sort_watched_clauses() { unsigned num = num_vars(); for (unsigned i = 0; i < num; i++) { clause_vector & ws = m_watches[i]; -//#linxi begin // sort_clauses_by_degree(ws.size(), ws.data()); - if (m_linxi_simple_check) { + if (m_simple_check) { sort_clauses_by_degree_lit_num(ws.size(), ws.data()); } else { sort_clauses_by_degree(ws.size(), ws.data()); } -//#linxi end } } diff --git a/src/nlsat/nlsat_variable_ordering_strategy.cpp b/src/nlsat/nlsat_variable_ordering_strategy.cpp index 8c4723fd3..dfcc14201 100644 --- a/src/nlsat/nlsat_variable_ordering_strategy.cpp +++ b/src/nlsat/nlsat_variable_ordering_strategy.cpp @@ -239,7 +239,7 @@ namespace nlsat { else { UNREACHABLE(); } - TRACE("linxi_reorder", + TRACE("reorder", tout << "new order: "; for (unsigned i = 0; i < num_vars; i++) tout << new_order[i] << " "; diff --git a/src/tactic/smtlogics/qfnra_tactic.cpp b/src/tactic/smtlogics/qfnra_tactic.cpp index 5ecfa2426..f95ae8a8c 100644 --- a/src/tactic/smtlogics/qfnra_tactic.cpp +++ b/src/tactic/smtlogics/qfnra_tactic.cpp @@ -41,11 +41,11 @@ tactic * mk_multilinear_ls_tactic(ast_manager & m, params_ref const & p, unsigne return using_params(mk_smt_tactic(m), p_mls); } -tactic * linxi_mk_qfnra_very_small_solver(ast_manager& m, params_ref const& p) { +tactic * mk_qfnra_very_small_solver(ast_manager& m, params_ref const& p) { ptr_vector ts; { params_ref p_sc = p; - p_sc.set_bool("linxi_simple_check", true); + p_sc.set_bool("simple_check", true); // p_sc.set_uint("seed", 997); ts.push_back(try_for(and_then(mk_qfnra_nlsat_tactic(m, p_sc), mk_fail_if_undecided_tactic()), 10 * 1000)); } @@ -55,24 +55,24 @@ tactic * linxi_mk_qfnra_very_small_solver(ast_manager& m, params_ref const& p) { ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_heuristic), 4 * 1000)); params_ref p_order_4 = p; - p_order_4.set_uint("linxi_variable_ordering_strategy", 4); + p_order_4.set_uint("variable_ordering_strategy", 4); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_4), 4 * 1000)); params_ref p_order_3 = p; - p_order_3.set_uint("linxi_variable_ordering_strategy", 3); + p_order_3.set_uint("variable_ordering_strategy", 3); // p_order_3.set_uint("seed", 17); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_3), 6 * 1000)); params_ref p_order_1 = p; - p_order_1.set_uint("linxi_variable_ordering_strategy", 1); + p_order_1.set_uint("variable_ordering_strategy", 1); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_1), 8 * 1000)); params_ref p_order_5 = p; - p_order_5.set_uint("linxi_variable_ordering_strategy", 5); + p_order_5.set_uint("variable_ordering_strategy", 5); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_5), 8 * 1000)); params_ref p_order_2 = p; - p_order_2.set_uint("linxi_variable_ordering_strategy", 2); + p_order_2.set_uint("variable_ordering_strategy", 2); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_2), 10 * 1000)); } { @@ -97,11 +97,11 @@ tactic * linxi_mk_qfnra_very_small_solver(ast_manager& m, params_ref const& p) { return or_else(ts.size(), ts.data()); } -tactic * linxi_mk_qfnra_small_solver(ast_manager& m, params_ref const& p) { +tactic * mk_qfnra_small_solver(ast_manager& m, params_ref const& p) { ptr_vector ts; { params_ref p_sc = p; - p_sc.set_bool("linxi_simple_check", true); + p_sc.set_bool("simple_check", true); // p_sc.set_uint("seed", 997); ts.push_back(try_for(and_then(mk_qfnra_nlsat_tactic(m, p_sc), mk_fail_if_undecided_tactic()), 20 * 1000)); } @@ -111,26 +111,26 @@ tactic * linxi_mk_qfnra_small_solver(ast_manager& m, params_ref const& p) { ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_heuristic), 5 * 1000)); params_ref p_order_4 = p; - p_order_4.set_uint("linxi_variable_ordering_strategy", 4); + p_order_4.set_uint("variable_ordering_strategy", 4); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_4), 5 * 1000)); params_ref p_order_3 = p; - p_order_3.set_uint("linxi_variable_ordering_strategy", 3); + p_order_3.set_uint("variable_ordering_strategy", 3); // p_order_3.set_uint("seed", 17); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_3), 10 * 1000)); params_ref p_order_1 = p; - p_order_1.set_uint("linxi_variable_ordering_strategy", 1); + p_order_1.set_uint("variable_ordering_strategy", 1); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_1), 15 * 1000)); params_ref p_order_5 = p; - p_order_5.set_uint("linxi_variable_ordering_strategy", 5); + p_order_5.set_uint("variable_ordering_strategy", 5); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_5), 15 * 1000)); params_ref p_order_2 = p; - p_order_2.set_uint("linxi_variable_ordering_strategy", 2); + p_order_2.set_uint("variable_ordering_strategy", 2); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_2), 20 * 1000)); } { @@ -155,12 +155,11 @@ tactic * linxi_mk_qfnra_small_solver(ast_manager& m, params_ref const& p) { return or_else(ts.size(), ts.data()); } -tactic * linxi_mk_qfnra_middle_solver(ast_manager& m, params_ref const& p) { +tactic * mk_qfnra_middle_solver(ast_manager& m, params_ref const& p) { ptr_vector ts; { params_ref p_sc = p; - p_sc.set_bool("linxi_simple_check", true); - // p_sc.set_uint("seed", 997); + p_sc.set_bool("simple_check", true); ts.push_back(try_for(and_then(mk_qfnra_nlsat_tactic(m, p_sc), mk_fail_if_undecided_tactic()), 30 * 1000)); } { @@ -170,27 +169,26 @@ tactic * linxi_mk_qfnra_middle_solver(ast_manager& m, params_ref const& p) { params_ref p_order_4 = p; - p_order_4.set_uint("linxi_variable_ordering_strategy", 4); + p_order_4.set_uint("variable_ordering_strategy", 4); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_4), 15 * 1000)); params_ref p_order_3 = p; - p_order_3.set_uint("linxi_variable_ordering_strategy", 3); - // p_order_3.set_uint("seed", 17); + p_order_3.set_uint("variable_ordering_strategy", 3); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_3), 15 * 1000)); params_ref p_order_1 = p; - p_order_1.set_uint("linxi_variable_ordering_strategy", 1); + p_order_1.set_uint("variable_ordering_strategy", 1); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_1), 20 * 1000)); params_ref p_order_5 = p; - p_order_5.set_uint("linxi_variable_ordering_strategy", 5); + p_order_5.set_uint("variable_ordering_strategy", 5); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_5), 20 * 1000)); params_ref p_order_2 = p; - p_order_2.set_uint("linxi_variable_ordering_strategy", 2); + p_order_2.set_uint("variable_ordering_strategy", 2); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_2), 25 * 1000)); } { @@ -215,38 +213,36 @@ tactic * linxi_mk_qfnra_middle_solver(ast_manager& m, params_ref const& p) { return or_else(ts.size(), ts.data()); } -tactic * linxi_mk_qfnra_large_solver(ast_manager& m, params_ref const& p) { +tactic * mk_qfnra_large_solver(ast_manager& m, params_ref const& p) { ptr_vector ts; { params_ref p_sc = p; - p_sc.set_bool("linxi_simple_check", true); - // p_sc.set_uint("seed", 997); + p_sc.set_bool("simple_check", true); ts.push_back(try_for(and_then(mk_qfnra_nlsat_tactic(m, p_sc), mk_fail_if_undecided_tactic()), 50 * 1000)); } { params_ref p_order_4 = p; - p_order_4.set_uint("linxi_variable_ordering_strategy", 4); + p_order_4.set_uint("variable_ordering_strategy", 4); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_4), 15 * 1000)); params_ref p_order_3 = p; - p_order_3.set_uint("linxi_variable_ordering_strategy", 3); - // p_order_3.set_uint("seed", 17); + p_order_3.set_uint("variable_ordering_strategy", 3); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_3), 30 * 1000)); params_ref p_order_1 = p; - p_order_1.set_uint("linxi_variable_ordering_strategy", 1); + p_order_1.set_uint("variable_ordering_strategy", 1); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_1), 40 * 1000)); params_ref p_order_5 = p; - p_order_5.set_uint("linxi_variable_ordering_strategy", 5); + p_order_5.set_uint("variable_ordering_strategy", 5); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_5), 40 * 1000)); params_ref p_order_2 = p; - p_order_2.set_uint("linxi_variable_ordering_strategy", 2); + p_order_2.set_uint("variable_ordering_strategy", 2); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_2), 50 * 1000)); } { @@ -271,27 +267,26 @@ tactic * linxi_mk_qfnra_large_solver(ast_manager& m, params_ref const& p) { return or_else(ts.size(), ts.data()); } -tactic * linxi_mk_qfnra_very_large_solver(ast_manager& m, params_ref const& p) { +tactic * mk_qfnra_very_large_solver(ast_manager& m, params_ref const& p) { ptr_vector ts; { params_ref p_sc = p; - p_sc.set_bool("linxi_simple_check", true); - // p_sc.set_uint("seed", 997); + p_sc.set_bool("simple_check", true); ts.push_back(try_for(and_then(mk_qfnra_nlsat_tactic(m, p_sc), mk_fail_if_undecided_tactic()), 100 * 1000)); } { params_ref p_order_1 = p; - p_order_1.set_uint("linxi_variable_ordering_strategy", 1); + p_order_1.set_uint("variable_ordering_strategy", 1); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_1), 80 * 1000)); params_ref p_order_5 = p; - p_order_5.set_uint("linxi_variable_ordering_strategy", 5); + p_order_5.set_uint("variable_ordering_strategy", 5); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_5), 80 * 1000)); params_ref p_order_2 = p; - p_order_2.set_uint("linxi_variable_ordering_strategy", 2); + p_order_2.set_uint("variable_ordering_strategy", 2); ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_order_2), 100 * 1000)); } { @@ -312,16 +307,16 @@ const double VERY_SMALL_THRESHOLD = 30.0; const double SMALL_THRESHOLD = 80.0; const double MIDDLE_THRESHOLD = 300.0; const double LARGE_THRESHOLD = 600.0; -tactic * linxi_mk_qfnra_mixed_solver(ast_manager& m, params_ref const& p) { +tactic * mk_qfnra_mixed_solver(ast_manager& m, params_ref const& p) { return cond(mk_lt(mk_memory_probe(), mk_const_probe(VERY_SMALL_THRESHOLD)), - linxi_mk_qfnra_very_small_solver(m, p), + mk_qfnra_very_small_solver(m, p), cond(mk_lt(mk_memory_probe(), mk_const_probe(SMALL_THRESHOLD)), - linxi_mk_qfnra_small_solver(m, p), + mk_qfnra_small_solver(m, p), cond(mk_lt(mk_memory_probe(), mk_const_probe(MIDDLE_THRESHOLD)), - linxi_mk_qfnra_middle_solver(m, p), + mk_qfnra_middle_solver(m, p), cond(mk_lt(mk_memory_probe(), mk_const_probe(LARGE_THRESHOLD)), - linxi_mk_qfnra_large_solver(m, p), - linxi_mk_qfnra_very_large_solver(m, p) + mk_qfnra_large_solver(m, p), + mk_qfnra_very_large_solver(m, p) ) ) ) @@ -332,7 +327,6 @@ tactic * mk_qfnra_tactic(ast_manager & m, params_ref const& p) { return and_then(mk_simplify_tactic(m, p), mk_propagate_values_tactic(m, p), - // mk_multilinear_ls_tactic(m, p) - linxi_mk_qfnra_mixed_solver(m, p) + mk_qfnra_mixed_solver(m, p) ); } From 33f0256e206a8f7d02ed9d5159492ee69f6a45b3 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Sat, 10 Aug 2024 14:53:56 -1000 Subject: [PATCH 058/187] cleanup --- src/nlsat/nlsat_simple_checker.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/nlsat/nlsat_simple_checker.h b/src/nlsat/nlsat_simple_checker.h index 969c7a141..1a854e855 100644 --- a/src/nlsat/nlsat_simple_checker.h +++ b/src/nlsat/nlsat_simple_checker.h @@ -7,7 +7,6 @@ namespace nlsat { struct imp; imp * m_imp; public: - // Simple_Checker(solver &_sol, pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, clause_vector &_learned, const atom_vector &_atoms, const unsigned &_arith_var_num); Simple_Checker(pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, literal_vector &_learned_unit, const atom_vector &_atoms, const unsigned &_arith_var_num); ~Simple_Checker(); bool operator()(); From 8999e1a340810dd181eddc7abbe14f3e2f828585 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 12 Aug 2024 08:29:06 -1000 Subject: [PATCH 059/187] use standard name conventions and add file headers Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_explain.h | 3 +- src/nlsat/nlsat_simple_checker.cpp | 26 +++------------- src/nlsat/nlsat_simple_checker.h | 25 ++++++++++++++-- src/nlsat/nlsat_solver.cpp | 4 +-- .../nlsat_variable_ordering_strategy.cpp | 30 +++++++++---------- src/nlsat/nlsat_variable_ordering_strategy.h | 27 +++++++++++++---- 6 files changed, 67 insertions(+), 48 deletions(-) diff --git a/src/nlsat/nlsat_explain.h b/src/nlsat/nlsat_explain.h index 2fdb76b11..f44a9ae92 100644 --- a/src/nlsat/nlsat_explain.h +++ b/src/nlsat/nlsat_explain.h @@ -8,7 +8,8 @@ Module Name: Abstract: Functor that implements the "explain" procedure defined in Dejan and Leo's paper. - + Uses paper Haokun Li and Bican Xia, "Solving Satisfiability of Polynomial Formulas By Sample - Cell Projection",https://arxiv.org/abs/2003.00409, + and code from https://github.com/hybridSMT/hybridSMT.git Author: Leonardo de Moura (leonardo) 2012-01-13. diff --git a/src/nlsat/nlsat_simple_checker.cpp b/src/nlsat/nlsat_simple_checker.cpp index 3e1e8dd1c..f61bc97ad 100644 --- a/src/nlsat/nlsat_simple_checker.cpp +++ b/src/nlsat/nlsat_simple_checker.cpp @@ -1,25 +1,7 @@ #include "nlsat/nlsat_simple_checker.h" -struct Debug_Tracer { - std::string tag_str; - Debug_Tracer(std::string _tag_str) { - tag_str = _tag_str; - TRACE("simple_checker", - tout << "Debug_Tracer begin\n"; - tout << tag_str << "\n"; - ); - } - ~Debug_Tracer() { - TRACE("simple_checker", - tout << "Debug_Tracer end\n"; - tout << tag_str << "\n"; - ); - } -}; - - namespace nlsat { - struct Simple_Checker::imp { + struct simple_checker::imp { // solver / pmanager ± anum_manager &am; @@ -1569,13 +1551,13 @@ else { // ( == 0) + (c > 0) -> > 0 return true; } }; - Simple_Checker::Simple_Checker(pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, literal_vector &_learned_unit, const atom_vector &_atoms, const unsigned &_arith_var_num) { + simple_checker::simple_checker(pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, literal_vector &_learned_unit, const atom_vector &_atoms, const unsigned &_arith_var_num) { m_imp = alloc(imp, _pm, _am, _clauses, _learned_unit, _atoms, _arith_var_num); } - Simple_Checker::~Simple_Checker() { + simple_checker::~simple_checker() { dealloc(m_imp); } - bool Simple_Checker::operator()() { + bool simple_checker::operator()() { return m_imp->operator()(); } } diff --git a/src/nlsat/nlsat_simple_checker.h b/src/nlsat/nlsat_simple_checker.h index 1a854e855..c13e2669c 100644 --- a/src/nlsat/nlsat_simple_checker.h +++ b/src/nlsat/nlsat_simple_checker.h @@ -1,14 +1,33 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + nlsat_simple_checker.cpp + +Abstract: + + Attempts to find a conflict by using simple polynomial forms. +Author: + + Mengyu Zhao (Linxi) and Shaowei Cai + +Revision History: + +--*/ + +#pragma once #include "math/polynomial/algebraic_numbers.h" #include "nlsat/nlsat_clause.h" namespace nlsat { - class Simple_Checker { + class simple_checker { struct imp; imp * m_imp; public: - Simple_Checker(pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, literal_vector &_learned_unit, const atom_vector &_atoms, const unsigned &_arith_var_num); - ~Simple_Checker(); + simple_checker(pmanager &_pm, anum_manager &_am, const clause_vector &_clauses, literal_vector &_learned_unit, const atom_vector &_atoms, const unsigned &_arith_var_num); + ~simple_checker(); bool operator()(); }; } \ No newline at end of file diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index 1c4aabe50..7c2dd1def 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -1783,7 +1783,7 @@ namespace nlsat { // test_anum(); literal_vector learned_unit; // Simple_Checker checker(m_solver, m_pm, m_am, m_clauses, m_learned, m_atoms, m_is_int.size()); - Simple_Checker checker(m_pm, m_am, m_clauses, learned_unit, m_atoms, m_is_int.size()); + simple_checker checker(m_pm, m_am, m_clauses, learned_unit, m_atoms, m_is_int.size()); if (!checker()) return false; for (unsigned i = 0, sz = learned_unit.size(); i < sz; ++i) { @@ -1800,7 +1800,7 @@ namespace nlsat { TRACE("reorder", tout << "runing vos: " << m_variable_ordering_strategy << '\n';); unsigned num = num_vars(); - VOS_Var_Info_Collector vos_collector(m_pm, m_atoms, num, m_variable_ordering_strategy); + vos_var_info_collector vos_collector(m_pm, m_atoms, num, m_variable_ordering_strategy); vos_collector.collect(m_clauses); vos_collector.collect(m_learned); diff --git a/src/nlsat/nlsat_variable_ordering_strategy.cpp b/src/nlsat/nlsat_variable_ordering_strategy.cpp index dfcc14201..5b91501e3 100644 --- a/src/nlsat/nlsat_variable_ordering_strategy.cpp +++ b/src/nlsat/nlsat_variable_ordering_strategy.cpp @@ -1,7 +1,7 @@ #include "nlsat/nlsat_variable_ordering_strategy.h" namespace nlsat { - struct VOS_Var_Info_Collector::imp { + struct vos_var_info_collector::imp { pmanager & pm; atom_vector const & m_atoms; unsigned num_vars; @@ -138,8 +138,8 @@ namespace nlsat { struct univariate_reorder_lt { - VOS_Var_Info_Collector::imp const *m_info; - univariate_reorder_lt(VOS_Var_Info_Collector::imp const *info):m_info(info) {} + vos_var_info_collector::imp const *m_info; + univariate_reorder_lt(vos_var_info_collector::imp const *info):m_info(info) {} bool operator()(var x, var y) const { if (m_info->m_num_uni[x] != m_info->m_num_uni[y]) return m_info->m_num_uni[x] > m_info->m_num_uni[y]; @@ -148,8 +148,8 @@ namespace nlsat { }; struct feature_reorder_lt { - VOS_Var_Info_Collector::imp const *m_info; - feature_reorder_lt(VOS_Var_Info_Collector::imp const * info): m_info(info){} + vos_var_info_collector::imp const *m_info; + feature_reorder_lt(vos_var_info_collector::imp const * info): m_info(info){} bool operator()(var x, var y) const { if (m_info->m_max_degree[x] != m_info->m_max_degree[y]) return m_info->m_max_degree[x] > m_info->m_max_degree[y]; @@ -162,8 +162,8 @@ namespace nlsat { } }; struct brown_reorder_lt { - VOS_Var_Info_Collector::imp const *m_info; - brown_reorder_lt(VOS_Var_Info_Collector::imp const *info):m_info(info) {} + vos_var_info_collector::imp const *m_info; + brown_reorder_lt(vos_var_info_collector::imp const *info):m_info(info) {} bool operator()(var x, var y) const { // if (a.max_degree != b.max_degree) // return a.max_degree > b.max_degree; @@ -180,8 +180,8 @@ namespace nlsat { } }; struct triangular_reorder_lt { - const VOS_Var_Info_Collector::imp *m_info; - triangular_reorder_lt(VOS_Var_Info_Collector::imp const *info):m_info(info) {} + const vos_var_info_collector::imp *m_info; + triangular_reorder_lt(vos_var_info_collector::imp const *info):m_info(info) {} bool operator()(var x, var y) const { // if (a.max_degree != b.max_degree) // return a.max_degree > b.max_degree; @@ -198,8 +198,8 @@ namespace nlsat { } }; struct onlypoly_reorder_lt { - const VOS_Var_Info_Collector::imp *m_info; - onlypoly_reorder_lt(VOS_Var_Info_Collector::imp const *info):m_info(info) {} + const vos_var_info_collector::imp *m_info; + onlypoly_reorder_lt(vos_var_info_collector::imp const *info):m_info(info) {} bool operator()(var x, var y) const { // high degree first if (m_info->m_max_degree[x] != m_info->m_max_degree[y]) @@ -267,16 +267,16 @@ namespace nlsat { // return out; // } }; - VOS_Var_Info_Collector::VOS_Var_Info_Collector(pmanager & _pm, atom_vector const & _atoms, unsigned _num_vars, unsigned _vos_type) { + vos_var_info_collector::vos_var_info_collector(pmanager & _pm, atom_vector const & _atoms, unsigned _num_vars, unsigned _vos_type) { m_imp = alloc(imp, _pm, _atoms, _num_vars, _vos_type); } - VOS_Var_Info_Collector::~VOS_Var_Info_Collector() { + vos_var_info_collector::~vos_var_info_collector() { dealloc(m_imp); } - void VOS_Var_Info_Collector::collect(clause_vector const & cs) { + void vos_var_info_collector::collect(clause_vector const & cs) { m_imp->collect(cs); } - void VOS_Var_Info_Collector::operator()(var_vector &perm) { + void vos_var_info_collector::operator()(var_vector &perm) { m_imp->operator()(perm); } } diff --git a/src/nlsat/nlsat_variable_ordering_strategy.h b/src/nlsat/nlsat_variable_ordering_strategy.h index 6e01825c3..b29bece27 100644 --- a/src/nlsat/nlsat_variable_ordering_strategy.h +++ b/src/nlsat/nlsat_variable_ordering_strategy.h @@ -1,3 +1,22 @@ +/*++ +Copyright (c) 2024 Microsoft Corporation + +Module Name: + + nlsat_simple_checker.cpp + +Abstract: + + +Author: + + Mengyu Zhao (Linxi) and Shaowei Cai, ported from https://github.com/hybridSMT/hybridSMT.git + +Revision History: + +--*/ + +#pragma once #include "nlsat/nlsat_clause.h" @@ -11,16 +30,14 @@ namespace nlsat { typedef polynomial::manager::numeral_vector numeral_vector; - // enum Variable_Ordering_Strategy_Type {NONE = 0, BROWN, TRIANGULAR, ONLYPOLY}; - enum Variable_Ordering_Strategy_Type {NONE = 0, BROWN, TRIANGULAR, ONLYPOLY, UNIVARIATE, FEATURE, ROOT}; - class VOS_Var_Info_Collector { + class vos_var_info_collector { struct imp; imp * m_imp; public: - VOS_Var_Info_Collector(pmanager & _pm, atom_vector const & atoms, unsigned _num_vars, unsigned _vos_type); - ~VOS_Var_Info_Collector(); + vos_var_info_collector(pmanager & _pm, atom_vector const & atoms, unsigned _num_vars, unsigned _vos_type); + ~vos_var_info_collector(); void operator()(var_vector &perm); void collect(clause_vector const & cs); }; From f2d35ddc5eec3c1ad1c8ba292c5c7bef50993ca4 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 12 Aug 2024 08:32:01 -1000 Subject: [PATCH 060/187] more cleanup --- src/nlsat/nlsat_solver.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index 7c2dd1def..c30515470 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -1780,9 +1780,7 @@ namespace nlsat { bool m_reordered = false; bool simple_check() { - // test_anum(); literal_vector learned_unit; - // Simple_Checker checker(m_solver, m_pm, m_am, m_clauses, m_learned, m_atoms, m_is_int.size()); simple_checker checker(m_pm, m_am, m_clauses, learned_unit, m_atoms, m_is_int.size()); if (!checker()) return false; From bf34600f08d732680f7a9b3d85a257caf435418b Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 12 Aug 2024 08:49:55 -1000 Subject: [PATCH 061/187] add release nodes and add the author reference in qfnra_tactic Signed-off-by: Lev Nachmanson --- RELEASE_NOTES.md | 7 +++++++ src/tactic/smtlogics/qfnra_tactic.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 3830f566f..b69772dcd 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -10,6 +10,13 @@ Version 4.next - native word level bit-vector solving. - introduction of simple induction lemmas to handle a limited repertoire of induction proofs. +Version 4.13.1 +============== +- single-sample cell projection in nlsat was designed by Haokun Li and Bican Xia. +- using simple-checker together with and variable ordering supported by qfnra_tactic was developed by Mengyu Zhao (Linxi) and Shaowei Cai. + + The projection is described in paper by Haokun Li and Bican Xia, [Solving Satisfiability of Polynomial Formulas By Sample - Cell Projection](https://arxiv.org/abs/2003.00409). The code ported from https://github.com/hybridSMT/hybridSMT.git + Version 4.13.0 ============== - add ARM64 wheels for Python, thanks to Steven Moy, smoy diff --git a/src/tactic/smtlogics/qfnra_tactic.h b/src/tactic/smtlogics/qfnra_tactic.h index 09a5d0480..344ea3f36 100644 --- a/src/tactic/smtlogics/qfnra_tactic.h +++ b/src/tactic/smtlogics/qfnra_tactic.h @@ -12,7 +12,7 @@ Abstract: Author: Leonardo (leonardo) 2012-02-28 - + Mengyu Zhao (Linxi) and Shaowei Cai, ported from https://github.com/hybridSMT/hybridSMT.git Notes: --*/ From 83f47bd84bbd2f22b1394cac03a024f1e49c5183 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 12 Aug 2024 10:28:27 -1000 Subject: [PATCH 062/187] wasm build problem Signed-off-by: Lev Nachmanson --- .github/workflows/wasm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 8e157f5a4..f0b8bd91b 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -48,7 +48,7 @@ jobs: source $(dirname $(which emsdk))/emsdk_env.sh which node which clang++ - npm run build:wasm + npm run build:wasm -- -sINITIAL_MEMORY=128MB -sALLOW_MEMORY_GROWTH - name: Test run: npm test From ed17de56d2433dbdfd11cca03f78ea8a47adb98e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 14 Aug 2024 08:51:20 -0700 Subject: [PATCH 063/187] fix #7343 Signed-off-by: Nikolaj Bjorner --- src/opt/opt_parse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opt/opt_parse.cpp b/src/opt/opt_parse.cpp index 29e8a604c..78ce8bd85 100644 --- a/src/opt/opt_parse.cpp +++ b/src/opt/opt_parse.cpp @@ -69,7 +69,7 @@ public: bool opt_stream_buffer::parse_token(char const* token) { skip_whitespace(); char const* t = token; - while (ch() == *t) { + while (*t && ch() == *t) { next(); ++t; } From 656545564dfdf7d82e27c8dc1f0f14bbea122352 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 14 Aug 2024 09:17:05 -0700 Subject: [PATCH 064/187] fix #7343 Signed-off-by: Nikolaj Bjorner --- src/opt/opt_parse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opt/opt_parse.cpp b/src/opt/opt_parse.cpp index 78ce8bd85..159246281 100644 --- a/src/opt/opt_parse.cpp +++ b/src/opt/opt_parse.cpp @@ -69,7 +69,7 @@ public: bool opt_stream_buffer::parse_token(char const* token) { skip_whitespace(); char const* t = token; - while (*t && ch() == *t) { + while (*t && ch() && ch() == *t) { next(); ++t; } From 0612a0ba1703d0fc312de4b16af6ff996b3fb45d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 22:09:44 +0100 Subject: [PATCH 065/187] Bump docker/build-push-action from 6.5.0 to 6.6.1 (#7338) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.5.0 to 6.6.1. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.5.0...v6.6.1) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 931ed071e..0b3827479 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -41,7 +41,7 @@ jobs: type=edge type=sha,prefix=ubuntu-20.04-bare-z3-sha- - name: Build and push Bare Z3 Docker Image - uses: docker/build-push-action@v6.5.0 + uses: docker/build-push-action@v6.6.1 with: context: . push: true From c1454dc31cf2de3c563fcdb83c60e030da0554a9 Mon Sep 17 00:00:00 2001 From: Zhang <5205699+Naville@users.noreply.github.com> Date: Fri, 16 Aug 2024 04:08:38 +0800 Subject: [PATCH 066/187] Fix building with Windows SDK and Clang-CL (#7337) * Fix building with Windows SDK and Clang-CL * Attempt to add Clang-CL to CI build configurations * Fix typo * Enable EHsc explicitly when using ClangCL due to it being default turned-off * Override CMAKE__FLAGS instead due to Z3 resets the _INIT variants --- .../workflows/msvc-static-build-clang-cl.yml | 23 +++++++++++++++++++ src/util/mpz.cpp | 22 +++++++++++------- 2 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/msvc-static-build-clang-cl.yml diff --git a/.github/workflows/msvc-static-build-clang-cl.yml b/.github/workflows/msvc-static-build-clang-cl.yml new file mode 100644 index 000000000..341f873c1 --- /dev/null +++ b/.github/workflows/msvc-static-build-clang-cl.yml @@ -0,0 +1,23 @@ +name: MSVC Clang-CL Static Build + +on: + push: + pull_request: + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + build: + runs-on: windows-2019 + env: + BUILD_TYPE: Release + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + + - name: Build + run: | + cmake -B build -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DZ3_BUILD_LIBZ3_SHARED=OFF -DZ3_BUILD_LIBZ3_MSVC_STATIC=ON -T ClangCL -DCMAKE_C_FLAGS="/EHsc" -DCMAKE_CXX_FLAGS="/EHsc" + cmake --build build --config ${{ env.BUILD_TYPE }} --parallel + diff --git a/src/util/mpz.cpp b/src/util/mpz.cpp index 296b4426e..b1837662c 100644 --- a/src/util/mpz.cpp +++ b/src/util/mpz.cpp @@ -46,10 +46,14 @@ Revision History: #define LEHMER_GCD #endif - -#if defined(__GNUC__) +#ifdef __has_builtin + #define HAS_BUILTIN(X) __has_builtin(X) +#else + #define HAS_BUILTIN(X) 0 +#endif +#if HAS_BUILTIN(__builtin_ctz) #define _trailing_zeros32(X) __builtin_ctz(X) -#elif defined(_WINDOWS) && (defined(_M_X86) || (defined(_M_X64) && !defined(_M_ARM64EC))) +#elif defined(_WINDOWS) && (defined(_M_X86) || (defined(_M_X64) && !defined(_M_ARM64EC))) && !defined(__clang__) // This is needed for _tzcnt_u32 and friends. #include #define _trailing_zeros32(X) _tzcnt_u32(X) @@ -62,11 +66,11 @@ static uint32_t _trailing_zeros32(uint32_t x) { #endif #if (defined(__LP64__) || defined(_WIN64)) && defined(_M_X64) && !defined(_M_ARM64EC) - #if defined(__GNUC__) - #define _trailing_zeros64(X) __builtin_ctzll(X) - #else - #define _trailing_zeros64(X) _tzcnt_u64(X) - #endif +#if HAS_BUILTIN(__builtin_ctzll) +#define _trailing_zeros64(X) __builtin_ctzll(X) +#elif !defined(__clang__) +#define _trailing_zeros64(X) _tzcnt_u64(X) +#endif #else static uint64_t _trailing_zeros64(uint64_t x) { uint64_t r = 0; @@ -75,6 +79,8 @@ static uint64_t _trailing_zeros64(uint64_t x) { } #endif +#undef HAS_BUILTIN + unsigned trailing_zeros(uint32_t x) { return static_cast(_trailing_zeros32(x)); } From 6a68cc55bbefcac1fdb417260850af9a84717260 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 26 Aug 2024 09:59:50 -0700 Subject: [PATCH 067/187] #7353 - clear pointer when existing stack Signed-off-by: Nikolaj Bjorner --- src/sat/sat_ddfw.cpp | 2 +- src/tactic/arith/fix_dl_var_tactic.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sat/sat_ddfw.cpp b/src/sat/sat_ddfw.cpp index bd7b0d26c..ccf5a55db 100644 --- a/src/sat/sat_ddfw.cpp +++ b/src/sat/sat_ddfw.cpp @@ -613,7 +613,7 @@ namespace sat { out << ci.m_num_trues << " " << ci.m_weight << "\n"; } for (unsigned v = 0; v < num_vars(); ++v) { - out << v << ": " << reward(v) << "\n"; + out << v << ": rw " << reward(v) << "\n"; } out << "unsat vars: "; for (bool_var v : m_unsat_vars) { diff --git a/src/tactic/arith/fix_dl_var_tactic.cpp b/src/tactic/arith/fix_dl_var_tactic.cpp index 13479e1bf..c96ca749b 100644 --- a/src/tactic/arith/fix_dl_var_tactic.cpp +++ b/src/tactic/arith/fix_dl_var_tactic.cpp @@ -35,7 +35,7 @@ class fix_dl_var_tactic : public tactic { struct failed {}; ast_manager & m; arith_util & m_util; - expr_fast_mark1 * m_visited; + expr_fast_mark1 * m_visited = nullptr; ptr_vector m_todo; obj_map m_occs; obj_map m_non_nested_occs; @@ -215,7 +215,7 @@ class fix_dl_var_tactic : public tactic { app * operator()(goal const & g) { try { expr_fast_mark1 visited; - m_visited = &visited; + flet _visited(m_visited, &visited); unsigned sz = g.size(); for (unsigned i = 0; i < sz; i++) { process(g.form(i)); From cff1e9233f752b69d9a14bd0270cdd33edb0d1ee Mon Sep 17 00:00:00 2001 From: "Kirill A. Korinsky" Date: Mon, 26 Aug 2024 19:02:54 +0200 Subject: [PATCH 068/187] Avoid broken stack at few places (#7353) * Avoid broken stack by degree_lit_num_lt * Avoid broken stack by fix_dl_var_tactic --------- Co-authored-by: Nikolaj Bjorner --- src/nlsat/nlsat_solver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index c30515470..e7e3071af 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -2835,7 +2835,7 @@ namespace nlsat { struct degree_lit_num_lt { unsigned_vector & m_degrees; unsigned_vector & m_lit_num; - degree_lit_num_lt(unsigned_vector & ds, unsigned_vector ln) : + degree_lit_num_lt(unsigned_vector & ds, unsigned_vector & ln) : m_degrees(ds), m_lit_num(ln) { } From 49ba3bc12fff6cd1e092a9671f3c4213819d749d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 26 Aug 2024 11:32:37 -0700 Subject: [PATCH 069/187] address compiler warnings gcc-13 Signed-off-by: Nikolaj Bjorner --- src/ast/proofs/proof_utils.h | 2 +- src/ast/simplifiers/dominator_simplifier.cpp | 4 +- src/ast/sls/bv_sls_eval.cpp | 1 - src/muz/spacer/spacer_concretize.cpp | 10 +- src/nlsat/nlsat_explain.cpp | 4 +- src/nlsat/nlsat_simplify.cpp | 1 - src/nlsat/nlsat_solver.cpp | 8268 +++++++++--------- src/qe/mbp/mbp_arrays_tg.cpp | 6 +- src/sat/sat_aig_cuts.cpp | 2 +- 9 files changed, 4147 insertions(+), 4151 deletions(-) diff --git a/src/ast/proofs/proof_utils.h b/src/ast/proofs/proof_utils.h index cc1744d4e..dbb9dfac0 100644 --- a/src/ast/proofs/proof_utils.h +++ b/src/ast/proofs/proof_utils.h @@ -230,7 +230,7 @@ public: << "New pf: " << mk_pp(newp, m) << "\n";); } - proof *r; + proof *r = nullptr; VERIFY(cache.find(pr, r)); DEBUG_CODE( diff --git a/src/ast/simplifiers/dominator_simplifier.cpp b/src/ast/simplifiers/dominator_simplifier.cpp index 2ef4528ab..0f9d70786 100644 --- a/src/ast/simplifiers/dominator_simplifier.cpp +++ b/src/ast/simplifiers/dominator_simplifier.cpp @@ -187,8 +187,8 @@ expr_ref dominator_simplifier::simplify_and_or(bool is_and, app * e) { } expr_ref dominator_simplifier::simplify_not(app * e) { - expr *ee; - ENSURE(m.is_not(e, ee)); + expr *ee = nullptr; + VERIFY(m.is_not(e, ee)); unsigned old_lvl = scope_level(); expr_ref t = simplify_rec(ee); local_pop(scope_level() - old_lvl); diff --git a/src/ast/sls/bv_sls_eval.cpp b/src/ast/sls/bv_sls_eval.cpp index f2dd165ab..eecc42511 100644 --- a/src/ast/sls/bv_sls_eval.cpp +++ b/src/ast/sls/bv_sls_eval.cpp @@ -145,7 +145,6 @@ namespace bv { SASSERT(m.is_bool(e)); SASSERT(e->get_family_id() == basic_family_id); - auto id = e->get_id(); switch (e->get_decl_kind()) { case OP_TRUE: return true; diff --git a/src/muz/spacer/spacer_concretize.cpp b/src/muz/spacer/spacer_concretize.cpp index 809e9a971..9700af149 100644 --- a/src/muz/spacer/spacer_concretize.cpp +++ b/src/muz/spacer/spacer_concretize.cpp @@ -27,7 +27,7 @@ struct proc { void operator()(var *n) const {} void operator()(quantifier *q) const {} void operator()(app const *n) const { - expr *e1, *e2; + expr *e1 = nullptr, *e2 = nullptr; if (m_arith.is_mul(n, e1, e2)) { if (is_var(e1) && !is_var(e2)) m_marks.mark(e2); @@ -71,7 +71,7 @@ bool pob_concretizer::apply(const expr_ref_vector &cube, expr_ref_vector &out) { } bool pob_concretizer::is_split_var(expr *e, expr *&var, bool &pos) { - expr *e1, *e2; + expr *e1 = nullptr, *e2 = nullptr; rational n; if (m_var_marks.is_marked(e)) { @@ -89,7 +89,7 @@ bool pob_concretizer::is_split_var(expr *e, expr *&var, bool &pos) { } void pob_concretizer::split_lit_le_lt(expr *_lit, expr_ref_vector &out) { - expr *e1, *e2; + expr *e1 = nullptr, *e2 = nullptr; expr *lit = _lit; m.is_not(_lit, lit); @@ -133,7 +133,7 @@ void pob_concretizer::split_lit_le_lt(expr *_lit, expr_ref_vector &out) { } void pob_concretizer::split_lit_ge_gt(expr *_lit, expr_ref_vector &out) { - expr *e1, *e2; + expr *e1 = nullptr, *e2 = nullptr; expr *lit = _lit; m.is_not(_lit, lit); @@ -182,7 +182,7 @@ bool pob_concretizer::apply_lit(expr *_lit, expr_ref_vector &out) { // split literals of the form a1*x1 + ... + an*xn ~ c, where c is a // constant, ~ is <, <=, >, or >=, and the top level operator of LHS is + - expr *e1, *e2; + expr *e1 = nullptr, *e2 = nullptr; if ((m_arith.is_lt(lit, e1, e2) || m_arith.is_le(lit, e1, e2)) && m_arith.is_add(e1)) { SASSERT(m_arith.is_numeral(e2)); diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp index 49842100d..12db1d3da 100644 --- a/src/nlsat/nlsat_explain.cpp +++ b/src/nlsat/nlsat_explain.cpp @@ -126,7 +126,7 @@ namespace nlsat { scoped_literal_vector m_core2; // temporary fields for storing the result - scoped_literal_vector * m_result; + scoped_literal_vector * m_result = nullptr; svector m_already_added_literal; evaluator & m_evaluator; @@ -149,8 +149,6 @@ namespace nlsat { m_todo(u), m_core1(s), m_core2(s), - m_result(nullptr), - m_cell_sample(is_sample), m_evaluator(ev) { diff --git a/src/nlsat/nlsat_simplify.cpp b/src/nlsat/nlsat_simplify.cpp index 2901d22c2..d483a0391 100644 --- a/src/nlsat/nlsat_simplify.cpp +++ b/src/nlsat/nlsat_simplify.cpp @@ -93,7 +93,6 @@ namespace nlsat { } void update_clauses(u_map const& b2l) { - bool is_sat = true; literal_vector lits; unsigned n = m_clauses.size(); diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index e7e3071af..f2c32cf6a 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -1,4134 +1,4134 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - nlsat_solver.cpp - -Abstract: - - Nonlinear arithmetic satisfiability procedure. The procedure is - complete for nonlinear real arithmetic, but it also has limited - support for integers. - -Author: - - Leonardo de Moura (leonardo) 2012-01-02. - -Revision History: - ---*/ -#include "util/z3_exception.h" -#include "util/chashtable.h" -#include "util/id_gen.h" -#include "util/map.h" -#include "util/dependency.h" -#include "util/permutation.h" -#include "math/polynomial/algebraic_numbers.h" -#include "math/polynomial/polynomial_cache.h" -#include "nlsat/nlsat_solver.h" -#include "nlsat/nlsat_clause.h" -#include "nlsat/nlsat_assignment.h" -#include "nlsat/nlsat_justification.h" -#include "nlsat/nlsat_evaluator.h" -#include "nlsat/nlsat_explain.h" -#include "nlsat/nlsat_params.hpp" -#include "nlsat/nlsat_simplify.h" -#include "nlsat/nlsat_simple_checker.h" -#include "nlsat/nlsat_variable_ordering_strategy.h" - -#define NLSAT_EXTRA_VERBOSE - -#ifdef NLSAT_EXTRA_VERBOSE -#define NLSAT_VERBOSE(CODE) IF_VERBOSE(10, CODE) -#else -#define NLSAT_VERBOSE(CODE) ((void)0) -#endif - -namespace nlsat { - - - typedef chashtable ineq_atom_table; - typedef chashtable root_atom_table; - - // for apply_permutation procedure - void swap(clause * & c1, clause * & c2) noexcept { - std::swap(c1, c2); - } - - struct solver::ctx { - params_ref m_params; - reslimit& m_rlimit; - small_object_allocator m_allocator; - unsynch_mpq_manager m_qm; - pmanager m_pm; - anum_manager m_am; - bool m_incremental; - ctx(reslimit& rlim, params_ref const & p, bool incremental): - m_params(p), - m_rlimit(rlim), - m_allocator("nlsat"), - m_pm(rlim, m_qm, &m_allocator), - m_am(rlim, m_qm, p, &m_allocator), - m_incremental(incremental) - {} - }; - - struct solver::imp { - - - struct dconfig { - typedef imp value_manager; - typedef small_object_allocator allocator; - typedef void* value; - static const bool ref_count = false; - }; - - typedef dependency_manager assumption_manager; - typedef assumption_manager::dependency* _assumption_set; - - typedef obj_ref assumption_set_ref; - - - typedef polynomial::cache cache; - typedef ptr_vector interval_set_vector; - - - - ctx& m_ctx; - solver& m_solver; - reslimit& m_rlimit; - small_object_allocator& m_allocator; - bool m_incremental; - unsynch_mpq_manager& m_qm; - pmanager& m_pm; - cache m_cache; - anum_manager& m_am; - mutable assumption_manager m_asm; - assignment m_assignment, m_lo, m_hi; // partial interpretation - evaluator m_evaluator; - interval_set_manager & m_ism; - ineq_atom_table m_ineq_atoms; - root_atom_table m_root_atoms; - - - vector m_bounds; - - id_gen m_cid_gen; - clause_vector m_clauses; // set of clauses - clause_vector m_learned; // set of learned clauses - clause_vector m_valids; - - unsigned m_num_bool_vars; - atom_vector m_atoms; // bool_var -> atom - svector m_bvalues; // boolean assignment - unsigned_vector m_levels; // bool_var -> level - svector m_justifications; - vector m_bwatches; // bool_var (that are not attached to atoms) -> clauses where it is maximal - bool_vector m_dead; // mark dead boolean variables - id_gen m_bid_gen; - - simplify m_simplify; - - bool_vector m_is_int; // m_is_int[x] is true if variable is integer - vector m_watches; // var -> clauses where variable is maximal - interval_set_vector m_infeasible; // var -> to a set of interval where the variable cannot be assigned to. - atom_vector m_var2eq; // var -> to asserted equality - var_vector m_perm; // var -> var permutation of the variables - var_vector m_inv_perm; - // m_perm: internal -> external - // m_inv_perm: external -> internal - struct perm_display_var_proc : public display_var_proc { - var_vector & m_perm; - display_var_proc m_default_display_var; - display_var_proc const * m_proc; // display external var ids - perm_display_var_proc(var_vector & perm): - m_perm(perm), - m_proc(nullptr) { - } - std::ostream& operator()(std::ostream & out, var x) const override { - if (m_proc == nullptr) - m_default_display_var(out, x); - else - (*m_proc)(out, m_perm[x]); - return out; - } - }; - perm_display_var_proc m_display_var; - - display_assumption_proc const* m_display_assumption; - struct display_literal_assumption : public display_assumption_proc { - imp& i; - literal_vector const& lits; - display_literal_assumption(imp& i, literal_vector const& lits): i(i), lits(lits) {} - std::ostream& operator()(std::ostream& out, assumption a) const override { - if (lits.begin() <= a && a < lits.end()) { - out << *((literal const*)a); - } - else if (i.m_display_assumption) { - (*i.m_display_assumption)(out, a); - } - return out; - } - - }; - struct scoped_display_assumptions { - imp& i; - display_assumption_proc const* m_save; - scoped_display_assumptions(imp& i, display_assumption_proc const& p): i(i), m_save(i.m_display_assumption) { - i.m_display_assumption = &p; - } - ~scoped_display_assumptions() { - i.m_display_assumption = m_save; - } - }; - - explain m_explain; - - bool_var m_bk; // current Boolean variable we are processing - var m_xk; // current arith variable we are processing - - unsigned m_scope_lvl; - - struct bvar_assignment {}; - struct stage {}; - struct trail { - enum kind { BVAR_ASSIGNMENT, INFEASIBLE_UPDT, NEW_LEVEL, NEW_STAGE, UPDT_EQ }; - kind m_kind; - union { - bool_var m_b; - interval_set * m_old_set; - atom * m_old_eq; - }; - trail(bool_var b, bvar_assignment):m_kind(BVAR_ASSIGNMENT), m_b(b) {} - trail(interval_set * old_set):m_kind(INFEASIBLE_UPDT), m_old_set(old_set) {} - trail(bool s, stage):m_kind(s ? NEW_STAGE : NEW_LEVEL) {} - trail(atom * a):m_kind(UPDT_EQ), m_old_eq(a) {} - }; - svector m_trail; - - anum m_zero; - - // configuration - unsigned long long m_max_memory; - unsigned m_lazy; // how lazy the solver is: 0 - satisfy all learned clauses, 1 - process only unit and empty learned clauses, 2 - use only conflict clauses for resolving conflicts - bool m_simplify_cores; - bool m_reorder; - bool m_randomize; - bool m_random_order; - unsigned m_random_seed; - bool m_inline_vars; - bool m_log_lemmas; - bool m_check_lemmas; - unsigned m_max_conflicts; - unsigned m_lemma_count; - bool m_simple_check; - unsigned m_variable_ordering_strategy; - bool m_set_0_more; - bool m_cell_sample; - - struct stats { - unsigned m_simplifications; - unsigned m_restarts; - unsigned m_conflicts; - unsigned m_propagations; - unsigned m_decisions; - unsigned m_stages; - unsigned m_irrational_assignments; // number of irrational witnesses - void reset() { memset(this, 0, sizeof(*this)); } - stats() { reset(); } - }; - // statistics - stats m_stats; - - imp(solver& s, ctx& c): - m_ctx(c), - m_solver(s), - m_rlimit(c.m_rlimit), - m_allocator(c.m_allocator), - m_incremental(c.m_incremental), - m_qm(c.m_qm), - m_pm(c.m_pm), - m_cache(m_pm), - m_am(c.m_am), - m_asm(*this, m_allocator), - m_assignment(m_am), m_lo(m_am), m_hi(m_am), - m_evaluator(s, m_assignment, m_pm, m_allocator), - m_ism(m_evaluator.ism()), - m_num_bool_vars(0), - m_simplify(s, m_atoms, m_clauses, m_learned, m_pm), - m_display_var(m_perm), - m_display_assumption(nullptr), - m_explain(s, m_assignment, m_cache, m_atoms, m_var2eq, m_evaluator, nlsat_params(c.m_params).cell_sample()), - m_scope_lvl(0), - m_lemma(s), - m_lazy_clause(s), - m_lemma_assumptions(m_asm) { - updt_params(c.m_params); - reset_statistics(); - mk_true_bvar(); - m_lemma_count = 0; - } - - ~imp() { - clear(); - } - - void mk_true_bvar() { - bool_var b = mk_bool_var(); - SASSERT(b == true_bool_var); - literal true_lit(b, false); - mk_clause(1, &true_lit, false, nullptr); - } - - void updt_params(params_ref const & _p) { - nlsat_params p(_p); - m_max_memory = p.max_memory(); - m_lazy = p.lazy(); - m_simplify_cores = p.simplify_conflicts(); - bool min_cores = p.minimize_conflicts(); - m_reorder = p.reorder(); - m_randomize = p.randomize(); - m_max_conflicts = p.max_conflicts(); - m_random_order = p.shuffle_vars(); - m_random_seed = p.seed(); - m_inline_vars = p.inline_vars(); - m_log_lemmas = p.log_lemmas(); - m_check_lemmas = p.check_lemmas(); - m_variable_ordering_strategy = p.variable_ordering_strategy(); - - - m_cell_sample = p.cell_sample(); - - - m_ism.set_seed(m_random_seed); - m_explain.set_simplify_cores(m_simplify_cores); - m_explain.set_minimize_cores(min_cores); - m_explain.set_factor(p.factor()); - m_am.updt_params(p.p); - } - - void reset() { - m_explain.reset(); - m_lemma.reset(); - m_lazy_clause.reset(); - undo_until_size(0); - del_clauses(); - del_unref_atoms(); - m_cache.reset(); - m_assignment.reset(); - m_lo.reset(); - m_hi.reset(); - } - - void clear() { - m_explain.reset(); - m_lemma.reset(); - m_lazy_clause.reset(); - undo_until_size(0); - del_clauses(); - del_unref_atoms(); - } - - void checkpoint() { - if (!m_rlimit.inc()) throw solver_exception(m_rlimit.get_cancel_msg()); - if (memory::get_allocation_size() > m_max_memory) throw solver_exception(Z3_MAX_MEMORY_MSG); - } - - // ----------------------- - // - // Basic - // - // ----------------------- - - unsigned num_bool_vars() const { - return m_num_bool_vars; - } - - unsigned num_vars() const { - return m_is_int.size(); - } - - bool is_int(var x) const { - return m_is_int[x]; - } - - void inc_ref(assumption) {} - - void dec_ref(assumption) {} - - void inc_ref(_assumption_set a) { - if (a != nullptr) m_asm.inc_ref(a); - } - - void dec_ref(_assumption_set a) { - if (a != nullptr) m_asm.dec_ref(a); - } - - void inc_ref(bool_var b) { - if (b == null_bool_var) - return; - atom * a = m_atoms[b]; - if (a == nullptr) - return; - TRACE("ref", display(tout << "inc: " << b << " " << a->ref_count() << " ", *a) << "\n";); - a->inc_ref(); - } - - void inc_ref(literal l) { - inc_ref(l.var()); - } - - void dec_ref(bool_var b) { - if (b == null_bool_var) - return; - atom * a = m_atoms[b]; - if (a == nullptr) - return; - SASSERT(a->ref_count() > 0); - a->dec_ref(); - TRACE("ref", display(tout << "dec: " << b << " " << a->ref_count() << " ", *a) << "\n";); - if (a->ref_count() == 0) - del(a); - } - - void dec_ref(literal l) { - dec_ref(l.var()); - } - - bool is_arith_atom(bool_var b) const { return m_atoms[b] != nullptr; } - - bool is_arith_literal(literal l) const { return is_arith_atom(l.var()); } - - var max_var(poly const * p) const { - return m_pm.max_var(p); - } - - var max_var(bool_var b) const { - if (!is_arith_atom(b)) - return null_var; - else - return m_atoms[b]->max_var(); - } - - var max_var(literal l) const { - return max_var(l.var()); - } - - /** - \brief Return the maximum variable occurring in cls. - */ - var max_var(unsigned sz, literal const * cls) const { - var x = null_var; - for (unsigned i = 0; i < sz; i++) { - literal l = cls[i]; - if (is_arith_literal(l)) { - var y = max_var(l); - if (x == null_var || y > x) - x = y; - } - } - return x; - } - - var max_var(clause const & cls) const { - return max_var(cls.size(), cls.data()); - } - - /** - \brief Return the maximum Boolean variable occurring in cls. - */ - bool_var max_bvar(clause const & cls) const { - bool_var b = null_bool_var; - for (literal l : cls) { - if (b == null_bool_var || l.var() > b) - b = l.var(); - } - return b; - } - - /** - \brief Return the degree of the maximal variable of the given atom - */ - unsigned degree(atom const * a) const { - if (a->is_ineq_atom()) { - unsigned max = 0; - unsigned sz = to_ineq_atom(a)->size(); - var x = a->max_var(); - for (unsigned i = 0; i < sz; i++) { - unsigned d = m_pm.degree(to_ineq_atom(a)->p(i), x); - if (d > max) - max = d; - } - return max; - } - else { - return m_pm.degree(to_root_atom(a)->p(), a->max_var()); - } - } - - /** - \brief Return the degree of the maximal variable in c - */ - unsigned degree(clause const & c) const { - var x = max_var(c); - if (x == null_var) - return 0; - unsigned max = 0; - for (literal l : c) { - atom const * a = m_atoms[l.var()]; - if (a == nullptr) - continue; - unsigned d = degree(a); - if (d > max) - max = d; - } - return max; - } - - // ----------------------- - // - // Variable, Atoms, Clauses & Assumption creation - // - // ----------------------- - - bool_var mk_bool_var_core() { - bool_var b = m_bid_gen.mk(); - m_num_bool_vars++; - m_atoms .setx(b, nullptr, nullptr); - m_bvalues .setx(b, l_undef, l_undef); - m_levels .setx(b, UINT_MAX, UINT_MAX); - m_justifications.setx(b, null_justification, null_justification); - m_bwatches .setx(b, clause_vector(), clause_vector()); - m_dead .setx(b, false, true); - return b; - } - - bool_var mk_bool_var() { - return mk_bool_var_core(); - } - - var mk_var(bool is_int) { - var x = m_pm.mk_var(); - register_var(x, is_int); - return x; - } - void register_var(var x, bool is_int) { - SASSERT(x == num_vars()); - m_is_int. push_back(is_int); - m_watches. push_back(clause_vector()); - m_infeasible.push_back(nullptr); - m_var2eq. push_back(nullptr); - m_perm. push_back(x); - m_inv_perm. push_back(x); - SASSERT(m_is_int.size() == m_watches.size()); - SASSERT(m_is_int.size() == m_infeasible.size()); - SASSERT(m_is_int.size() == m_var2eq.size()); - SASSERT(m_is_int.size() == m_perm.size()); - SASSERT(m_is_int.size() == m_inv_perm.size()); - } - - bool_vector m_found_vars; - void vars(literal l, var_vector& vs) { - vs.reset(); - atom * a = m_atoms[l.var()]; - if (a == nullptr) { - - } - else if (a->is_ineq_atom()) { - unsigned sz = to_ineq_atom(a)->size(); - var_vector new_vs; - for (unsigned j = 0; j < sz; j++) { - m_found_vars.reset(); - m_pm.vars(to_ineq_atom(a)->p(j), new_vs); - for (unsigned i = 0; i < new_vs.size(); ++i) { - if (!m_found_vars.get(new_vs[i], false)) { - m_found_vars.setx(new_vs[i], true, false); - vs.push_back(new_vs[i]); - } - } - } - } - else { - m_pm.vars(to_root_atom(a)->p(), vs); - //vs.erase(max_var(to_root_atom(a)->p())); - vs.push_back(to_root_atom(a)->x()); - } - } - - void deallocate(ineq_atom * a) { - unsigned obj_sz = ineq_atom::get_obj_size(a->size()); - a->~ineq_atom(); - m_allocator.deallocate(obj_sz, a); - } - - void deallocate(root_atom * a) { - a->~root_atom(); - m_allocator.deallocate(sizeof(root_atom), a); - } - - void del(bool_var b) { - SASSERT(m_bwatches[b].empty()); - //SASSERT(m_bvalues[b] == l_undef); - m_num_bool_vars--; - m_dead[b] = true; - m_atoms[b] = nullptr; - m_bvalues[b] = l_undef; - m_bid_gen.recycle(b); - } - - void del(ineq_atom * a) { - CTRACE("nlsat_solver", a->ref_count() > 0, display(tout, *a) << "\n";); - // this triggers in too many benign cases: - // SASSERT(a->ref_count() == 0); - m_ineq_atoms.erase(a); - del(a->bvar()); - unsigned sz = a->size(); - for (unsigned i = 0; i < sz; i++) - m_pm.dec_ref(a->p(i)); - deallocate(a); - } - - void del(root_atom * a) { - SASSERT(a->ref_count() == 0); - m_root_atoms.erase(a); - del(a->bvar()); - m_pm.dec_ref(a->p()); - deallocate(a); - } - - void del(atom * a) { - if (a == nullptr) - return; - TRACE("nlsat_verbose", display(tout << "del: b" << a->m_bool_var << " " << a->ref_count() << " ", *a) << "\n";); - if (a->is_ineq_atom()) - del(to_ineq_atom(a)); - else - del(to_root_atom(a)); - } - - // Delete atoms with ref_count == 0 - void del_unref_atoms() { - for (auto* a : m_atoms) { - del(a); - } - } - - - ineq_atom* mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool& is_new, bool simplify) { - SASSERT(sz >= 1); - SASSERT(k == atom::LT || k == atom::GT || k == atom::EQ); - int sign = 1; - polynomial_ref p(m_pm); - ptr_buffer uniq_ps; - var max = null_var; - for (unsigned i = 0; i < sz; i++) { - p = m_pm.flip_sign_if_lm_neg(ps[i]); - if (p.get() != ps[i] && !is_even[i]) { - sign = -sign; - } - var curr_max = max_var(p.get()); - if (curr_max > max || max == null_var) - max = curr_max; - if (sz == 1 && simplify) { - if (sign < 0) - k = atom::flip(k); - sign = 1; - polynomial::manager::ineq_type t; - switch (k) { - case atom::EQ: t = polynomial::manager::ineq_type::EQ; break; - case atom::LT: t = polynomial::manager::ineq_type::LT; break; - case atom::GT: t = polynomial::manager::ineq_type::GT; break; - default: UNREACHABLE(); break; - } - polynomial::var_vector vars; - m_pm.vars(p, vars); - bool all_int = all_of(vars, [&](var x) { return is_int(x); }); - if (!all_int) - t = polynomial::manager::ineq_type::EQ; - m_pm.gcd_simplify(p, t); - } - uniq_ps.push_back(m_cache.mk_unique(p)); - TRACE("nlsat_table_bug", tout << "p: " << p << ", uniq: " << uniq_ps.back() << "\n";); - //verbose_stream() << "p: " << p.get() << ", uniq: " << uniq_ps.back() << "\n"; - } - void * mem = m_allocator.allocate(ineq_atom::get_obj_size(sz)); - if (sign < 0) - k = atom::flip(k); - ineq_atom * tmp_atom = new (mem) ineq_atom(k, sz, uniq_ps.data(), is_even, max); - ineq_atom * atom = m_ineq_atoms.insert_if_not_there(tmp_atom); - CTRACE("nlsat_table_bug", tmp_atom != atom, ineq_atom::hash_proc h; - tout << "mk_ineq_atom hash: " << h(tmp_atom) << "\n"; display(tout, *tmp_atom, m_display_var) << "\n";); - CTRACE("nlsat_table_bug", atom->max_var() != max, display(tout << "nonmax: ", *atom, m_display_var) << "\n";); - SASSERT(atom->max_var() == max); - is_new = (atom == tmp_atom); - if (is_new) { - for (unsigned i = 0; i < sz; i++) { - m_pm.inc_ref(atom->p(i)); - } - } - else { - deallocate(tmp_atom); - } - return atom; - } - - bool_var mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify = false) { - bool is_new = false; - ineq_atom* atom = mk_ineq_atom(k, sz, ps, is_even, is_new, simplify); - if (!is_new) { - return atom->bvar(); - } - else { - bool_var b = mk_bool_var_core(); - m_atoms[b] = atom; - atom->m_bool_var = b; - TRACE("nlsat_verbose", display(tout << "create: b" << atom->m_bool_var << " ", *atom) << "\n";); - return b; - } - } - - literal mk_ineq_literal(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify = false) { - SASSERT(k == atom::LT || k == atom::GT || k == atom::EQ); - bool is_const = true; - polynomial::manager::scoped_numeral cnst(m_pm.m()); - m_pm.m().set(cnst, 1); - for (unsigned i = 0; i < sz; ++i) { - if (m_pm.is_const(ps[i])) { - if (m_pm.is_zero(ps[i])) { - m_pm.m().set(cnst, 0); - is_const = true; - break; - } - auto const& c = m_pm.coeff(ps[i], 0); - m_pm.m().mul(cnst, c, cnst); - if (is_even[i] && m_pm.m().is_neg(c)) { - m_pm.m().neg(cnst); - } - } - else { - is_const = false; - } - } - if (is_const) { - if (m_pm.m().is_pos(cnst) && k == atom::GT) return true_literal; - if (m_pm.m().is_neg(cnst) && k == atom::LT) return true_literal; - if (m_pm.m().is_zero(cnst) && k == atom::EQ) return true_literal; - return false_literal; - } - return literal(mk_ineq_atom(k, sz, ps, is_even, simplify), false); - } - - bool_var mk_root_atom(atom::kind k, var x, unsigned i, poly * p) { - polynomial_ref p1(m_pm), uniq_p(m_pm); - p1 = m_pm.flip_sign_if_lm_neg(p); // flipping the sign of the polynomial will not change its roots. - uniq_p = m_cache.mk_unique(p1); - TRACE("nlsat_solver", tout << x << " " << p1 << " " << uniq_p << "\n";); - SASSERT(i > 0); - SASSERT(x >= max_var(p)); - SASSERT(k == atom::ROOT_LT || k == atom::ROOT_GT || k == atom::ROOT_EQ || k == atom::ROOT_LE || k == atom::ROOT_GE); - - void * mem = m_allocator.allocate(sizeof(root_atom)); - root_atom * new_atom = new (mem) root_atom(k, x, i, uniq_p); - root_atom * old_atom = m_root_atoms.insert_if_not_there(new_atom); - SASSERT(old_atom->max_var() == x); - if (old_atom != new_atom) { - deallocate(new_atom); - return old_atom->bvar(); - } - bool_var b = mk_bool_var_core(); - m_atoms[b] = new_atom; - new_atom->m_bool_var = b; - m_pm.inc_ref(new_atom->p()); - return b; - } - - void attach_clause(clause & cls) { - var x = max_var(cls); - if (x != null_var) { - m_watches[x].push_back(&cls); - } - else { - bool_var b = max_bvar(cls); - m_bwatches[b].push_back(&cls); - } - } - - void deattach_clause(clause & cls) { - var x = max_var(cls); - if (x != null_var) { - m_watches[x].erase(&cls); - } - else { - bool_var b = max_bvar(cls); - m_bwatches[b].erase(&cls); - } - } - - void deallocate(clause * cls) { - size_t obj_sz = clause::get_obj_size(cls->size()); - cls->~clause(); - m_allocator.deallocate(obj_sz, cls); - } - - void del_clause(clause * cls) { - deattach_clause(*cls); - m_cid_gen.recycle(cls->id()); - unsigned sz = cls->size(); - for (unsigned i = 0; i < sz; i++) - dec_ref((*cls)[i]); - _assumption_set a = static_cast<_assumption_set>(cls->assumptions()); - dec_ref(a); - deallocate(cls); - } - - void del_clause(clause * cls, clause_vector& clauses) { - clauses.erase(cls); - del_clause(cls); - } - - void del_clauses(ptr_vector & cs) { - for (clause* cp : cs) - del_clause(cp); - cs.reset(); - } - - void del_clauses() { - del_clauses(m_clauses); - del_clauses(m_learned); - del_clauses(m_valids); - } - - // We use a simple heuristic to sort literals - // - bool literals < arith literals - // - sort literals based on max_var - // - sort literal with the same max_var using degree - // break ties using the fact that ineqs are usually cheaper to process than eqs. - struct lit_lt { - imp & m; - lit_lt(imp & _m):m(_m) {} - - bool operator()(literal l1, literal l2) const { - atom * a1 = m.m_atoms[l1.var()]; - atom * a2 = m.m_atoms[l2.var()]; - if (a1 == nullptr && a2 == nullptr) - return l1.index() < l2.index(); - if (a1 == nullptr) - return true; - if (a2 == nullptr) - return false; - var x1 = a1->max_var(); - var x2 = a2->max_var(); - if (x1 < x2) - return true; - if (x1 > x2) - return false; - SASSERT(x1 == x2); - unsigned d1 = m.degree(a1); - unsigned d2 = m.degree(a2); - if (d1 < d2) - return true; - if (d1 > d2) - return false; - if (!a1->is_eq() && a2->is_eq()) - return true; - if (a1->is_eq() && !a2->is_eq()) - return false; - return l1.index() < l2.index(); - } - }; - - class scoped_bool_vars { - imp& s; - svector vec; - public: - scoped_bool_vars(imp& s):s(s) {} - ~scoped_bool_vars() { - for (bool_var v : vec) { - s.dec_ref(v); - } - } - void push_back(bool_var v) { - s.inc_ref(v); - vec.push_back(v); - } - bool_var const* begin() const { return vec.begin(); } - bool_var const* end() const { return vec.end(); } - bool_var operator[](bool_var v) const { return vec[v]; } - }; - - void check_lemma(unsigned n, literal const* cls, bool is_valid, assumption_set a) { - TRACE("nlsat", display(tout << "check lemma: ", n, cls) << "\n"; - display(tout);); - IF_VERBOSE(2, display(verbose_stream() << "check lemma " << (is_valid?"valid: ":"consequence: "), n, cls) << "\n"); - for (clause* c : m_learned) IF_VERBOSE(1, display(verbose_stream() << "lemma: ", *c) << "\n"); - scoped_suspend_rlimit _limit(m_rlimit); - ctx c(m_rlimit, m_ctx.m_params, m_ctx.m_incremental); - solver solver2(c); - imp& checker = *(solver2.m_imp); - checker.m_check_lemmas = false; - checker.m_log_lemmas = false; - checker.m_inline_vars = false; - - auto pconvert = [&](poly* p) { - return convert(m_pm, p, checker.m_pm); - }; - - // need to translate Boolean variables and literals - scoped_bool_vars tr(checker); - for (var x = 0; x < m_is_int.size(); ++x) { - checker.register_var(x, is_int(x)); - } - bool_var bv = 0; - tr.push_back(bv); - for (bool_var b = 1; b < m_atoms.size(); ++b) { - atom* a = m_atoms[b]; - if (a == nullptr) { - bv = checker.mk_bool_var(); - } - else if (a->is_ineq_atom()) { - ineq_atom& ia = *to_ineq_atom(a); - unsigned sz = ia.size(); - polynomial_ref_vector ps(checker.m_pm); - bool_vector is_even; - for (unsigned i = 0; i < sz; ++i) { - ps.push_back(pconvert(ia.p(i))); - is_even.push_back(ia.is_even(i)); - } - bv = checker.mk_ineq_atom(ia.get_kind(), sz, ps.data(), is_even.data()); - } - else if (a->is_root_atom()) { - root_atom& r = *to_root_atom(a); - if (r.x() >= max_var(r.p())) { - // permutation may be reverted after check completes, - // but then root atoms are not used in lemmas. - bv = checker.mk_root_atom(r.get_kind(), r.x(), r.i(), pconvert(r.p())); - } - } - else { - UNREACHABLE(); - } - tr.push_back(bv); - } - if (!is_valid) { - for (clause* c : m_clauses) { - if (!a && c->assumptions()) { - continue; - } - literal_vector lits; - for (literal lit : *c) { - lits.push_back(literal(tr[lit.var()], lit.sign())); - } - checker.mk_external_clause(lits.size(), lits.data(), nullptr); - } - } - for (unsigned i = 0; i < n; ++i) { - literal lit = cls[i]; - literal nlit(tr[lit.var()], !lit.sign()); - checker.mk_external_clause(1, &nlit, nullptr); - } - lbool r = checker.check(); - if (r == l_true) { - for (bool_var b : tr) { - literal lit(b, false); - IF_VERBOSE(0, checker.display(verbose_stream(), lit) << " := " << checker.value(lit) << "\n"); - TRACE("nlsat", checker.display(tout, lit) << " := " << checker.value(lit) << "\n";); - } - for (clause* c : m_learned) { - bool found = false; - for (literal lit: *c) { - literal tlit(tr[lit.var()], lit.sign()); - found |= checker.value(tlit) == l_true; - } - if (!found) { - IF_VERBOSE(0, display(verbose_stream() << "violdated clause: ", *c) << "\n"); - TRACE("nlsat", display(tout << "violdated clause: ", *c) << "\n";); - } - } - for (clause* c : m_valids) { - bool found = false; - for (literal lit: *c) { - literal tlit(tr[lit.var()], lit.sign()); - found |= checker.value(tlit) == l_true; - } - if (!found) { - IF_VERBOSE(0, display(verbose_stream() << "violdated tautology clause: ", *c) << "\n"); - TRACE("nlsat", display(tout << "violdated tautology clause: ", *c) << "\n";); - } - } - throw default_exception("lemma did not check"); - UNREACHABLE(); - } - } - - void log_lemma(std::ostream& out, clause const& cls) { - log_lemma(out, cls.size(), cls.data(), false); - } - - void log_lemma(std::ostream& out, unsigned n, literal const* cls, bool is_valid) { - ++m_lemma_count; - out << "(set-logic NRA)\n"; - if (is_valid) { - display_smt2_bool_decls(out); - display_smt2_arith_decls(out); - } - else - display_smt2(out); - for (unsigned i = 0; i < n; ++i) - display_smt2(out << "(assert ", ~cls[i]) << ")\n"; - display(out << "(echo \"#" << m_lemma_count << " ", n, cls) << "\")\n"; - out << "(check-sat)\n(reset)\n"; - - TRACE("nlsat", display(tout << "(echo \"#" << m_lemma_count << " ", n, cls) << "\")\n"); - } - - clause * mk_clause_core(unsigned num_lits, literal const * lits, bool learned, _assumption_set a) { - SASSERT(num_lits > 0); - unsigned cid = m_cid_gen.mk(); - void * mem = m_allocator.allocate(clause::get_obj_size(num_lits)); - clause * cls = new (mem) clause(cid, num_lits, lits, learned, a); - for (unsigned i = 0; i < num_lits; i++) - inc_ref(lits[i]); - inc_ref(a); - return cls; - } - - clause * mk_clause(unsigned num_lits, literal const * lits, bool learned, _assumption_set a) { - if (num_lits == 0) { - num_lits = 1; - lits = &false_literal; - } - SASSERT(num_lits > 0); - clause * cls = mk_clause_core(num_lits, lits, learned, a); - TRACE("nlsat_sort", display(tout << "mk_clause:\n", *cls) << "\n";); - std::sort(cls->begin(), cls->end(), lit_lt(*this)); - TRACE("nlsat", display(tout << " after sort:\n", *cls) << "\n";); - if (learned && m_log_lemmas) { - log_lemma(verbose_stream(), *cls); - } - if (learned && m_check_lemmas && false) { - check_lemma(cls->size(), cls->data(), false, cls->assumptions()); - } - if (learned) - m_learned.push_back(cls); - else - m_clauses.push_back(cls); - attach_clause(*cls); - return cls; - } - - void mk_external_clause(unsigned num_lits, literal const * lits, assumption a) { - _assumption_set as = nullptr; - if (a != nullptr) - as = m_asm.mk_leaf(a); - if (num_lits == 0) { - num_lits = 1; - lits = &false_literal; - } - mk_clause(num_lits, lits, false, as); - } - - // ----------------------- - // - // Search - // - // ----------------------- - - void save_assign_trail(bool_var b) { - m_trail.push_back(trail(b, bvar_assignment())); - } - - void save_set_updt_trail(interval_set * old_set) { - m_trail.push_back(trail(old_set)); - } - - void save_updt_eq_trail(atom * old_eq) { - m_trail.push_back(trail(old_eq)); - } - - void save_new_stage_trail() { - m_trail.push_back(trail(true, stage())); - } - - void save_new_level_trail() { - m_trail.push_back(trail(false, stage())); - } - - void undo_bvar_assignment(bool_var b) { - m_bvalues[b] = l_undef; - m_levels[b] = UINT_MAX; - del_jst(m_allocator, m_justifications[b]); - m_justifications[b] = null_justification; - if (m_atoms[b] == nullptr && b < m_bk) - m_bk = b; - } - - void undo_set_updt(interval_set * old_set) { - if (m_xk == null_var) - return; - var x = m_xk; - if (x < m_infeasible.size()) { - m_ism.dec_ref(m_infeasible[x]); - m_infeasible[x] = old_set; - } - } - - void undo_new_stage() { - if (m_xk == 0) { - m_xk = null_var; - } - else if (m_xk != null_var) { - m_xk--; - m_assignment.reset(m_xk); - } - } - - void undo_new_level() { - SASSERT(m_scope_lvl > 0); - m_scope_lvl--; - m_evaluator.pop(1); - } - - void undo_updt_eq(atom * a) { - if (m_var2eq.size() > m_xk) - m_var2eq[m_xk] = a; - } - - template - void undo_until(Predicate const & pred) { - while (pred() && !m_trail.empty()) { - trail & t = m_trail.back(); - switch (t.m_kind) { - case trail::BVAR_ASSIGNMENT: - undo_bvar_assignment(t.m_b); - break; - case trail::INFEASIBLE_UPDT: - undo_set_updt(t.m_old_set); - break; - case trail::NEW_STAGE: - undo_new_stage(); - break; - case trail::NEW_LEVEL: - undo_new_level(); - break; - case trail::UPDT_EQ: - undo_updt_eq(t.m_old_eq); - break; - default: - break; - } - m_trail.pop_back(); - } - } - - struct size_pred { - svector & m_trail; - unsigned m_old_size; - size_pred(svector & trail, unsigned old_size):m_trail(trail), m_old_size(old_size) {} - bool operator()() const { return m_trail.size() > m_old_size; } - }; - - // Keep undoing until trail has the given size - void undo_until_size(unsigned old_size) { - SASSERT(m_trail.size() >= old_size); - undo_until(size_pred(m_trail, old_size)); - } - - struct stage_pred { - var const & m_xk; - var m_target; - stage_pred(var const & xk, var target):m_xk(xk), m_target(target) {} - bool operator()() const { return m_xk != m_target; } - }; - - // Keep undoing until stage is new_xk - void undo_until_stage(var new_xk) { - undo_until(stage_pred(m_xk, new_xk)); - } - - struct level_pred { - unsigned const & m_scope_lvl; - unsigned m_new_lvl; - level_pred(unsigned const & scope_lvl, unsigned new_lvl):m_scope_lvl(scope_lvl), m_new_lvl(new_lvl) {} - bool operator()() const { return m_scope_lvl > m_new_lvl; } - }; - - // Keep undoing until level is new_lvl - void undo_until_level(unsigned new_lvl) { - undo_until(level_pred(m_scope_lvl, new_lvl)); - } - - struct unassigned_pred { - bool_var m_b; - svector const & m_bvalues; - unassigned_pred(svector const & bvalues, bool_var b): - m_b(b), - m_bvalues(bvalues) {} - bool operator()() const { return m_bvalues[m_b] != l_undef; } - }; - - // Keep undoing until b is unassigned - void undo_until_unassigned(bool_var b) { - undo_until(unassigned_pred(m_bvalues, b)); - SASSERT(m_bvalues[b] == l_undef); - } - - struct true_pred { - bool operator()() const { return true; } - }; - - void undo_until_empty() { - undo_until(true_pred()); - } - - /** - \brief Create a new scope level - */ - void new_level() { - m_evaluator.push(); - m_scope_lvl++; - save_new_level_trail(); - } - - /** - \brief Return the value of the given literal that was assigned by the search - engine. - */ - lbool assigned_value(literal l) const { - bool_var b = l.var(); - if (l.sign()) - return ~m_bvalues[b]; - else - return m_bvalues[b]; - } - - /** - \brief Assign literal using the given justification - */ - void assign(literal l, justification j) { - TRACE("nlsat_assign", - display(tout << "assigning literal: ", l); - display(tout << " <- ", j);); - - SASSERT(assigned_value(l) == l_undef); - SASSERT(j != null_justification); - SASSERT(!j.is_null()); - if (j.is_decision()) - m_stats.m_decisions++; - else - m_stats.m_propagations++; - bool_var b = l.var(); - m_bvalues[b] = to_lbool(!l.sign()); - m_levels[b] = m_scope_lvl; - m_justifications[b] = j; - save_assign_trail(b); - updt_eq(b, j); - TRACE("nlsat_assign", tout << "b" << b << " -> " << m_bvalues[b] << "\n";); - } - - /** - \brief Create a "case-split" - */ - void decide(literal l) { - new_level(); - assign(l, decided_justification); - } - - /** - \brief Return the value of a literal as defined in Dejan and Leo's paper. - */ - lbool value(literal l) { - lbool val = assigned_value(l); - if (val != l_undef) { - TRACE("nlsat_verbose", display(tout << " assigned value " << val << " for ", l) << "\n";); - return val; - } - bool_var b = l.var(); - atom * a = m_atoms[b]; - if (a == nullptr) { - TRACE("nlsat_verbose", display(tout << " no atom for ", l) << "\n";); - return l_undef; - } - var max = a->max_var(); - if (!m_assignment.is_assigned(max)) { - TRACE("nlsat_verbose", display(tout << " maximal variable not assigned ", l) << "\n";); - return l_undef; - } - val = to_lbool(m_evaluator.eval(a, l.sign())); - TRACE("nlsat_verbose", display(tout << " evaluated value " << val << " for ", l) << "\n";); - TRACE("value_bug", tout << "value of: "; display(tout, l); tout << " := " << val << "\n"; - tout << "xk: " << m_xk << ", a->max_var(): " << a->max_var() << "\n"; - display_assignment(tout);); - return val; - } - - /** - \brief Return true if the given clause is already satisfied in the current partial interpretation. - */ - bool is_satisfied(clause const & cls) const { - for (literal l : cls) { - if (const_cast(this)->value(l) == l_true) { - TRACE("value_bug:", tout << l << " := true\n";); - return true; - } - } - return false; - } - - /** - \brief Return true if the given clause is false in the current partial interpretation. - */ - bool is_inconsistent(unsigned sz, literal const * cls) { - for (unsigned i = 0; i < sz; i++) { - if (value(cls[i]) != l_false) { - TRACE("is_inconsistent", tout << "literal is not false:\n"; display(tout, cls[i]); tout << "\n";); - return false; - } - } - return true; - } - - /** - \brief Process a clauses that contains only Boolean literals. - */ - bool process_boolean_clause(clause const & cls) { - SASSERT(m_xk == null_var); - unsigned num_undef = 0; - unsigned first_undef = UINT_MAX; - unsigned sz = cls.size(); - for (unsigned i = 0; i < sz; i++) { - literal l = cls[i]; - SASSERT(m_atoms[l.var()] == nullptr); - SASSERT(value(l) != l_true); - if (value(l) == l_false) - continue; - SASSERT(value(l) == l_undef); - num_undef++; - if (first_undef == UINT_MAX) - first_undef = i; - } - if (num_undef == 0) - return false; - SASSERT(first_undef != UINT_MAX); - if (num_undef == 1) - assign(cls[first_undef], mk_clause_jst(&cls)); // unit clause - else - decide(cls[first_undef]); - return true; - } - - /** - \brief assign l to true, because l + (justification of) s is infeasible in RCF in the current interpretation. - */ - literal_vector core; - ptr_vector clauses; - void R_propagate(literal l, interval_set const * s, bool include_l = true) { - m_ism.get_justifications(s, core, clauses); - if (include_l) - core.push_back(~l); - auto j = mk_lazy_jst(m_allocator, core.size(), core.data(), clauses.size(), clauses.data()); - TRACE("nlsat_resolve", display(tout, j); display_eval(tout << "evaluated:", j)); - assign(l, j); - SASSERT(value(l) == l_true); - } - - /** - \brief m_infeasible[m_xk] <- m_infeasible[m_xk] Union s - */ - void updt_infeasible(interval_set const * s) { - SASSERT(m_xk != null_var); - interval_set * xk_set = m_infeasible[m_xk]; - save_set_updt_trail(xk_set); - interval_set_ref new_set(m_ism); - TRACE("nlsat_inf_set", tout << "updating infeasible set\n"; m_ism.display(tout, xk_set) << "\n"; m_ism.display(tout, s) << "\n";); - new_set = m_ism.mk_union(s, xk_set); - TRACE("nlsat_inf_set", tout << "new infeasible set:\n"; m_ism.display(tout, new_set) << "\n";); - SASSERT(!m_ism.is_full(new_set)); - m_ism.inc_ref(new_set); - m_infeasible[m_xk] = new_set; - } - - /** - \brief Update m_var2eq mapping. - */ - void updt_eq(bool_var b, justification j) { - if (!m_simplify_cores) - return; - if (m_bvalues[b] != l_true) - return; - atom * a = m_atoms[b]; - if (a == nullptr || a->get_kind() != atom::EQ || to_ineq_atom(a)->size() > 1 || to_ineq_atom(a)->is_even(0)) - return; - switch (j.get_kind()) { - case justification::CLAUSE: - if (j.get_clause()->assumptions() != nullptr) return; - break; - case justification::LAZY: - if (j.get_lazy()->num_clauses() > 0) return; - if (j.get_lazy()->num_lits() > 0) return; - break; - default: - break; - } - var x = m_xk; - SASSERT(a->max_var() == x); - SASSERT(x != null_var); - if (m_var2eq[x] != 0 && degree(m_var2eq[x]) <= degree(a)) - return; // we only update m_var2eq if the new equality has smaller degree - TRACE("nlsat_simplify_core", tout << "Saving equality for "; m_display_var(tout, x) << " (x" << x << ") "; - tout << "scope-lvl: " << scope_lvl() << "\n"; display(tout, literal(b, false)) << "\n"; - display(tout, j); - ); - save_updt_eq_trail(m_var2eq[x]); - m_var2eq[x] = a; - } - - /** - \brief Process a clause that contains nonlinear arithmetic literals - - If satisfy_learned is true, then learned clauses are satisfied even if m_lazy > 0 - */ - bool process_arith_clause(clause const & cls, bool satisfy_learned) { - if (!satisfy_learned && m_lazy >= 2 && cls.is_learned()) { - TRACE("nlsat", tout << "skip learned\n";); - return true; // ignore lemmas in super lazy mode - } - SASSERT(m_xk == max_var(cls)); - unsigned num_undef = 0; // number of undefined literals - unsigned first_undef = UINT_MAX; // position of the first undefined literal - interval_set_ref first_undef_set(m_ism); // infeasible region of the first undefined literal - interval_set * xk_set = m_infeasible[m_xk]; // current set of infeasible interval for current variable - SASSERT(!m_ism.is_full(xk_set)); - for (unsigned idx = 0; idx < cls.size(); ++idx) { - literal l = cls[idx]; - checkpoint(); - if (value(l) == l_false) - continue; - if (value(l) == l_true) - return true; // could happen if clause is a tautology - CTRACE("nlsat", max_var(l) != m_xk || value(l) != l_undef, display(tout); - tout << "xk: " << m_xk << ", max_var(l): " << max_var(l) << ", l: "; display(tout, l) << "\n"; - display(tout, cls) << "\n";); - SASSERT(value(l) == l_undef); - SASSERT(max_var(l) == m_xk); - bool_var b = l.var(); - atom * a = m_atoms[b]; - SASSERT(a != nullptr); - interval_set_ref curr_set(m_ism); - curr_set = m_evaluator.infeasible_intervals(a, l.sign(), &cls); - TRACE("nlsat_inf_set", tout << "infeasible set for literal: "; display(tout, l); tout << "\n"; m_ism.display(tout, curr_set); tout << "\n"; - display(tout, cls) << "\n";); - if (m_ism.is_empty(curr_set)) { - TRACE("nlsat_inf_set", tout << "infeasible set is empty, found literal\n";); - R_propagate(l, nullptr); - SASSERT(is_satisfied(cls)); - return true; - } - if (m_ism.is_full(curr_set)) { - TRACE("nlsat_inf_set", tout << "infeasible set is R, skip literal\n";); - R_propagate(~l, nullptr); - continue; - } - if (m_ism.subset(curr_set, xk_set)) { - TRACE("nlsat_inf_set", tout << "infeasible set is a subset of current set, found literal\n";); - R_propagate(l, xk_set); - return true; - } - interval_set_ref tmp(m_ism); - tmp = m_ism.mk_union(curr_set, xk_set); - if (m_ism.is_full(tmp)) { - TRACE("nlsat_inf_set", tout << "infeasible set + current set = R, skip literal\n"; - display(tout, cls) << "\n"; - m_ism.display(tout, tmp); tout << "\n"; - ); - R_propagate(~l, tmp, false); - continue; - } - num_undef++; - if (first_undef == UINT_MAX) { - first_undef = idx; - first_undef_set = curr_set; - } - } - TRACE("nlsat_inf_set", tout << "num_undef: " << num_undef << "\n";); - if (num_undef == 0) - return false; - SASSERT(first_undef != UINT_MAX); - if (num_undef == 1) { - // unit clause - assign(cls[first_undef], mk_clause_jst(&cls)); - updt_infeasible(first_undef_set); - } - else if ( satisfy_learned || - !cls.is_learned() /* must always satisfy input clauses */ || - m_lazy == 0 /* if not in lazy mode, we also satiffy lemmas */) { - decide(cls[first_undef]); - updt_infeasible(first_undef_set); - } - else { - TRACE("nlsat_lazy", tout << "skipping clause, satisfy_learned: " << satisfy_learned << ", cls.is_learned(): " << cls.is_learned() - << ", lazy: " << m_lazy << "\n";); - } - return true; - } - - /** - \brief Try to satisfy the given clause. Return true if succeeded. - - If satisfy_learned is true, then (arithmetic) learned clauses are satisfied even if m_lazy > 0 - */ - bool process_clause(clause const & cls, bool satisfy_learned) { - if (is_satisfied(cls)) - return true; - if (m_xk == null_var) - return process_boolean_clause(cls); - else - return process_arith_clause(cls, satisfy_learned); - } - - /** - \brief Try to satisfy the given "set" of clauses. - Return 0, if the set was satisfied, or the violating clause otherwise - */ - clause * process_clauses(clause_vector const & cs) { - for (clause* c : cs) { - if (!process_clause(*c, false)) - return c; - } - return nullptr; // succeeded - } - - /** - \brief Make sure m_bk is the first unassigned pure Boolean variable. - Set m_bk == null_bool_var if there is no unassigned pure Boolean variable. - */ - void peek_next_bool_var() { - while (m_bk < m_atoms.size()) { - if (!m_dead[m_bk] && m_atoms[m_bk] == nullptr && m_bvalues[m_bk] == l_undef) { - return; - } - m_bk++; - } - m_bk = null_bool_var; - } - - /** - \brief Create a new stage. See Dejan and Leo's paper. - */ - void new_stage() { - m_stats.m_stages++; - save_new_stage_trail(); - if (m_xk == null_var) - m_xk = 0; - else - m_xk++; - } - - /** - \brief Assign m_xk - */ - void select_witness() { - scoped_anum w(m_am); - SASSERT(!m_ism.is_full(m_infeasible[m_xk])); - m_ism.pick_in_complement(m_infeasible[m_xk], is_int(m_xk), w, m_randomize); - TRACE("nlsat", - tout << "infeasible intervals: "; m_ism.display(tout, m_infeasible[m_xk]); tout << "\n"; - tout << "assigning "; m_display_var(tout, m_xk) << "(x" << m_xk << ") -> " << w << "\n";); - TRACE("nlsat_root", tout << "value as root object: "; m_am.display_root(tout, w); tout << "\n";); - if (!m_am.is_rational(w)) - m_stats.m_irrational_assignments++; - m_assignment.set_core(m_xk, w); - } - - - - bool is_satisfied() { - if (m_bk == null_bool_var && m_xk >= num_vars()) { - TRACE("nlsat", tout << "found model\n"; display_assignment(tout);); - fix_patch(); - SASSERT(check_satisfied(m_clauses)); - return true; // all variables were assigned, and all clauses were satisfied. - } - else { - return false; - } - } - - - /** - \brief main procedure - */ - lbool search() { - TRACE("nlsat", tout << "starting search...\n"; display(tout); tout << "\nvar order:\n"; display_vars(tout);); - TRACE("nlsat_proof", tout << "ASSERTED\n"; display(tout);); - TRACE("nlsat_proof_sk", tout << "ASSERTED\n"; display_abst(tout);); - TRACE("nlsat_mathematica", display_mathematica(tout);); - TRACE("nlsat", display_smt2(tout);); - m_bk = 0; - m_xk = null_var; - - while (true) { - if (should_reorder()) - do_reorder(); - -#if 0 - if (should_gc()) - do_gc(); -#endif - - if (should_simplify()) - do_simplify(); - - CASSERT("nlsat", check_satisfied()); - if (m_xk == null_var) { - peek_next_bool_var(); - if (m_bk == null_bool_var) - new_stage(); // move to arith vars - } - else { - new_stage(); // peek next arith var - } - TRACE("nlsat_bug", tout << "xk: x" << m_xk << " bk: b" << m_bk << "\n";); - if (is_satisfied()) { - return l_true; - } - while (true) { - TRACE("nlsat_verbose", tout << "processing variable "; - if (m_xk != null_var) { - m_display_var(tout, m_xk); tout << " " << m_watches[m_xk].size(); - } - else { - tout << m_bwatches[m_bk].size() << " boolean b" << m_bk; - } - tout << "\n";); - checkpoint(); - clause * conflict_clause; - if (m_xk == null_var) - conflict_clause = process_clauses(m_bwatches[m_bk]); - else - conflict_clause = process_clauses(m_watches[m_xk]); - if (conflict_clause == nullptr) - break; - if (!resolve(*conflict_clause)) - return l_false; - if (m_stats.m_conflicts >= m_max_conflicts) - return l_undef; - log(); - } - - if (m_xk == null_var) { - if (m_bvalues[m_bk] == l_undef) { - decide(literal(m_bk, true)); - m_bk++; - } - } - else { - select_witness(); - } - } - } - - void gc() { - if (m_learned.size() <= 4*m_clauses.size()) - return; - reset_watches(); - reinit_cache(); - unsigned j = 0; - for (unsigned i = 0; i < m_learned.size(); ++i) { - auto cls = m_learned[i]; - if (i - j < m_clauses.size() && cls->size() > 1 && !cls->is_active()) - del_clause(cls); - else { - m_learned[j++] = cls; - cls->set_active(false); - } - } - m_learned.shrink(j); - reattach_arith_clauses(m_clauses); - reattach_arith_clauses(m_learned); - } - - - bool should_gc() { - return m_learned.size() > 10 * m_clauses.size(); - } - - void do_gc() { - undo_to_base(); - gc(); - } - - void undo_to_base() { - init_search(); - m_bk = 0; - m_xk = null_var; - } - - unsigned m_restart_threshold = 10000; - bool should_reorder() { - return m_stats.m_conflicts > 0 && m_stats.m_conflicts % m_restart_threshold == 0; - } - - void do_reorder() { - undo_to_base(); - m_stats.m_restarts++; - m_stats.m_conflicts++; - if (m_reordered) - restore_order(); - apply_reorder(); - } - - bool m_did_simplify = false; - bool should_simplify() { - return - !m_did_simplify && m_inline_vars && - !m_incremental && m_stats.m_conflicts > 100; - } - - void do_simplify() { - undo_to_base(); - m_did_simplify = true; - m_simplify(); - } - - unsigned m_next_conflict = 100; - void log() { - if (m_stats.m_conflicts != 1 && m_stats.m_conflicts < m_next_conflict) - return; - m_next_conflict += 100; - IF_VERBOSE(2, verbose_stream() << "(nlsat :conflicts " << m_stats.m_conflicts - << " :decisions " << m_stats.m_decisions - << " :propagations " << m_stats.m_propagations - << " :clauses " << m_clauses.size() - << " :learned " << m_learned.size() << ")\n"); - } - - - lbool search_check() { - lbool r = l_undef; - m_stats.m_conflicts = 0; - m_stats.m_restarts = 0; - m_next_conflict = 0; - while (true) { - r = search(); - if (r != l_true) - break; - ++m_stats.m_restarts; - vector> bounds; - - for (var x = 0; x < num_vars(); x++) { - if (is_int(x) && m_assignment.is_assigned(x) && !m_am.is_int(m_assignment.value(x))) { - scoped_anum v(m_am), vlo(m_am); - v = m_assignment.value(x); - rational lo; - m_am.int_lt(v, vlo); - if (!m_am.is_int(vlo)) - continue; - m_am.to_rational(vlo, lo); - // derive tight bounds. - while (true) { - lo++; - if (!m_am.gt(v, lo.to_mpq())) { - lo--; - break; - } - } - bounds.push_back(std::make_pair(x, lo)); - } - } - if (bounds.empty()) - break; - - gc(); - if (m_stats.m_restarts % 10 == 0) { - if (m_reordered) - restore_order(); - apply_reorder(); - } - - init_search(); - IF_VERBOSE(2, verbose_stream() << "(nlsat-b&b :conflicts " << m_stats.m_conflicts - << " :decisions " << m_stats.m_decisions - << " :propagations " << m_stats.m_propagations - << " :clauses " << m_clauses.size() - << " :learned " << m_learned.size() << ")\n"); - for (auto const& b : bounds) { - var x = b.first; - rational lo = b.second; - rational hi = lo + 1; // rational::one(); - bool is_even = false; - polynomial_ref p(m_pm); - rational one(1); - m_lemma.reset(); - p = m_pm.mk_linear(1, &one, &x, -lo); - poly* p1 = p.get(); - m_lemma.push_back(~mk_ineq_literal(atom::GT, 1, &p1, &is_even)); - p = m_pm.mk_linear(1, &one, &x, -hi); - poly* p2 = p.get(); - m_lemma.push_back(~mk_ineq_literal(atom::LT, 1, &p2, &is_even)); - - // perform branch and bound - clause * cls = mk_clause(m_lemma.size(), m_lemma.data(), true, nullptr); - IF_VERBOSE(4, display(verbose_stream(), *cls) << "\n"); - if (cls) { - TRACE("nlsat", display(tout << "conflict " << lo << " " << hi, *cls); tout << "\n";); - } - } - } - return r; - } - - bool m_reordered = false; - bool simple_check() { - literal_vector learned_unit; - simple_checker checker(m_pm, m_am, m_clauses, learned_unit, m_atoms, m_is_int.size()); - if (!checker()) - return false; - for (unsigned i = 0, sz = learned_unit.size(); i < sz; ++i) { - clause *cla = mk_clause(1, &learned_unit[i], true, nullptr); - if (m_atoms[learned_unit[i].var()] == nullptr) { - assign(learned_unit[i], mk_clause_jst(cla)); - } - } - return true; - } - - - void run_variable_ordering_strategy() { - TRACE("reorder", tout << "runing vos: " << m_variable_ordering_strategy << '\n';); - - unsigned num = num_vars(); - vos_var_info_collector vos_collector(m_pm, m_atoms, num, m_variable_ordering_strategy); - vos_collector.collect(m_clauses); - vos_collector.collect(m_learned); - - var_vector perm; - vos_collector(perm); - reorder(perm.size(), perm.data()); - } - - void apply_reorder() { - m_reordered = false; - if (!can_reorder()) - ; - else if (m_random_order) { - shuffle_vars(); - m_reordered = true; - } - else if (m_reorder) { - heuristic_reorder(); - m_reordered = true; - } - } - - lbool check() { - - if (m_simple_check) { - if (!simple_check()) { - TRACE("simple_check", tout << "real unsat\n";); - return l_false; - } - TRACE("simple_checker_learned", - tout << "simple check done\n"; - ); - } - - TRACE("nlsat_smt2", display_smt2(tout);); - TRACE("nlsat_fd", tout << "is_full_dimensional: " << is_full_dimensional() << "\n";); - init_search(); - m_explain.set_full_dimensional(is_full_dimensional()); - bool reordered = false; - - - if (!can_reorder()) { - - } - else if (m_variable_ordering_strategy > 0) { - run_variable_ordering_strategy(); - reordered = true; - } - else if (m_random_order) { - shuffle_vars(); - reordered = true; - } - else if (m_reorder) { - heuristic_reorder(); - reordered = true; - } - sort_watched_clauses(); - lbool r = search_check(); - CTRACE("nlsat_model", r == l_true, tout << "model before restore order\n"; display_assignment(tout);); - if (reordered) { - restore_order(); - } - CTRACE("nlsat_model", r == l_true, tout << "model\n"; display_assignment(tout);); - CTRACE("nlsat", r == l_false, display(tout << "unsat\n");); - SASSERT(r != l_true || check_satisfied(m_clauses)); - return r; - } - - void init_search() { - undo_until_empty(); - while (m_scope_lvl > 0) { - undo_new_level(); - } - m_xk = null_var; - for (unsigned i = 0; i < m_bvalues.size(); ++i) { - m_bvalues[i] = l_undef; - } - m_assignment.reset(); - } - - lbool check(literal_vector& assumptions) { - literal_vector result; - unsigned sz = assumptions.size(); - literal const* ptr = assumptions.data(); - for (unsigned i = 0; i < sz; ++i) { - mk_external_clause(1, ptr+i, (assumption)(ptr+i)); - } - display_literal_assumption dla(*this, assumptions); - scoped_display_assumptions _scoped_display(*this, dla); - lbool r = check(); - - if (r == l_false) { - // collect used literals from m_lemma_assumptions - vector deps; - get_core(deps); - for (unsigned i = 0; i < deps.size(); ++i) { - literal const* lp = (literal const*)(deps[i]); - if (ptr <= lp && lp < ptr + sz) { - result.push_back(*lp); - } - } - } - collect(assumptions, m_clauses); - collect(assumptions, m_learned); - del_clauses(m_valids); - if (m_check_lemmas) { - for (clause* c : m_learned) { - check_lemma(c->size(), c->data(), false, nullptr); - } - } - -#if 0 - for (clause* c : m_learned) { - IF_VERBOSE(0, display(verbose_stream() << "KEEP: ", c->size(), c->c_ptr()) << "\n"); - } -#endif - assumptions.reset(); - assumptions.append(result); - return r; - } - - void get_core(vector& deps) { - m_asm.linearize(m_lemma_assumptions.get(), deps); - } - - void collect(literal_vector const& assumptions, clause_vector& clauses) { - unsigned j = 0; - for (clause * c : clauses) { - if (collect(assumptions, *c)) { - del_clause(c); - } - else { - clauses[j++] = c; - } - } - clauses.shrink(j); - } - - bool collect(literal_vector const& assumptions, clause const& c) { - unsigned sz = assumptions.size(); - literal const* ptr = assumptions.data(); - _assumption_set asms = static_cast<_assumption_set>(c.assumptions()); - if (asms == nullptr) { - return false; - } - vector deps; - m_asm.linearize(asms, deps); - for (auto dep : deps) { - if (ptr <= dep && dep < ptr + sz) { - return true; - } - } - return false; - } - - // ----------------------- - // - // Conflict Resolution - // - // ----------------------- - svector m_marks; // bool_var -> bool temp mark used during conflict resolution - unsigned m_num_marks; - scoped_literal_vector m_lemma; - scoped_literal_vector m_lazy_clause; - assumption_set_ref m_lemma_assumptions; // assumption tracking - - // Conflict resolution invariant: a marked literal is in m_lemma or on the trail stack. - - bool check_marks() { - for (unsigned m : m_marks) { - (void)m; - SASSERT(m == 0); - } - return true; - } - - unsigned scope_lvl() const { return m_scope_lvl; } - - bool is_marked(bool_var b) const { return m_marks.get(b, 0) == 1; } - - void mark(bool_var b) { m_marks.setx(b, 1, 0); } - - void reset_mark(bool_var b) { m_marks[b] = 0; } - - void reset_marks() { - for (auto const& l : m_lemma) { - reset_mark(l.var()); - } - } - - void process_antecedent(literal antecedent) { - checkpoint(); - bool_var b = antecedent.var(); - TRACE("nlsat_resolve", display(tout << "resolving antecedent: ", antecedent) << "\n";); - if (assigned_value(antecedent) == l_undef) { - checkpoint(); - // antecedent must be false in the current arith interpretation - SASSERT(value(antecedent) == l_false || m_rlimit.is_canceled()); - if (!is_marked(b)) { - SASSERT(is_arith_atom(b) && max_var(b) < m_xk); // must be in a previous stage - TRACE("nlsat_resolve", tout << "literal is unassigned, but it is false in arithmetic interpretation, adding it to lemma\n";); - mark(b); - m_lemma.push_back(antecedent); - } - return; - } - - unsigned b_lvl = m_levels[b]; - TRACE("nlsat_resolve", tout << "b_lvl: " << b_lvl << ", is_marked(b): " << is_marked(b) << ", m_num_marks: " << m_num_marks << "\n";); - if (!is_marked(b)) { - mark(b); - if (b_lvl == scope_lvl() /* same level */ && max_var(b) == m_xk /* same stage */) { - TRACE("nlsat_resolve", tout << "literal is in the same level and stage, increasing marks\n";); - m_num_marks++; - } - else { - TRACE("nlsat_resolve", tout << "previous level or stage, adding literal to lemma\n"; - tout << "max_var(b): " << max_var(b) << ", m_xk: " << m_xk << ", lvl: " << b_lvl << ", scope_lvl: " << scope_lvl() << "\n";); - m_lemma.push_back(antecedent); - } - } - } - - void resolve_clause(bool_var b, unsigned sz, literal const * c) { - TRACE("nlsat_proof", tout << "resolving "; if (b != null_bool_var) display_atom(tout, b) << "\n"; display(tout, sz, c); tout << "\n";); - TRACE("nlsat_proof_sk", tout << "resolving "; if (b != null_bool_var) tout << "b" << b; tout << "\n"; display_abst(tout, sz, c); tout << "\n";); - - for (unsigned i = 0; i < sz; i++) { - if (c[i].var() != b) - process_antecedent(c[i]); - } - } - - void resolve_clause(bool_var b, clause & c) { - TRACE("nlsat_resolve", tout << "resolving clause "; if (b != null_bool_var) tout << "for b: " << b << "\n"; display(tout, c) << "\n";); - c.set_active(true); - resolve_clause(b, c.size(), c.data()); - m_lemma_assumptions = m_asm.mk_join(static_cast<_assumption_set>(c.assumptions()), m_lemma_assumptions); - } - - void resolve_lazy_justification(bool_var b, lazy_justification const & jst) { - TRACE("nlsat_resolve", tout << "resolving lazy_justification for b" << b << "\n";); - unsigned sz = jst.num_lits(); - - // Dump lemma as Mathematica formula that must be true, - // if the current interpretation (really) makes the core in jst infeasible. - TRACE("nlsat_mathematica", - tout << "assignment lemma\n"; - literal_vector core; - for (unsigned i = 0; i < sz; i++) { - core.push_back(~jst.lit(i)); - } - display_mathematica_lemma(tout, core.size(), core.data(), true);); - - m_lazy_clause.reset(); - m_explain(jst.num_lits(), jst.lits(), m_lazy_clause); - for (unsigned i = 0; i < sz; i++) - m_lazy_clause.push_back(~jst.lit(i)); - - // lazy clause is a valid clause - TRACE("nlsat_mathematica", display_mathematica_lemma(tout, m_lazy_clause.size(), m_lazy_clause.data());); - TRACE("nlsat_proof_sk", tout << "theory lemma\n"; display_abst(tout, m_lazy_clause.size(), m_lazy_clause.data()); tout << "\n";); - TRACE("nlsat_resolve", - tout << "m_xk: " << m_xk << ", "; m_display_var(tout, m_xk) << "\n"; - tout << "new valid clause:\n"; - display(tout, m_lazy_clause.size(), m_lazy_clause.data()) << "\n";); - - - if (m_log_lemmas) - log_lemma(verbose_stream(), m_lazy_clause.size(), m_lazy_clause.data(), true); - - if (m_check_lemmas) { - check_lemma(m_lazy_clause.size(), m_lazy_clause.data(), true, nullptr); - m_valids.push_back(mk_clause_core(m_lazy_clause.size(), m_lazy_clause.data(), false, nullptr)); - } - -#ifdef Z3DEBUG - { - unsigned sz = m_lazy_clause.size(); - for (unsigned i = 0; i < sz; i++) { - literal l = m_lazy_clause[i]; - if (l.var() != b) { - if (value(l) != l_false) - display(verbose_stream() << value(l) << " ", 1, &l); - SASSERT(value(l) == l_false || m_rlimit.is_canceled()); - } - else { - SASSERT(value(l) == l_true || m_rlimit.is_canceled()); - SASSERT(!l.sign() || m_bvalues[b] == l_false); - SASSERT(l.sign() || m_bvalues[b] == l_true); - } - } - } -#endif - checkpoint(); - resolve_clause(b, m_lazy_clause.size(), m_lazy_clause.data()); - - for (unsigned i = 0; i < jst.num_clauses(); ++i) { - clause const& c = jst.clause(i); - TRACE("nlsat", display(tout << "adding clause assumptions ", c) << "\n";); - m_lemma_assumptions = m_asm.mk_join(static_cast<_assumption_set>(c.assumptions()), m_lemma_assumptions); - } - } - - /** - \brief Return true if all literals in ls are from previous stages. - */ - bool only_literals_from_previous_stages(unsigned num, literal const * ls) const { - for (unsigned i = 0; i < num; i++) { - if (max_var(ls[i]) == m_xk) - return false; - } - return true; - } - - /** - \brief Return the maximum scope level in ls. - - \pre This method assumes value(ls[i]) is l_false for i in [0, num) - */ - unsigned max_scope_lvl(unsigned num, literal const * ls) { - unsigned max = 0; - for (unsigned i = 0; i < num; i++) { - literal l = ls[i]; - bool_var b = l.var(); - SASSERT(value(ls[i]) == l_false); - if (assigned_value(l) == l_false) { - unsigned lvl = m_levels[b]; - if (lvl > max) - max = lvl; - } - else { - // l must be a literal from a previous stage that is false in the current interpretation - SASSERT(assigned_value(l) == l_undef); - SASSERT(max_var(b) != null_var); - SASSERT(m_xk != null_var); - SASSERT(max_var(b) < m_xk); - } - } - return max; - } - - /** - \brief Remove literals of the given lvl (that are in the current stage) from lemma. - - \pre This method assumes value(ls[i]) is l_false for i in [0, num) - */ - void remove_literals_from_lvl(scoped_literal_vector & lemma, unsigned lvl) { - TRACE("nlsat_resolve", tout << "removing literals from lvl: " << lvl << " and stage " << m_xk << "\n";); - unsigned sz = lemma.size(); - unsigned j = 0; - for (unsigned i = 0; i < sz; i++) { - literal l = lemma[i]; - bool_var b = l.var(); - SASSERT(is_marked(b)); - SASSERT(value(lemma[i]) == l_false); - if (assigned_value(l) == l_false && m_levels[b] == lvl && max_var(b) == m_xk) { - m_num_marks++; - continue; - } - lemma.set(j, l); - j++; - } - lemma.shrink(j); - } - - /** - \brief Return true if it is a Boolean lemma. - */ - bool is_bool_lemma(unsigned sz, literal const * ls) const { - for (unsigned i = 0; i < sz; i++) { - if (m_atoms[ls[i].var()] != nullptr) - return false; - } - return true; - } - - - /** - Return the maximal decision level in lemma for literals in the first sz-1 positions that - are at the same stage. If all these literals are from previous stages, - we just backtrack the current level. - */ - unsigned find_new_level_arith_lemma(unsigned sz, literal const * lemma) { - SASSERT(!is_bool_lemma(sz, lemma)); - unsigned new_lvl = 0; - bool found_lvl = false; - for (unsigned i = 0; i < sz - 1; i++) { - literal l = lemma[i]; - if (max_var(l) == m_xk) { - bool_var b = l.var(); - if (!found_lvl) { - found_lvl = true; - new_lvl = m_levels[b]; - } - else { - if (m_levels[b] > new_lvl) - new_lvl = m_levels[b]; - } - } - } - SASSERT(!found_lvl || new_lvl < scope_lvl()); - if (!found_lvl) { - TRACE("nlsat_resolve", tout << "fail to find new lvl, using previous one\n";); - new_lvl = scope_lvl() - 1; - } - return new_lvl; - } - - struct scoped_reset_marks { - imp& i; - scoped_reset_marks(imp& i):i(i) {} - ~scoped_reset_marks() { if (i.m_num_marks > 0) { i.m_num_marks = 0; for (char& m : i.m_marks) m = 0; } } - }; - - - /** - \brief Return true if the conflict was solved. - */ - bool resolve(clause & conflict) { - clause * conflict_clause = &conflict; - m_lemma_assumptions = nullptr; - start: - SASSERT(check_marks()); - TRACE("nlsat_proof", tout << "STARTING RESOLUTION\n";); - TRACE("nlsat_proof_sk", tout << "STARTING RESOLUTION\n";); - m_stats.m_conflicts++; - TRACE("nlsat", tout << "resolve, conflicting clause:\n"; display(tout, *conflict_clause) << "\n"; - tout << "xk: "; if (m_xk != null_var) m_display_var(tout, m_xk); else tout << ""; tout << "\n"; - tout << "scope_lvl: " << scope_lvl() << "\n"; - tout << "current assignment\n"; display_assignment(tout);); - - m_num_marks = 0; - m_lemma.reset(); - m_lemma_assumptions = nullptr; - scoped_reset_marks _sr(*this); - resolve_clause(null_bool_var, *conflict_clause); - - unsigned top = m_trail.size(); - bool found_decision; - while (true) { - found_decision = false; - while (m_num_marks > 0) { - checkpoint(); - SASSERT(top > 0); - trail & t = m_trail[top-1]; - SASSERT(t.m_kind != trail::NEW_STAGE); // we only mark literals that are in the same stage - if (t.m_kind == trail::BVAR_ASSIGNMENT) { - bool_var b = t.m_b; - if (is_marked(b)) { - TRACE("nlsat_resolve", tout << "found marked: b" << b << "\n"; display_atom(tout, b) << "\n";); - m_num_marks--; - reset_mark(b); - justification jst = m_justifications[b]; - switch (jst.get_kind()) { - case justification::CLAUSE: - resolve_clause(b, *(jst.get_clause())); - break; - case justification::LAZY: - resolve_lazy_justification(b, *(jst.get_lazy())); - break; - case justification::DECISION: - SASSERT(m_num_marks == 0); - found_decision = true; - TRACE("nlsat_resolve", tout << "found decision\n";); - m_lemma.push_back(literal(b, m_bvalues[b] == l_true)); - break; - default: - UNREACHABLE(); - break; - } - } - } - top--; - } - - // m_lemma is an implicating clause after backtracking current scope level. - if (found_decision) - break; - - // If lemma only contains literals from previous stages, then we can stop. - // We make progress by returning to a previous stage with additional information (new lemma) - // that forces us to select a new partial interpretation - if (only_literals_from_previous_stages(m_lemma.size(), m_lemma.data())) - break; - - // Conflict does not depend on the current decision, and it is still in the current stage. - // We should find - // - the maximal scope level in the lemma - // - remove literal assigned in the scope level from m_lemma - // - backtrack to this level - // - and continue conflict resolution from there - // - we must bump m_num_marks for literals removed from m_lemma - unsigned max_lvl = max_scope_lvl(m_lemma.size(), m_lemma.data()); - TRACE("nlsat_resolve", tout << "conflict does not depend on current decision, backtracking to level: " << max_lvl << "\n";); - SASSERT(max_lvl < scope_lvl()); - remove_literals_from_lvl(m_lemma, max_lvl); - undo_until_level(max_lvl); - top = m_trail.size(); - TRACE("nlsat_resolve", tout << "scope_lvl: " << scope_lvl() << " num marks: " << m_num_marks << "\n";); - SASSERT(scope_lvl() == max_lvl); - } - - TRACE("nlsat_proof", tout << "New lemma\n"; display(tout, m_lemma); tout << "\n=========================\n";); - TRACE("nlsat_proof_sk", tout << "New lemma\n"; display_abst(tout, m_lemma); tout << "\n=========================\n";); - - if (m_lemma.empty()) { - TRACE("nlsat", tout << "empty clause generated\n";); - return false; // problem is unsat, empty clause was generated - } - - reset_marks(); // remove marks from the literals in m_lemmas. - TRACE("nlsat", tout << "new lemma:\n"; display(tout, m_lemma.size(), m_lemma.data()); tout << "\n"; - tout << "found_decision: " << found_decision << "\n";); - - if (m_check_lemmas) { - check_lemma(m_lemma.size(), m_lemma.data(), false, m_lemma_assumptions.get()); - } - - if (m_log_lemmas) - log_lemma(verbose_stream(), m_lemma.size(), m_lemma.data(), false); - - // There are two possibilities: - // 1) m_lemma contains only literals from previous stages, and they - // are false in the current interpretation. We make progress - // by returning to a previous stage with additional information (new clause) - // that forces us to select a new partial interpretation - // >>> Return to some previous stage (we may also backjump many decisions and stages). - // - // 2) m_lemma contains at most one literal from the current level (the last literal). - // Moreover, this literal was a decision, but the new lemma forces it to - // be assigned to a different value. - // >>> In this case, we remain in the same stage but, we add a new asserted literal - // in a previous scope level. We may backjump many decisions. - // - unsigned sz = m_lemma.size(); - clause * new_cls = nullptr; - if (!found_decision) { - // Case 1) - // We just have to find the maximal variable in m_lemma, and return to that stage - // Remark: the lemma may contain only boolean literals, in this case new_max_var == null_var; - var new_max_var = max_var(sz, m_lemma.data()); - TRACE("nlsat_resolve", tout << "backtracking to stage: " << new_max_var << ", curr: " << m_xk << "\n";); - undo_until_stage(new_max_var); - SASSERT(m_xk == new_max_var); - new_cls = mk_clause(sz, m_lemma.data(), true, m_lemma_assumptions.get()); - TRACE("nlsat", tout << "new_level: " << scope_lvl() << "\nnew_stage: " << new_max_var << "\n"; - if (new_max_var != null_var) m_display_var(tout, new_max_var) << "\n";); - } - else { - SASSERT(scope_lvl() >= 1); - // Case 2) - if (is_bool_lemma(m_lemma.size(), m_lemma.data())) { - // boolean lemma, we just backtrack until the last literal is unassigned. - bool_var max_bool_var = m_lemma[m_lemma.size()-1].var(); - undo_until_unassigned(max_bool_var); - } - else { - // We must find the maximal decision level in literals in the first sz-1 positions that - // are at the same stage. If all these literals are from previous stages, - // we just backtrack the current level. - unsigned new_lvl = find_new_level_arith_lemma(m_lemma.size(), m_lemma.data()); - TRACE("nlsat", tout << "backtracking to new level: " << new_lvl << ", curr: " << m_scope_lvl << "\n";); - undo_until_level(new_lvl); - } - - if (lemma_is_clause(*conflict_clause)) { - TRACE("nlsat", tout << "found decision literal in conflict clause\n";); - VERIFY(process_clause(*conflict_clause, true)); - return true; - } - new_cls = mk_clause(sz, m_lemma.data(), true, m_lemma_assumptions.get()); - } - NLSAT_VERBOSE(display(verbose_stream(), *new_cls) << "\n";); - if (!process_clause(*new_cls, true)) { - TRACE("nlsat", tout << "new clause triggered another conflict, restarting conflict resolution...\n"; - display(tout, *new_cls) << "\n"; - ); - // we are still in conflict - conflict_clause = new_cls; - goto start; - } - TRACE("nlsat_resolve_done", display_assignment(tout);); - return true; - } - - bool lemma_is_clause(clause const& cls) const { - bool same = (m_lemma.size() == cls.size()); - for (unsigned i = 0; same && i < m_lemma.size(); ++i) { - same = m_lemma[i] == cls[i]; - } - return same; - } - - - // ----------------------- - // - // Debugging - // - // ----------------------- - - bool check_watches() const { -#ifdef Z3DEBUG - for (var x = 0; x < num_vars(); x++) { - clause_vector const & cs = m_watches[x]; - unsigned sz = cs.size(); - for (unsigned i = 0; i < sz; i++) { - SASSERT(max_var(*(cs[i])) == x); - } - } -#endif - return true; - } - - bool check_bwatches() const { -#ifdef Z3DEBUG - for (bool_var b = 0; b < m_bwatches.size(); b++) { - clause_vector const & cs = m_bwatches[b]; - unsigned sz = cs.size(); - for (unsigned i = 0; i < sz; i++) { - clause const & c = *(cs[i]); - SASSERT(max_var(c) == null_var); - SASSERT(max_bvar(c) == b); - } - } -#endif - return true; - } - - bool check_invariant() const { - SASSERT(check_watches()); - SASSERT(check_bwatches()); - return true; - } - - bool check_satisfied(clause_vector const & cs) const { - unsigned sz = cs.size(); - for (unsigned i = 0; i < sz; i++) { - clause const & c = *(cs[i]); - if (!is_satisfied(c)) { - TRACE("nlsat", tout << "not satisfied\n"; display(tout, c); tout << "\n";); - return false; - } - } - return true; - } - - bool check_satisfied() const { - TRACE("nlsat", tout << "bk: b" << m_bk << ", xk: x" << m_xk << "\n"; if (m_xk != null_var) { m_display_var(tout, m_xk); tout << "\n"; }); - unsigned num = m_atoms.size(); - if (m_bk != null_bool_var) - num = m_bk; - for (bool_var b = 0; b < num; b++) { - if (!check_satisfied(m_bwatches[b])) { - UNREACHABLE(); - return false; - } - } - if (m_xk != null_var) { - for (var x = 0; x < m_xk; x++) { - if (!check_satisfied(m_watches[x])) { - UNREACHABLE(); - return false; - } - } - } - return true; - } - - // ----------------------- - // - // Statistics - // - // ----------------------- - - void collect_statistics(statistics & st) { - st.update("nlsat conflicts", m_stats.m_conflicts); - st.update("nlsat propagations", m_stats.m_propagations); - st.update("nlsat decisions", m_stats.m_decisions); - st.update("nlsat restarts", m_stats.m_restarts); - st.update("nlsat stages", m_stats.m_stages); - st.update("nlsat simplifications", m_stats.m_simplifications); - st.update("nlsat irrational assignments", m_stats.m_irrational_assignments); - } - - void reset_statistics() { - m_stats.reset(); - } - - // ----------------------- - // - // Variable reordering - // - // ----------------------- - - struct var_info_collector { - pmanager & pm; - atom_vector const & m_atoms; - var_vector m_shuffle; - unsigned_vector m_max_degree; - unsigned_vector m_num_occs; - - var_info_collector(pmanager & _pm, atom_vector const & atoms, unsigned num_vars): - pm(_pm), - m_atoms(atoms) { - m_max_degree.resize(num_vars, 0); - m_num_occs.resize(num_vars, 0); - } - - var_vector m_vars; - void collect(poly * p) { - m_vars.reset(); - pm.vars(p, m_vars); - unsigned sz = m_vars.size(); - for (unsigned i = 0; i < sz; i++) { - var x = m_vars[i]; - unsigned k = pm.degree(p, x); - m_num_occs[x]++; - if (k > m_max_degree[x]) - m_max_degree[x] = k; - } - } - - void collect(literal l) { - bool_var b = l.var(); - atom * a = m_atoms[b]; - if (a == nullptr) - return; - if (a->is_ineq_atom()) { - unsigned sz = to_ineq_atom(a)->size(); - for (unsigned i = 0; i < sz; i++) { - collect(to_ineq_atom(a)->p(i)); - } - } - else { - collect(to_root_atom(a)->p()); - } - } - - void collect(clause const & c) { - unsigned sz = c.size(); - for (unsigned i = 0; i < sz; i++) - collect(c[i]); - } - - void collect(clause_vector const & cs) { - unsigned sz = cs.size(); - for (unsigned i = 0; i < sz; i++) - collect(*(cs[i])); - } - - std::ostream& display(std::ostream & out, display_var_proc const & proc) { - unsigned sz = m_num_occs.size(); - for (unsigned i = 0; i < sz; i++) { - proc(out, i); out << " -> " << m_max_degree[i] << " : " << m_num_occs[i] << "\n"; - } - return out; - } - }; - - struct reorder_lt { - var_info_collector const & m_info; - reorder_lt(var_info_collector const & info):m_info(info) {} - bool operator()(var x, var y) const { - // high degree first - if (m_info.m_max_degree[x] < m_info.m_max_degree[y]) - return false; - if (m_info.m_max_degree[x] > m_info.m_max_degree[y]) - return true; - // more constrained first - if (m_info.m_num_occs[x] < m_info.m_num_occs[y]) - return false; - if (m_info.m_num_occs[x] > m_info.m_num_occs[y]) - return true; - return m_info.m_shuffle[x] < m_info.m_shuffle[y]; - } - }; - - // Order variables by degree and number of occurrences - void heuristic_reorder() { - unsigned num = num_vars(); - var_info_collector collector(m_pm, m_atoms, num); - collector.collect(m_clauses); - collector.collect(m_learned); - init_shuffle(collector.m_shuffle); - TRACE("nlsat_reorder", collector.display(tout, m_display_var);); - var_vector new_order; - for (var x = 0; x < num; x++) - new_order.push_back(x); - - std::sort(new_order.begin(), new_order.end(), reorder_lt(collector)); - TRACE("nlsat_reorder", - tout << "new order: "; for (unsigned i = 0; i < num; i++) tout << new_order[i] << " "; tout << "\n";); - var_vector perm; - perm.resize(num, 0); - for (var x = 0; x < num; x++) { - perm[new_order[x]] = x; - } - reorder(perm.size(), perm.data()); - SASSERT(check_invariant()); - } - - void init_shuffle(var_vector& p) { - unsigned num = num_vars(); - for (var x = 0; x < num; x++) - p.push_back(x); - - random_gen r(++m_random_seed); - shuffle(p.size(), p.data(), r); - } - - void shuffle_vars() { - var_vector p; - init_shuffle(p); - reorder(p.size(), p.data()); - } - - bool can_reorder() const { - return all_of(m_learned, [&](clause* c) { return !has_root_atom(*c); }) - && all_of(m_clauses, [&](clause* c) { return !has_root_atom(*c); }); - } - - /** - \brief Reorder variables using the giving permutation. - p maps internal variables to their new positions - */ - - - void reorder(unsigned sz, var const * p) { - - remove_learned_roots(); - SASSERT(can_reorder()); - TRACE("nlsat_reorder", tout << "solver before variable reorder\n"; display(tout); - display_vars(tout); - tout << "\npermutation:\n"; - for (unsigned i = 0; i < sz; i++) tout << p[i] << " "; tout << "\n"; - ); - // verbose_stream() << "\npermutation: " << p[0] << " count " << count << " " << m_rlimit.is_canceled() << "\n"; - reinit_cache(); - SASSERT(num_vars() == sz); - TRACE("nlsat_bool_assignment_bug", tout << "before reset watches\n"; display_bool_assignment(tout);); - reset_watches(); - assignment new_assignment(m_am); - for (var x = 0; x < num_vars(); x++) { - if (m_assignment.is_assigned(x)) - new_assignment.set(p[x], m_assignment.value(x)); - } - var_vector new_inv_perm; - new_inv_perm.resize(sz); - // the undo_until_size(0) statement erases the Boolean assignment. - // undo_until_size(0) - undo_until_stage(null_var); - m_cache.reset(); -#ifdef Z3DEBUG - for (var x = 0; x < num_vars(); x++) { - SASSERT(m_watches[x].empty()); - } -#endif - // update m_perm mapping - for (unsigned ext_x = 0; ext_x < sz; ext_x++) { - // p: internal -> new pos - // m_perm: internal -> external - // m_inv_perm: external -> internal - new_inv_perm[ext_x] = p[m_inv_perm[ext_x]]; - m_perm.set(new_inv_perm[ext_x], ext_x); - } - bool_vector is_int; - is_int.swap(m_is_int); - for (var x = 0; x < sz; x++) { - m_is_int.setx(p[x], is_int[x], false); - SASSERT(m_infeasible[x] == 0); - } - m_inv_perm.swap(new_inv_perm); -#ifdef Z3DEBUG - for (var x = 0; x < num_vars(); x++) { - SASSERT(x == m_inv_perm[m_perm[x]]); - SASSERT(m_watches[x].empty()); - } -#endif - m_pm.rename(sz, p); - for (auto& b : m_bounds) - b.x = p[b.x]; - TRACE("nlsat_bool_assignment_bug", tout << "before reinit cache\n"; display_bool_assignment(tout);); - reinit_cache(); - m_assignment.swap(new_assignment); - reattach_arith_clauses(m_clauses); - reattach_arith_clauses(m_learned); - TRACE("nlsat_reorder", tout << "solver after variable reorder\n"; display(tout); display_vars(tout);); - } - - - /** - \brief Restore variable order. - */ - void restore_order() { - // m_perm: internal -> external - // m_inv_perm: external -> internal - var_vector p; - p.append(m_perm); - reorder(p.size(), p.data()); -#ifdef Z3DEBUG - for (var x = 0; x < num_vars(); x++) { - SASSERT(m_perm[x] == x); - SASSERT(m_inv_perm[x] == x); - } -#endif - } - - /** - \brief After variable reordering some lemmas containing root atoms may be ill-formed. - */ - void remove_learned_roots() { - unsigned j = 0; - for (clause* c : m_learned) { - if (has_root_atom(*c)) { - del_clause(c); - } - else { - m_learned[j++] = c; - } - } - m_learned.shrink(j); - } - - /** - \brief Return true if the clause contains an ill formed root atom - */ - bool has_root_atom(clause const & c) const { - for (literal lit : c) { - bool_var b = lit.var(); - atom * a = m_atoms[b]; - if (a && a->is_root_atom()) - return true; - } - return false; - } - - /** - \brief reinsert all polynomials in the unique cache - */ - void reinit_cache() { - reinit_cache(m_clauses); - reinit_cache(m_learned); - for (atom* a : m_atoms) - reinit_cache(a); - } - void reinit_cache(clause_vector const & cs) { - for (clause* c : cs) - reinit_cache(*c); - } - void reinit_cache(clause const & c) { - for (literal l : c) - reinit_cache(l); - } - void reinit_cache(literal l) { - bool_var b = l.var(); - reinit_cache(m_atoms[b]); - } - void reinit_cache(atom* a) { - if (a == nullptr) { - - } - else if (a->is_ineq_atom()) { - var max = 0; - unsigned sz = to_ineq_atom(a)->size(); - for (unsigned i = 0; i < sz; i++) { - poly * p = to_ineq_atom(a)->p(i); - VERIFY(m_cache.mk_unique(p) == p); - var x = m_pm.max_var(p); - if (x > max) - max = x; - } - a->m_max_var = max; - } - else { - poly * p = to_root_atom(a)->p(); - VERIFY(m_cache.mk_unique(p) == p); - a->m_max_var = m_pm.max_var(p); - } - } - - void reset_watches() { - unsigned num = num_vars(); - for (var x = 0; x < num; x++) { - m_watches[x].reset(); - } - } - - void reattach_arith_clauses(clause_vector const & cs) { - for (clause* cp : cs) { - var x = max_var(*cp); - if (x != null_var) - m_watches[x].push_back(cp); - } - } - - // ----------------------- - // - // Solver initialization - // - // ----------------------- - - struct degree_lt { - unsigned_vector & m_degrees; - degree_lt(unsigned_vector & ds):m_degrees(ds) {} - bool operator()(unsigned i1, unsigned i2) const { - if (m_degrees[i1] < m_degrees[i2]) - return true; - if (m_degrees[i1] > m_degrees[i2]) - return false; - return i1 < i2; - } - }; - - unsigned_vector m_cs_degrees; - unsigned_vector m_cs_p; - void sort_clauses_by_degree(unsigned sz, clause ** cs) { - if (sz <= 1) - return; - TRACE("nlsat_reorder_clauses", tout << "before:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); - m_cs_degrees.reset(); - m_cs_p.reset(); - for (unsigned i = 0; i < sz; i++) { - m_cs_p.push_back(i); - m_cs_degrees.push_back(degree(*(cs[i]))); - } - std::sort(m_cs_p.begin(), m_cs_p.end(), degree_lt(m_cs_degrees)); - TRACE("nlsat_reorder_clauses", tout << "permutation: "; ::display(tout, m_cs_p.begin(), m_cs_p.end()); tout << "\n";); - apply_permutation(sz, cs, m_cs_p.data()); - TRACE("nlsat_reorder_clauses", tout << "after:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); - } - - - struct degree_lit_num_lt { - unsigned_vector & m_degrees; - unsigned_vector & m_lit_num; - degree_lit_num_lt(unsigned_vector & ds, unsigned_vector & ln) : - m_degrees(ds), - m_lit_num(ln) { - } - bool operator()(unsigned i1, unsigned i2) const { - if (m_lit_num[i1] == 1 && m_lit_num[i2] > 1) - return true; - if (m_lit_num[i1] > 1 && m_lit_num[i2] == 1) - return false; - if (m_degrees[i1] != m_degrees[i2]) - return m_degrees[i1] < m_degrees[i2]; - if (m_lit_num[i1] != m_lit_num[i2]) - return m_lit_num[i1] < m_lit_num[i2]; - return i1 < i2; - } - }; - - unsigned_vector m_dl_degrees; - unsigned_vector m_dl_lit_num; - unsigned_vector m_dl_p; - void sort_clauses_by_degree_lit_num(unsigned sz, clause ** cs) { - if (sz <= 1) - return; - TRACE("nlsat_reorder_clauses", tout << "before:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); - m_dl_degrees.reset(); - m_dl_lit_num.reset(); - m_dl_p.reset(); - for (unsigned i = 0; i < sz; i++) { - m_dl_degrees.push_back(degree(*(cs[i]))); - m_dl_lit_num.push_back(cs[i]->size()); - m_dl_p.push_back(i); - } - std::sort(m_dl_p.begin(), m_dl_p.end(), degree_lit_num_lt(m_dl_degrees, m_dl_lit_num)); - TRACE("nlsat_reorder_clauses", tout << "permutation: "; ::display(tout, m_dl_p.begin(), m_dl_p.end()); tout << "\n";); - apply_permutation(sz, cs, m_dl_p.data()); - TRACE("nlsat_reorder_clauses", tout << "after:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); - } - - void sort_watched_clauses() { - unsigned num = num_vars(); - for (unsigned i = 0; i < num; i++) { - clause_vector & ws = m_watches[i]; - // sort_clauses_by_degree(ws.size(), ws.data()); - if (m_simple_check) { - sort_clauses_by_degree_lit_num(ws.size(), ws.data()); - } - else { - sort_clauses_by_degree(ws.size(), ws.data()); - } - } - } - - // ----------------------- - // - // Full dimensional - // - // A problem is in the full dimensional fragment if it does - // not contain equalities or non-strict inequalities. - // - // ----------------------- - - bool is_full_dimensional(literal l) const { - atom * a = m_atoms[l.var()]; - if (a == nullptr) - return true; - switch (a->get_kind()) { - case atom::EQ: return l.sign(); - case atom::LT: return !l.sign(); - case atom::GT: return !l.sign(); - case atom::ROOT_EQ: return l.sign(); - case atom::ROOT_LT: return !l.sign(); - case atom::ROOT_GT: return !l.sign(); - case atom::ROOT_LE: return l.sign(); - case atom::ROOT_GE: return l.sign(); - default: - UNREACHABLE(); - return false; - } - } - - bool is_full_dimensional(clause const & c) const { - for (literal l : c) { - if (!is_full_dimensional(l)) - return false; - } - return true; - } - - bool is_full_dimensional(clause_vector const & cs) const { - for (clause* c : cs) { - if (!is_full_dimensional(*c)) - return false; - } - return true; - } - - bool is_full_dimensional() const { - return is_full_dimensional(m_clauses); - } - - - // ----------------------- - // - // Simplification - // - // ----------------------- - - // solve simple equalities - // TBD WU-Reit decomposition? - - // - elim_unconstrained - // - solve_eqs - // - fm - - /** - \brief isolate variables in unit equalities. - Assume a clause is c == v*p + q - and the context implies p > 0 - - replace v by -q/p - remove clause c, - The for other occurrences of v, - replace v*r + v*v*r' > 0 by - by p*p*v*r + p*p*v*v*r' > 0 - by p*q*r + q*q*r' > 0 - - The method ignores lemmas and assumes constraints don't use roots. - */ - - - - // Eliminated variables are tracked in m_bounds. - // Each element in m_bounds tracks the eliminated variable and an upper or lower bound - // that has to be satisfied. Variables that are eliminated through equalities are tracked - // by non-strict bounds. A satisfiable solution is required to provide an evaluation that - // is consistent with the bounds. For equalities, the non-strict lower or upper bound can - // always be assigned as a value to the variable. - - void fix_patch() { - m_lo.reset(); m_hi.reset(); - for (auto& b : m_bounds) - m_assignment.reset(b.x); - for (unsigned i = m_bounds.size(); i-- > 0; ) - fix_patch(m_bounds[i]); - } - - // x is unassigned, lo < x -> x <- lo + 1 - // x is unassigned, x < hi -> x <- hi - 1 - // x is unassigned, lo <= x -> x <- lo - // x is unassigned, x <= hi -> x <- hi - // x is assigned above hi, lo is strict lo < x < hi -> set x <- (lo + hi)/2 - // x is assigned below hi, above lo -> no-op - // x is assigned below lo, hi is strict lo < x < hi -> set x <-> (lo + hi)/2 - // x is assigned above hi, x <= hi -> x <- hi - // x is assigned blow lo, lo <= x -> x <- lo - void fix_patch(bound_constraint& b) { - var x = b.x; - scoped_anum Av(m_am), Bv(m_am), val(m_am); - m_pm.eval(b.A, m_assignment, Av); - m_pm.eval(b.B, m_assignment, Bv); - m_am.neg(Bv); - val = Bv / Av; - // Ax >= B - // is-lower : A > 0 - // is-upper: A < 0 - // x <- B / A - bool is_lower = m_am.is_pos(Av); - TRACE("nlsat", - m_display_var(tout << "patch v" << x << " ", x) << "\n"; - if (m_assignment.is_assigned(x)) m_am.display(tout << "previous value: ", m_assignment.value(x)); tout << "\n"; - m_am.display(tout << "updated value: ", val); tout << "\n"; - ); - - if (!m_assignment.is_assigned(x)) { - if (!b.is_strict) - m_assignment.set_core(x, val); - else if (is_lower) - m_assignment.set_core(x, val + 1); - else - m_assignment.set_core(x, val - 1); - } - else { - auto& aval = m_assignment.value(x); - if (is_lower) { - // lo < value(x), lo < x -> x is unchanged - if (b.is_strict && m_am.lt(val, aval)) - ; - else if (!b.is_strict && m_am.le(val, aval)) - ; - else if (!b.is_strict) - m_assignment.set_core(x, val); - // aval < lo < x, hi is unassigned: x <- lo + 1 - else if (!m_hi.is_assigned(x)) - m_assignment.set_core(x, val + 1); - // aval < lo < x, hi is assigned: x <- (lo + hi) / 2 - else { - scoped_anum mid(m_am); - m_am.add(m_hi.value(x), val, mid); - mid = mid / 2; - m_assignment.set_core(x, mid); - } - } - else { - // dual to lower bounds - if (b.is_strict && m_am.lt(aval, val)) - ; - else if (!b.is_strict && m_am.le(aval, val)) - ; - else if (!b.is_strict) - m_assignment.set_core(x, val); - else if (!m_lo.is_assigned(x)) - m_assignment.set_core(x, val - 1); - else { - scoped_anum mid(m_am); - m_am.add(m_lo.value(x), val, mid); - mid = mid / 2; - m_assignment.set_core(x, mid); - } - } - } - - if (is_lower) { - if (!m_lo.is_assigned(x) || m_am.lt(m_lo.value(x), val)) - m_lo.set_core(x, val); - } - else { - if (!m_hi.is_assigned(x) || m_am.gt(m_hi.value(x), val)) - m_hi.set_core(x, val); - } - } - - bool is_unit_ineq(clause const& c) const { - return - c.size() == 1 && - m_atoms[c[0].var()] && - m_atoms[c[0].var()]->is_ineq_atom(); - } - - bool is_unit_eq(clause const& c) const { - return - is_unit_ineq(c) && - !c[0].sign() && - m_atoms[c[0].var()]->is_eq(); - } - - /** - \brief determine whether the clause is a comparison v > k or v < k', where k >= 0 or k' <= 0. - */ - lbool is_cmp0(clause const& c, var& v) { - if (!is_unit_ineq(c)) - return l_undef; - literal lit = c[0]; - ineq_atom const& a = *to_ineq_atom(m_atoms[lit.var()]); - bool sign = lit.sign(); - poly * p0; - if (!is_single_poly(a, p0)) - return l_undef; - if (m_pm.is_var(p0, v)) { - if (!sign && a.get_kind() == atom::GT) { - return l_true; - } - if (!sign && a.get_kind() == atom::LT) { - return l_false; - } - return l_undef; - } - polynomial::scoped_numeral n(m_pm.m()); - if (m_pm.is_var_num(p0, v, n)) { - // x - k > 0 - if (!sign && a.get_kind() == atom::GT && m_pm.m().is_nonneg(n)) { - return l_true; - } - // x + k < 0 - if (!sign && a.get_kind() == atom::LT && m_pm.m().is_nonpos(n)) { - return l_false; - } - // !(x + k > 0) - if (sign && a.get_kind() == atom::GT && m_pm.m().is_pos(n)) { - return l_false; - } - // !(x - k < 0) - if (sign && a.get_kind() == atom::LT && m_pm.m().is_neg(n)) { - return l_true; - } - } - return l_undef; - } - - bool is_single_poly(ineq_atom const& a, poly*& p) { - unsigned sz = a.size(); - return sz == 1 && a.is_odd(0) && (p = a.p(0), true); - } - - bool is_unit(polynomial_ref const& p) { - if (!m_pm.is_const(p)) - return false; - auto const& c = m_pm.coeff(p, 0); - return m_pm.m().is_one(c) || m_pm.m().is_minus_one(c); - } - - // ----------------------- - // - // Pretty printing - // - // ----------------------- - - std::ostream& display_num_assignment(std::ostream & out, display_var_proc const & proc) const { - for (var x = 0; x < num_vars(); x++) { - if (m_assignment.is_assigned(x)) { - proc(out, x); - out << " -> "; - m_am.display_decimal(out, m_assignment.value(x)); - out << "\n"; - } - } - return out; - } - - std::ostream& display_bool_assignment(std::ostream & out) const { - unsigned sz = m_atoms.size(); - for (bool_var b = 0; b < sz; b++) { - if (m_atoms[b] == nullptr && m_bvalues[b] != l_undef) { - out << "b" << b << " -> " << (m_bvalues[b] == l_true ? "true" : "false") << " @" << m_levels[b] << "\n"; - } - else if (m_atoms[b] != nullptr && m_bvalues[b] != l_undef) { - display(out << "b" << b << " ", *m_atoms[b]) << " -> " << (m_bvalues[b] == l_true ? "true" : "false") << " @" << m_levels[b] << "\n"; - } - } - TRACE("nlsat_bool_assignment", - for (bool_var b = 0; b < sz; b++) { - out << "b" << b << " -> " << m_bvalues[b] << " "; - if (m_atoms[b]) display(out, *m_atoms[b]); - out << "\n"; - }); - return out; - } - - bool display_mathematica_assignment(std::ostream & out) const { - bool first = true; - for (var x = 0; x < num_vars(); x++) { - if (m_assignment.is_assigned(x)) { - if (first) - first = false; - else - out << " && "; - out << "x" << x << " == "; - m_am.display_mathematica(out, m_assignment.value(x)); - } - } - return !first; - } - - std::ostream& display_num_assignment(std::ostream & out) const { - return display_num_assignment(out, m_display_var); - } - - std::ostream& display_assignment(std::ostream& out) const { - display_bool_assignment(out); - display_num_assignment(out); - return out; - } - - std::ostream& display(std::ostream& out, justification j) const { - switch (j.get_kind()) { - case justification::CLAUSE: - display(out, *j.get_clause()) << "\n"; - break; - case justification::LAZY: { - lazy_justification const& lz = *j.get_lazy(); - display_not(out, lz.num_lits(), lz.lits()) << "\n"; - for (unsigned i = 0; i < lz.num_clauses(); ++i) { - display(out, lz.clause(i)) << "\n"; - } - break; - } - default: - out << j.get_kind() << "\n"; - break; - } - return out; - } - - bool m_display_eval = false; - std::ostream& display_eval(std::ostream& out, justification j) { - flet _display(m_display_eval, true); - return display(out, j); - } - - std::ostream& display_ineq(std::ostream & out, ineq_atom const & a, display_var_proc const & proc, bool use_star = false) const { - unsigned sz = a.size(); - for (unsigned i = 0; i < sz; i++) { - if (use_star && i > 0) - out << "*"; - bool is_even = a.is_even(i); - if (is_even || sz > 1) - out << "("; - display_polynomial(out, a.p(i), proc, use_star); - if (is_even || sz > 1) - out << ")"; - if (is_even) - out << "^2"; - } - switch (a.get_kind()) { - case atom::LT: out << " < 0"; break; - case atom::GT: out << " > 0"; break; - case atom::EQ: out << " = 0"; break; - default: UNREACHABLE(); break; - } - return out; - } - - std::ostream& display_mathematica(std::ostream & out, ineq_atom const & a) const { - unsigned sz = a.size(); - for (unsigned i = 0; i < sz; i++) { - if (i > 0) - out << "*"; - bool is_even = a.is_even(i); - if (sz > 1) - out << "("; - if (is_even) - out << "("; - m_pm.display(out, a.p(i), display_var_proc(), true); - if (is_even) - out << "^2)"; - if (sz > 1) - out << ")"; - } - switch (a.get_kind()) { - case atom::LT: out << " < 0"; break; - case atom::GT: out << " > 0"; break; - case atom::EQ: out << " == 0"; break; - default: UNREACHABLE(); break; - } - return out; - } - - std::ostream& display_polynomial_smt2(std::ostream & out, poly const* p, display_var_proc const & proc) const { - return m_pm.display_smt2(out, p, proc); - } - - std::ostream& display_ineq_smt2(std::ostream & out, ineq_atom const & a, display_var_proc const & proc) const { - switch (a.get_kind()) { - case atom::LT: out << "(< "; break; - case atom::GT: out << "(> "; break; - case atom::EQ: out << "(= "; break; - default: UNREACHABLE(); break; - } - unsigned sz = a.size(); - if (sz > 1) - out << "(* "; - for (unsigned i = 0; i < sz; i++) { - if (i > 0) out << " "; - if (a.is_even(i)) { - out << "(* "; - display_polynomial_smt2(out, a.p(i), proc); - out << " "; - display_polynomial_smt2(out, a.p(i), proc); - out << ")"; - } - else { - display_polynomial_smt2(out, a.p(i), proc); - } - } - if (sz > 1) - out << ")"; - out << " 0)"; - return out; - } - - std::ostream& display_poly_root(std::ostream& out, char const* y, root_atom const& a, display_var_proc const& proc) const { - out << "(exists (("; proc(out,a.x()); out << " Real))\n"; - out << "(and (= " << y << " "; - proc(out, a.x()); - out << ") (= 0 "; - display_polynomial_smt2(out, a.p(), proc); - out << ")))\n"; - return out; - } - - std::ostream& display_binary_smt2(std::ostream& out, poly const* p1, char const* rel, poly const* p2, display_var_proc const& proc) const { - out << "(" << rel << " "; - display_polynomial_smt2(out, p1, proc); - out << " "; - display_polynomial_smt2(out, p2, proc); - out << ")"; - return out; - } - - - std::ostream& display_linear_root_smt2(std::ostream & out, root_atom const & a, display_var_proc const & proc) const { - polynomial_ref A(m_pm), B(m_pm), Z(m_pm), Ax(m_pm); - polynomial::scoped_numeral zero(m_qm); - m_pm.m().set(zero, 0); - A = m_pm.derivative(a.p(), a.x()); - B = m_pm.neg(m_pm.substitute(a.p(), a.x(), zero)); - Z = m_pm.mk_zero(); - - Ax = m_pm.mul(m_pm.mk_polynomial(a.x()), A); - - // x < root[1](ax + b) == (a > 0 => ax + b < 0) & (a < 0 => ax + b > 0) - // x < root[1](ax + b) == (a > 0 => ax < -b) & (a < 0 => ax > -b) - - char const* rel1 = "<", *rel2 = ">"; - switch (a.get_kind()) { - case atom::ROOT_LT: rel1 = "<"; rel2 = ">"; break; - case atom::ROOT_GT: rel1 = ">"; rel2 = "<"; break; - case atom::ROOT_LE: rel1 = "<="; rel2 = ">="; break; - case atom::ROOT_GE: rel1 = ">="; rel2 = "<="; break; - case atom::ROOT_EQ: rel1 = rel2 = "="; break; - default: UNREACHABLE(); break; - } - - out << "(and "; - out << "(=> "; display_binary_smt2(out, A, ">", Z, proc); display_binary_smt2(out, Ax, rel1, B, proc); out << ") "; - out << "(=> "; display_binary_smt2(out, A, "<", Z, proc); display_binary_smt2(out, Ax, rel2, B, proc); out << ") "; - out << ")"; - - return out; - } - - - std::ostream& display_root_smt2(std::ostream& out, root_atom const& a, display_var_proc const& proc) const { - if (a.i() == 1 && m_pm.degree(a.p(), a.x()) == 1) - return display_linear_root_smt2(out, a, proc); -#if 1 - out << "(exists ("; - for (unsigned j = 0; j < a.i(); ++j) { - std::string y = std::string("y") + std::to_string(j); - out << "(" << y << " Real) "; - } - out << ")\n"; - out << "(and\n"; - for (unsigned j = 0; j < a.i(); ++j) { - std::string y = std::string("y") + std::to_string(j); - display_poly_root(out, y.c_str(), a, proc); - } - for (unsigned j = 0; j + 1 < a.i(); ++j) { - std::string y1 = std::string("y") + std::to_string(j); - std::string y2 = std::string("y") + std::to_string(j+1); - out << "(< " << y1 << " " << y2 << ")\n"; - } - - std::string yn = "y" + std::to_string(a.i() - 1); - - // TODO we need (forall z : z < yn . p(z) => z = y1 or ... z = y_{n-1}) - // to say y1, .., yn are the first n distinct roots. - // - out << "(forall ((z Real)) (=> (and (< z " << yn << ") "; display_poly_root(out, "z", a, proc) << ") "; - if (a.i() == 1) { - out << "false))\n"; - } - else { - out << "(or "; - for (unsigned j = 0; j + 1 < a.i(); ++j) { - std::string y1 = std::string("y") + std::to_string(j); - out << "(= z " << y1 << ") "; - } - out << ")))\n"; - } - switch (a.get_kind()) { - case atom::ROOT_LT: out << "(< "; proc(out, a.x()); out << " " << yn << ")"; break; - case atom::ROOT_GT: out << "(> "; proc(out, a.x()); out << " " << yn << ")"; break; - case atom::ROOT_LE: out << "(<= "; proc(out, a.x()); out << " " << yn << ")"; break; - case atom::ROOT_GE: out << "(>= "; proc(out, a.x()); out << " " << yn << ")"; break; - case atom::ROOT_EQ: out << "(= "; proc(out, a.x()); out << " " << yn << ")"; NOT_IMPLEMENTED_YET(); break; - default: UNREACHABLE(); break; - } - out << "))"; - return out; -#endif - - - return display_root(out, a, proc); - } - - std::ostream& display_root(std::ostream & out, root_atom const & a, display_var_proc const & proc) const { - proc(out, a.x()); - switch (a.get_kind()) { - case atom::ROOT_LT: out << " < "; break; - case atom::ROOT_GT: out << " > "; break; - case atom::ROOT_LE: out << " <= "; break; - case atom::ROOT_GE: out << " >= "; break; - case atom::ROOT_EQ: out << " = "; break; - default: UNREACHABLE(); break; - } - out << "root[" << a.i() << "]("; - display_polynomial(out, a.p(), proc); - out << ")"; - return out; - } - - struct mathematica_var_proc : public display_var_proc { - var m_x; - public: - mathematica_var_proc(var x):m_x(x) {} - std::ostream& operator()(std::ostream & out, var x) const override { - if (m_x == x) - return out << "#1"; - else - return out << "x" << x; - } - }; - - std::ostream& display_mathematica(std::ostream & out, root_atom const & a) const { - out << "x" << a.x(); - switch (a.get_kind()) { - case atom::ROOT_LT: out << " < "; break; - case atom::ROOT_GT: out << " > "; break; - case atom::ROOT_LE: out << " <= "; break; - case atom::ROOT_GE: out << " >= "; break; - case atom::ROOT_EQ: out << " == "; break; - default: UNREACHABLE(); break; - } - out << "Root["; - display_polynomial(out, a.p(), mathematica_var_proc(a.x()), true); - out << " &, " << a.i() << "]"; - return out; - } - - std::ostream& display(std::ostream & out, atom const & a, display_var_proc const & proc) const { - if (a.is_ineq_atom()) - return display_ineq(out, static_cast(a), proc); - else - return display_root(out, static_cast(a), proc); - } - - std::ostream& display(std::ostream & out, atom const & a) const { - return display(out, a, m_display_var); - } - - std::ostream& display_mathematica(std::ostream & out, atom const & a) const { - if (a.is_ineq_atom()) - return display_mathematica(out, static_cast(a)); - else - return display_mathematica(out, static_cast(a)); - } - - std::ostream& display_smt2(std::ostream & out, atom const & a, display_var_proc const & proc) const { - if (a.is_ineq_atom()) - return display_ineq_smt2(out, static_cast(a), proc); - else - return display_root_smt2(out, static_cast(a), proc); - } - - std::ostream& display_atom(std::ostream & out, bool_var b, display_var_proc const & proc) const { - if (b == 0) - out << "true"; - else if (m_atoms[b] == 0) - out << "b" << b; - else - display(out, *(m_atoms[b]), proc); - return out; - } - - std::ostream& display_atom(std::ostream & out, bool_var b) const { - return display_atom(out, b, m_display_var); - } - - std::ostream& display_mathematica_atom(std::ostream & out, bool_var b) const { - if (b == 0) - out << "(0 < 1)"; - else if (m_atoms[b] == 0) - out << "b" << b; - else - display_mathematica(out, *(m_atoms[b])); - return out; - } - - std::ostream& display_smt2_atom(std::ostream & out, bool_var b, display_var_proc const & proc) const { - if (b == 0) - out << "true"; - else if (m_atoms[b] == 0) - out << "b" << b; - else - display_smt2(out, *(m_atoms[b]), proc); - return out; - } - - std::ostream& display(std::ostream & out, literal l, display_var_proc const & proc) const { - if (l.sign()) { - bool_var b = l.var(); - out << "!"; - if (m_atoms[b] != 0) - out << "("; - display_atom(out, b, proc); - if (m_atoms[b] != 0) - out << ")"; - } - else { - display_atom(out, l.var(), proc); - } - return out; - } - - std::ostream& display(std::ostream & out, literal l) const { - return display(out, l, m_display_var); - } - - std::ostream& display_smt2(std::ostream & out, literal l) const { - return display_smt2(out, l, m_display_var); - } - - std::ostream& display_mathematica(std::ostream & out, literal l) const { - if (l.sign()) { - bool_var b = l.var(); - out << "!"; - if (m_atoms[b] != 0) - out << "("; - display_mathematica_atom(out, b); - if (m_atoms[b] != 0) - out << ")"; - } - else { - display_mathematica_atom(out, l.var()); - } - return out; - } - - std::ostream& display_smt2(std::ostream & out, literal l, display_var_proc const & proc) const { - if (l.sign()) { - bool_var b = l.var(); - out << "(not "; - display_smt2_atom(out, b, proc); - out << ")"; - } - else { - display_smt2_atom(out, l.var(), proc); - } - return out; - } - - std::ostream& display_assumptions(std::ostream & out, _assumption_set s) const { - if (!m_display_assumption) - return out; - vector deps; - m_asm.linearize(s, deps); - bool first = true; - for (auto dep : deps) { - if (first) first = false; else out << " "; - (*m_display_assumption)(out, dep); - } - return out; - } - - std::ostream& display(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { - for (unsigned i = 0; i < num; i++) { - if (i > 0) - out << " or "; - display(out, ls[i], proc); - } - return out; - } - - std::ostream& display(std::ostream & out, unsigned num, literal const * ls) const { - return display(out, num, ls, m_display_var); - } - - std::ostream& display_not(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { - for (unsigned i = 0; i < num; i++) { - if (i > 0) - out << " or "; - display(out, ~ls[i], proc); - } - return out; - } - - std::ostream& display_not(std::ostream & out, unsigned num, literal const * ls) const { - return display_not(out, num, ls, m_display_var); - } - - std::ostream& display(std::ostream & out, scoped_literal_vector const & cs) { - return display(out, cs.size(), cs.data(), m_display_var); - } - - std::ostream& display(std::ostream & out, clause const & c, display_var_proc const & proc) const { - if (c.assumptions() != nullptr) { - display_assumptions(out, static_cast<_assumption_set>(c.assumptions())); - out << " |- "; - } - return display(out, c.size(), c.data(), proc); - } - - std::ostream& display(std::ostream & out, clause const & c) const { - return display(out, c, m_display_var); - } - - - std::ostream& display_polynomial(std::ostream& out, poly* p, display_var_proc const & proc, bool use_star = false) const { - if (m_display_eval) { - polynomial_ref q(m_pm); - q = p; - for (var x = 0; x < num_vars(); x++) - if (m_assignment.is_assigned(x)) { - auto& a = m_assignment.value(x); - if (!m_am.is_rational(a)) - continue; - mpq r; - m_am.to_rational(a, r); - q = m_pm.substitute(q, 1, &x, &r); - } - m_pm.display(out, q, proc, use_star); - } - else - m_pm.display(out, p, proc, use_star); - return out; - } - - // -- - - std::ostream& display_smt2(std::ostream & out, unsigned n, literal const* ls) const { - return display_smt2(out, n, ls, display_var_proc()); - } - - - std::ostream& display_smt2(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { - if (num == 0) { - out << "false"; - } - else if (num == 1) { - display_smt2(out, ls[0], proc); - } - else { - out << "(or"; - for (unsigned i = 0; i < num; i++) { - out << " "; - display_smt2(out, ls[i], proc); - } - out << ")"; - } - return out; - } - - std::ostream& display_smt2(std::ostream & out, clause const & c, display_var_proc const & proc = display_var_proc()) const { - return display_smt2(out, c.size(), c.data(), proc); - } - - std::ostream& display_abst(std::ostream & out, literal l) const { - if (l.sign()) { - bool_var b = l.var(); - out << "!"; - if (b == true_bool_var) - out << "true"; - else - out << "b" << b; - } - else { - out << "b" << l.var(); - } - return out; - } - - std::ostream& display_abst(std::ostream & out, unsigned num, literal const * ls) const { - for (unsigned i = 0; i < num; i++) { - if (i > 0) - out << " or "; - display_abst(out, ls[i]); - } - return out; - } - - std::ostream& display_abst(std::ostream & out, scoped_literal_vector const & cs) const { - return display_abst(out, cs.size(), cs.data()); - } - - std::ostream& display_abst(std::ostream & out, clause const & c) const { - return display_abst(out, c.size(), c.data()); - } - - std::ostream& display_mathematica(std::ostream & out, clause const & c) const { - out << "("; - unsigned sz = c.size(); - for (unsigned i = 0; i < sz; i++) { - if (i > 0) - out << " || "; - display_mathematica(out, c[i]); - } - out << ")"; - return out; - } - - // Debugging support: - // Display generated lemma in Mathematica format. - // Mathematica must reduce lemma to True (modulo resource constraints). - std::ostream& display_mathematica_lemma(std::ostream & out, unsigned num, literal const * ls, bool include_assignment = false) const { - out << "Resolve[ForAll[{"; - // var definition - for (unsigned i = 0; i < num_vars(); i++) { - if (i > 0) - out << ", "; - out << "x" << i; - } - out << "}, "; - if (include_assignment) { - out << "!("; - if (!display_mathematica_assignment(out)) - out << "0 < 1"; // nothing was printed - out << ") || "; - } - for (unsigned i = 0; i < num; i++) { - if (i > 0) - out << " || "; - display_mathematica(out, ls[i]); - } - out << "], Reals]\n"; // end of exists - return out; - } - - std::ostream& display(std::ostream & out, clause_vector const & cs, display_var_proc const & proc) const { - for (clause* c : cs) { - display(out, *c, proc) << "\n"; - } - return out; - } - - std::ostream& display(std::ostream & out, clause_vector const & cs) const { - return display(out, cs, m_display_var); - } - - std::ostream& display_mathematica(std::ostream & out, clause_vector const & cs) const { - unsigned sz = cs.size(); - for (unsigned i = 0; i < sz; i++) { - if (i > 0) out << ",\n"; - display_mathematica(out << " ", *(cs[i])); - } - return out; - } - - std::ostream& display_abst(std::ostream & out, clause_vector const & cs) const { - for (clause* c : cs) { - display_abst(out, *c) << "\n"; - } - return out; - } - - std::ostream& display(std::ostream & out, display_var_proc const & proc) const { - display(out, m_clauses, proc); - if (!m_learned.empty()) { - display(out << "Lemmas:\n", m_learned, proc); - } - return out; - } - - std::ostream& display_mathematica(std::ostream & out) const { - return display_mathematica(out << "{\n", m_clauses) << "}\n"; - } - - std::ostream& display_abst(std::ostream & out) const { - display_abst(out, m_clauses); - if (!m_learned.empty()) { - display_abst(out << "Lemmas:\n", m_learned); - } - return out; - } - - std::ostream& display(std::ostream & out) const { - display(out, m_display_var); - display_assignment(out << "assignment:\n"); - return out << "---\n"; - } - - std::ostream& display_vars(std::ostream & out) const { - for (unsigned i = 0; i < num_vars(); i++) { - out << i << " -> "; m_display_var(out, i); out << "\n"; - } - return out; - } - - std::ostream& display_smt2_arith_decls(std::ostream & out) const { - unsigned sz = m_is_int.size(); - for (unsigned i = 0; i < sz; i++) { - if (is_int(i)) { - out << "(declare-fun "; m_display_var(out, i) << " () Int)\n"; - } - else { - out << "(declare-fun "; m_display_var(out, i) << " () Real)\n"; - } - } - return out; - } - - std::ostream& display_smt2_bool_decls(std::ostream & out) const { - unsigned sz = m_atoms.size(); - for (unsigned i = 0; i < sz; i++) { - if (m_atoms[i] == nullptr) - out << "(declare-fun b" << i << " () Bool)\n"; - } - return out; - } - - std::ostream& display_smt2(std::ostream & out) const { - display_smt2_bool_decls(out); - display_smt2_arith_decls(out); - out << "(assert (and true\n"; - for (clause* c : m_clauses) { - display_smt2(out, *c, m_display_var) << "\n"; - } - out << "))\n" << std::endl; - return out; - } - }; - - solver::solver(reslimit& rlim, params_ref const & p, bool incremental) { - m_ctx = alloc(ctx, rlim, p, incremental); - m_imp = alloc(imp, *this, *m_ctx); - } - - solver::solver(ctx& ctx) { - m_ctx = nullptr; - m_imp = alloc(imp, *this, ctx); - } - - solver::~solver() { - dealloc(m_imp); - dealloc(m_ctx); - } - - lbool solver::check() { - return m_imp->check(); - } - - lbool solver::check(literal_vector& assumptions) { - return m_imp->check(assumptions); - } - - void solver::get_core(vector& assumptions) { - return m_imp->get_core(assumptions); - } - - void solver::reset() { - m_imp->reset(); - } - - - void solver::updt_params(params_ref const & p) { - m_imp->updt_params(p); - } - - - void solver::collect_param_descrs(param_descrs & d) { - algebraic_numbers::manager::collect_param_descrs(d); - nlsat_params::collect_param_descrs(d); - } - - unsynch_mpq_manager & solver::qm() { - return m_imp->m_qm; - } - - anum_manager & solver::am() { - return m_imp->m_am; - } - - pmanager & solver::pm() { - return m_imp->m_pm; - } - - void solver::set_display_var(display_var_proc const & proc) { - m_imp->m_display_var.m_proc = &proc; - } - - void solver::set_display_assumption(display_assumption_proc const& proc) { - m_imp->m_display_assumption = &proc; - } - - - unsigned solver::num_vars() const { - return m_imp->num_vars(); - } - - bool solver::is_int(var x) const { - return m_imp->is_int(x); - } - - bool_var solver::mk_bool_var() { - return m_imp->mk_bool_var(); - } - - literal solver::mk_true() { - return literal(0, false); - } - - atom * solver::bool_var2atom(bool_var b) { - return m_imp->m_atoms[b]; - } - - void solver::vars(literal l, var_vector& vs) { - m_imp->vars(l, vs); - } - - atom_vector const& solver::get_atoms() { - return m_imp->m_atoms; - } - - atom_vector const& solver::get_var2eq() { - return m_imp->m_var2eq; - } - - evaluator& solver::get_evaluator() { - return m_imp->m_evaluator; - } - - explain& solver::get_explain() { - return m_imp->m_explain; - } - - void solver::reorder(unsigned sz, var const* p) { - m_imp->reorder(sz, p); - } - - void solver::restore_order() { - m_imp->restore_order(); - } - - void solver::set_rvalues(assignment const& as) { - m_imp->m_assignment.copy(as); - } - - void solver::get_rvalues(assignment& as) { - as.copy(m_imp->m_assignment); - } - - void solver::get_bvalues(svector const& bvars, svector& vs) { - vs.reset(); - for (bool_var b : bvars) { - vs.reserve(b + 1, l_undef); - if (!m_imp->m_atoms[b]) { - vs[b] = m_imp->m_bvalues[b]; - } - } - TRACE("nlsat", display(tout);); - } - - void solver::set_bvalues(svector const& vs) { - TRACE("nlsat", display(tout);); - for (bool_var b = 0; b < vs.size(); ++b) { - if (vs[b] != l_undef) { - m_imp->m_bvalues[b] = vs[b]; - SASSERT(!m_imp->m_atoms[b]); - } - } -#if 0 - m_imp->m_bvalues.reset(); - m_imp->m_bvalues.append(vs); - m_imp->m_bvalues.resize(m_imp->m_atoms.size(), l_undef); - for (unsigned i = 0; i < m_imp->m_atoms.size(); ++i) { - atom* a = m_imp->m_atoms[i]; - SASSERT(!a); - if (a) { - m_imp->m_bvalues[i] = to_lbool(m_imp->m_evaluator.eval(a, false)); - } - } -#endif - TRACE("nlsat", display(tout);); - } - - void solver::del_clause(clause* c) { - m_imp->del_clause(c); - } - - var solver::mk_var(bool is_int) { - return m_imp->mk_var(is_int); - } - - bool_var solver::mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even) { - return m_imp->mk_ineq_atom(k, sz, ps, is_even); - } - - literal solver::mk_ineq_literal(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify) { - return m_imp->mk_ineq_literal(k, sz, ps, is_even, simplify); - } - - bool_var solver::mk_root_atom(atom::kind k, var x, unsigned i, poly * p) { - return m_imp->mk_root_atom(k, x, i, p); - } - - void solver::inc_ref(bool_var b) { - m_imp->inc_ref(b); - } - - void solver::dec_ref(bool_var b) { - m_imp->dec_ref(b); - } - - void solver::inc_ref(assumption a) { - m_imp->inc_ref(static_cast(a)); - } - - void solver::dec_ref(assumption a) { - m_imp->dec_ref(static_cast(a)); - } - - void solver::mk_clause(unsigned num_lits, literal * lits, assumption a) { - return m_imp->mk_external_clause(num_lits, lits, a); - } - - std::ostream& solver::display(std::ostream & out) const { - return m_imp->display(out); - } - - std::ostream& solver::display(std::ostream & out, literal l) const { - return m_imp->display(out, l); - } - - std::ostream& solver::display(std::ostream & out, unsigned n, literal const* ls) const { - for (unsigned i = 0; i < n; ++i) { - display(out, ls[i]); - out << "; "; - } - return out; - } - - std::ostream& solver::display(std::ostream & out, literal_vector const& ls) const { - return display(out, ls.size(), ls.data()); - } - - std::ostream& solver::display_smt2(std::ostream & out, literal l) const { - return m_imp->display_smt2(out, l); - } - - std::ostream& solver::display_smt2(std::ostream & out, unsigned n, literal const* ls) const { - for (unsigned i = 0; i < n; ++i) { - display_smt2(out, ls[i]); - out << " "; - } - return out; - } - - std::ostream& solver::display(std::ostream& out, clause const& c) const { - return m_imp->display(out, c); - } - - std::ostream& solver::display_smt2(std::ostream & out) const { - return m_imp->display_smt2(out); - } - - std::ostream& solver::display_smt2(std::ostream & out, literal_vector const& ls) const { - return display_smt2(out, ls.size(), ls.data()); - } - - std::ostream& solver::display(std::ostream & out, var x) const { - return m_imp->m_display_var(out, x); - } - - std::ostream& solver::display(std::ostream & out, atom const& a) const { - return m_imp->display(out, a, m_imp->m_display_var); - } - - display_var_proc const & solver::display_proc() const { - return m_imp->m_display_var; - } - - anum const & solver::value(var x) const { - if (m_imp->m_assignment.is_assigned(x)) - return m_imp->m_assignment.value(x); - return m_imp->m_zero; - } - - lbool solver::bvalue(bool_var b) const { - return m_imp->m_bvalues[b]; - } - - lbool solver::value(literal l) const { - return m_imp->value(l); - } - - bool solver::is_interpreted(bool_var b) const { - return m_imp->m_atoms[b] != 0; - } - - void solver::reset_statistics() { - return m_imp->reset_statistics(); - } - - void solver::collect_statistics(statistics & st) { - return m_imp->collect_statistics(st); - } - - clause* solver::mk_clause(unsigned n, literal const* lits, bool learned, internal_assumption a) { - return m_imp->mk_clause(n, lits, learned, static_cast(a)); - } - - void solver::inc_simplify() { - m_imp->m_stats.m_simplifications++; - } - - bool solver::has_root_atom(clause const& c) const { - return m_imp->has_root_atom(c); - } - - void solver::add_bound(bound_constraint const& c) { - m_imp->m_bounds.push_back(c); - } - - assumption solver::join(assumption a, assumption b) { - return (m_imp->m_asm.mk_join(static_cast(a), static_cast(b))); - } - -}; +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + nlsat_solver.cpp + +Abstract: + + Nonlinear arithmetic satisfiability procedure. The procedure is + complete for nonlinear real arithmetic, but it also has limited + support for integers. + +Author: + + Leonardo de Moura (leonardo) 2012-01-02. + +Revision History: + +--*/ +#include "util/z3_exception.h" +#include "util/chashtable.h" +#include "util/id_gen.h" +#include "util/map.h" +#include "util/dependency.h" +#include "util/permutation.h" +#include "math/polynomial/algebraic_numbers.h" +#include "math/polynomial/polynomial_cache.h" +#include "nlsat/nlsat_solver.h" +#include "nlsat/nlsat_clause.h" +#include "nlsat/nlsat_assignment.h" +#include "nlsat/nlsat_justification.h" +#include "nlsat/nlsat_evaluator.h" +#include "nlsat/nlsat_explain.h" +#include "nlsat/nlsat_params.hpp" +#include "nlsat/nlsat_simplify.h" +#include "nlsat/nlsat_simple_checker.h" +#include "nlsat/nlsat_variable_ordering_strategy.h" + +#define NLSAT_EXTRA_VERBOSE + +#ifdef NLSAT_EXTRA_VERBOSE +#define NLSAT_VERBOSE(CODE) IF_VERBOSE(10, CODE) +#else +#define NLSAT_VERBOSE(CODE) ((void)0) +#endif + +namespace nlsat { + + + typedef chashtable ineq_atom_table; + typedef chashtable root_atom_table; + + // for apply_permutation procedure + void swap(clause * & c1, clause * & c2) noexcept { + std::swap(c1, c2); + } + + struct solver::ctx { + params_ref m_params; + reslimit& m_rlimit; + small_object_allocator m_allocator; + unsynch_mpq_manager m_qm; + pmanager m_pm; + anum_manager m_am; + bool m_incremental; + ctx(reslimit& rlim, params_ref const & p, bool incremental): + m_params(p), + m_rlimit(rlim), + m_allocator("nlsat"), + m_pm(rlim, m_qm, &m_allocator), + m_am(rlim, m_qm, p, &m_allocator), + m_incremental(incremental) + {} + }; + + struct solver::imp { + + + struct dconfig { + typedef imp value_manager; + typedef small_object_allocator allocator; + typedef void* value; + static const bool ref_count = false; + }; + + typedef dependency_manager assumption_manager; + typedef assumption_manager::dependency* _assumption_set; + + typedef obj_ref assumption_set_ref; + + + typedef polynomial::cache cache; + typedef ptr_vector interval_set_vector; + + + + ctx& m_ctx; + solver& m_solver; + reslimit& m_rlimit; + small_object_allocator& m_allocator; + bool m_incremental; + unsynch_mpq_manager& m_qm; + pmanager& m_pm; + cache m_cache; + anum_manager& m_am; + mutable assumption_manager m_asm; + assignment m_assignment, m_lo, m_hi; // partial interpretation + evaluator m_evaluator; + interval_set_manager & m_ism; + ineq_atom_table m_ineq_atoms; + root_atom_table m_root_atoms; + + + vector m_bounds; + + id_gen m_cid_gen; + clause_vector m_clauses; // set of clauses + clause_vector m_learned; // set of learned clauses + clause_vector m_valids; + + unsigned m_num_bool_vars; + atom_vector m_atoms; // bool_var -> atom + svector m_bvalues; // boolean assignment + unsigned_vector m_levels; // bool_var -> level + svector m_justifications; + vector m_bwatches; // bool_var (that are not attached to atoms) -> clauses where it is maximal + bool_vector m_dead; // mark dead boolean variables + id_gen m_bid_gen; + + simplify m_simplify; + + bool_vector m_is_int; // m_is_int[x] is true if variable is integer + vector m_watches; // var -> clauses where variable is maximal + interval_set_vector m_infeasible; // var -> to a set of interval where the variable cannot be assigned to. + atom_vector m_var2eq; // var -> to asserted equality + var_vector m_perm; // var -> var permutation of the variables + var_vector m_inv_perm; + // m_perm: internal -> external + // m_inv_perm: external -> internal + struct perm_display_var_proc : public display_var_proc { + var_vector & m_perm; + display_var_proc m_default_display_var; + display_var_proc const * m_proc; // display external var ids + perm_display_var_proc(var_vector & perm): + m_perm(perm), + m_proc(nullptr) { + } + std::ostream& operator()(std::ostream & out, var x) const override { + if (m_proc == nullptr) + m_default_display_var(out, x); + else + (*m_proc)(out, m_perm[x]); + return out; + } + }; + perm_display_var_proc m_display_var; + + display_assumption_proc const* m_display_assumption; + struct display_literal_assumption : public display_assumption_proc { + imp& i; + literal_vector const& lits; + display_literal_assumption(imp& i, literal_vector const& lits): i(i), lits(lits) {} + std::ostream& operator()(std::ostream& out, assumption a) const override { + if (lits.begin() <= a && a < lits.end()) { + out << *((literal const*)a); + } + else if (i.m_display_assumption) { + (*i.m_display_assumption)(out, a); + } + return out; + } + + }; + struct scoped_display_assumptions { + imp& i; + display_assumption_proc const* m_save; + scoped_display_assumptions(imp& i, display_assumption_proc const& p): i(i), m_save(i.m_display_assumption) { + i.m_display_assumption = &p; + } + ~scoped_display_assumptions() { + i.m_display_assumption = m_save; + } + }; + + explain m_explain; + + bool_var m_bk; // current Boolean variable we are processing + var m_xk; // current arith variable we are processing + + unsigned m_scope_lvl; + + struct bvar_assignment {}; + struct stage {}; + struct trail { + enum kind { BVAR_ASSIGNMENT, INFEASIBLE_UPDT, NEW_LEVEL, NEW_STAGE, UPDT_EQ }; + kind m_kind; + union { + bool_var m_b; + interval_set * m_old_set; + atom * m_old_eq; + }; + trail(bool_var b, bvar_assignment):m_kind(BVAR_ASSIGNMENT), m_b(b) {} + trail(interval_set * old_set):m_kind(INFEASIBLE_UPDT), m_old_set(old_set) {} + trail(bool s, stage):m_kind(s ? NEW_STAGE : NEW_LEVEL) {} + trail(atom * a):m_kind(UPDT_EQ), m_old_eq(a) {} + }; + svector m_trail; + + anum m_zero; + + // configuration + unsigned long long m_max_memory; + unsigned m_lazy; // how lazy the solver is: 0 - satisfy all learned clauses, 1 - process only unit and empty learned clauses, 2 - use only conflict clauses for resolving conflicts + bool m_simplify_cores; + bool m_reorder; + bool m_randomize; + bool m_random_order; + unsigned m_random_seed; + bool m_inline_vars; + bool m_log_lemmas; + bool m_check_lemmas; + unsigned m_max_conflicts; + unsigned m_lemma_count; + bool m_simple_check; + unsigned m_variable_ordering_strategy; + bool m_set_0_more; + bool m_cell_sample; + + struct stats { + unsigned m_simplifications; + unsigned m_restarts; + unsigned m_conflicts; + unsigned m_propagations; + unsigned m_decisions; + unsigned m_stages; + unsigned m_irrational_assignments; // number of irrational witnesses + void reset() { memset(this, 0, sizeof(*this)); } + stats() { reset(); } + }; + // statistics + stats m_stats; + + imp(solver& s, ctx& c): + m_ctx(c), + m_solver(s), + m_rlimit(c.m_rlimit), + m_allocator(c.m_allocator), + m_incremental(c.m_incremental), + m_qm(c.m_qm), + m_pm(c.m_pm), + m_cache(m_pm), + m_am(c.m_am), + m_asm(*this, m_allocator), + m_assignment(m_am), m_lo(m_am), m_hi(m_am), + m_evaluator(s, m_assignment, m_pm, m_allocator), + m_ism(m_evaluator.ism()), + m_num_bool_vars(0), + m_simplify(s, m_atoms, m_clauses, m_learned, m_pm), + m_display_var(m_perm), + m_display_assumption(nullptr), + m_explain(s, m_assignment, m_cache, m_atoms, m_var2eq, m_evaluator, nlsat_params(c.m_params).cell_sample()), + m_scope_lvl(0), + m_lemma(s), + m_lazy_clause(s), + m_lemma_assumptions(m_asm) { + updt_params(c.m_params); + reset_statistics(); + mk_true_bvar(); + m_lemma_count = 0; + } + + ~imp() { + clear(); + } + + void mk_true_bvar() { + bool_var b = mk_bool_var(); + SASSERT(b == true_bool_var); + literal true_lit(b, false); + mk_clause(1, &true_lit, false, nullptr); + } + + void updt_params(params_ref const & _p) { + nlsat_params p(_p); + m_max_memory = p.max_memory(); + m_lazy = p.lazy(); + m_simplify_cores = p.simplify_conflicts(); + bool min_cores = p.minimize_conflicts(); + m_reorder = p.reorder(); + m_randomize = p.randomize(); + m_max_conflicts = p.max_conflicts(); + m_random_order = p.shuffle_vars(); + m_random_seed = p.seed(); + m_inline_vars = p.inline_vars(); + m_log_lemmas = p.log_lemmas(); + m_check_lemmas = p.check_lemmas(); + m_variable_ordering_strategy = p.variable_ordering_strategy(); + + + m_cell_sample = p.cell_sample(); + + + m_ism.set_seed(m_random_seed); + m_explain.set_simplify_cores(m_simplify_cores); + m_explain.set_minimize_cores(min_cores); + m_explain.set_factor(p.factor()); + m_am.updt_params(p.p); + } + + void reset() { + m_explain.reset(); + m_lemma.reset(); + m_lazy_clause.reset(); + undo_until_size(0); + del_clauses(); + del_unref_atoms(); + m_cache.reset(); + m_assignment.reset(); + m_lo.reset(); + m_hi.reset(); + } + + void clear() { + m_explain.reset(); + m_lemma.reset(); + m_lazy_clause.reset(); + undo_until_size(0); + del_clauses(); + del_unref_atoms(); + } + + void checkpoint() { + if (!m_rlimit.inc()) throw solver_exception(m_rlimit.get_cancel_msg()); + if (memory::get_allocation_size() > m_max_memory) throw solver_exception(Z3_MAX_MEMORY_MSG); + } + + // ----------------------- + // + // Basic + // + // ----------------------- + + unsigned num_bool_vars() const { + return m_num_bool_vars; + } + + unsigned num_vars() const { + return m_is_int.size(); + } + + bool is_int(var x) const { + return m_is_int[x]; + } + + void inc_ref(assumption) {} + + void dec_ref(assumption) {} + + void inc_ref(_assumption_set a) { + if (a != nullptr) m_asm.inc_ref(a); + } + + void dec_ref(_assumption_set a) { + if (a != nullptr) m_asm.dec_ref(a); + } + + void inc_ref(bool_var b) { + if (b == null_bool_var) + return; + atom * a = m_atoms[b]; + if (a == nullptr) + return; + TRACE("ref", display(tout << "inc: " << b << " " << a->ref_count() << " ", *a) << "\n";); + a->inc_ref(); + } + + void inc_ref(literal l) { + inc_ref(l.var()); + } + + void dec_ref(bool_var b) { + if (b == null_bool_var) + return; + atom * a = m_atoms[b]; + if (a == nullptr) + return; + SASSERT(a->ref_count() > 0); + a->dec_ref(); + TRACE("ref", display(tout << "dec: " << b << " " << a->ref_count() << " ", *a) << "\n";); + if (a->ref_count() == 0) + del(a); + } + + void dec_ref(literal l) { + dec_ref(l.var()); + } + + bool is_arith_atom(bool_var b) const { return m_atoms[b] != nullptr; } + + bool is_arith_literal(literal l) const { return is_arith_atom(l.var()); } + + var max_var(poly const * p) const { + return m_pm.max_var(p); + } + + var max_var(bool_var b) const { + if (!is_arith_atom(b)) + return null_var; + else + return m_atoms[b]->max_var(); + } + + var max_var(literal l) const { + return max_var(l.var()); + } + + /** + \brief Return the maximum variable occurring in cls. + */ + var max_var(unsigned sz, literal const * cls) const { + var x = null_var; + for (unsigned i = 0; i < sz; i++) { + literal l = cls[i]; + if (is_arith_literal(l)) { + var y = max_var(l); + if (x == null_var || y > x) + x = y; + } + } + return x; + } + + var max_var(clause const & cls) const { + return max_var(cls.size(), cls.data()); + } + + /** + \brief Return the maximum Boolean variable occurring in cls. + */ + bool_var max_bvar(clause const & cls) const { + bool_var b = null_bool_var; + for (literal l : cls) { + if (b == null_bool_var || l.var() > b) + b = l.var(); + } + return b; + } + + /** + \brief Return the degree of the maximal variable of the given atom + */ + unsigned degree(atom const * a) const { + if (a->is_ineq_atom()) { + unsigned max = 0; + unsigned sz = to_ineq_atom(a)->size(); + var x = a->max_var(); + for (unsigned i = 0; i < sz; i++) { + unsigned d = m_pm.degree(to_ineq_atom(a)->p(i), x); + if (d > max) + max = d; + } + return max; + } + else { + return m_pm.degree(to_root_atom(a)->p(), a->max_var()); + } + } + + /** + \brief Return the degree of the maximal variable in c + */ + unsigned degree(clause const & c) const { + var x = max_var(c); + if (x == null_var) + return 0; + unsigned max = 0; + for (literal l : c) { + atom const * a = m_atoms[l.var()]; + if (a == nullptr) + continue; + unsigned d = degree(a); + if (d > max) + max = d; + } + return max; + } + + // ----------------------- + // + // Variable, Atoms, Clauses & Assumption creation + // + // ----------------------- + + bool_var mk_bool_var_core() { + bool_var b = m_bid_gen.mk(); + m_num_bool_vars++; + m_atoms .setx(b, nullptr, nullptr); + m_bvalues .setx(b, l_undef, l_undef); + m_levels .setx(b, UINT_MAX, UINT_MAX); + m_justifications.setx(b, null_justification, null_justification); + m_bwatches .setx(b, clause_vector(), clause_vector()); + m_dead .setx(b, false, true); + return b; + } + + bool_var mk_bool_var() { + return mk_bool_var_core(); + } + + var mk_var(bool is_int) { + var x = m_pm.mk_var(); + register_var(x, is_int); + return x; + } + void register_var(var x, bool is_int) { + SASSERT(x == num_vars()); + m_is_int. push_back(is_int); + m_watches. push_back(clause_vector()); + m_infeasible.push_back(nullptr); + m_var2eq. push_back(nullptr); + m_perm. push_back(x); + m_inv_perm. push_back(x); + SASSERT(m_is_int.size() == m_watches.size()); + SASSERT(m_is_int.size() == m_infeasible.size()); + SASSERT(m_is_int.size() == m_var2eq.size()); + SASSERT(m_is_int.size() == m_perm.size()); + SASSERT(m_is_int.size() == m_inv_perm.size()); + } + + bool_vector m_found_vars; + void vars(literal l, var_vector& vs) { + vs.reset(); + atom * a = m_atoms[l.var()]; + if (a == nullptr) { + + } + else if (a->is_ineq_atom()) { + unsigned sz = to_ineq_atom(a)->size(); + var_vector new_vs; + for (unsigned j = 0; j < sz; j++) { + m_found_vars.reset(); + m_pm.vars(to_ineq_atom(a)->p(j), new_vs); + for (unsigned i = 0; i < new_vs.size(); ++i) { + if (!m_found_vars.get(new_vs[i], false)) { + m_found_vars.setx(new_vs[i], true, false); + vs.push_back(new_vs[i]); + } + } + } + } + else { + m_pm.vars(to_root_atom(a)->p(), vs); + //vs.erase(max_var(to_root_atom(a)->p())); + vs.push_back(to_root_atom(a)->x()); + } + } + + void deallocate(ineq_atom * a) { + unsigned obj_sz = ineq_atom::get_obj_size(a->size()); + a->~ineq_atom(); + m_allocator.deallocate(obj_sz, a); + } + + void deallocate(root_atom * a) { + a->~root_atom(); + m_allocator.deallocate(sizeof(root_atom), a); + } + + void del(bool_var b) { + SASSERT(m_bwatches[b].empty()); + //SASSERT(m_bvalues[b] == l_undef); + m_num_bool_vars--; + m_dead[b] = true; + m_atoms[b] = nullptr; + m_bvalues[b] = l_undef; + m_bid_gen.recycle(b); + } + + void del(ineq_atom * a) { + CTRACE("nlsat_solver", a->ref_count() > 0, display(tout, *a) << "\n";); + // this triggers in too many benign cases: + // SASSERT(a->ref_count() == 0); + m_ineq_atoms.erase(a); + del(a->bvar()); + unsigned sz = a->size(); + for (unsigned i = 0; i < sz; i++) + m_pm.dec_ref(a->p(i)); + deallocate(a); + } + + void del(root_atom * a) { + SASSERT(a->ref_count() == 0); + m_root_atoms.erase(a); + del(a->bvar()); + m_pm.dec_ref(a->p()); + deallocate(a); + } + + void del(atom * a) { + if (a == nullptr) + return; + TRACE("nlsat_verbose", display(tout << "del: b" << a->m_bool_var << " " << a->ref_count() << " ", *a) << "\n";); + if (a->is_ineq_atom()) + del(to_ineq_atom(a)); + else + del(to_root_atom(a)); + } + + // Delete atoms with ref_count == 0 + void del_unref_atoms() { + for (auto* a : m_atoms) { + del(a); + } + } + + + ineq_atom* mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool& is_new, bool simplify) { + SASSERT(sz >= 1); + SASSERT(k == atom::LT || k == atom::GT || k == atom::EQ); + int sign = 1; + polynomial_ref p(m_pm); + ptr_buffer uniq_ps; + var max = null_var; + for (unsigned i = 0; i < sz; i++) { + p = m_pm.flip_sign_if_lm_neg(ps[i]); + if (p.get() != ps[i] && !is_even[i]) { + sign = -sign; + } + var curr_max = max_var(p.get()); + if (curr_max > max || max == null_var) + max = curr_max; + if (sz == 1 && simplify) { + if (sign < 0) + k = atom::flip(k); + sign = 1; + polynomial::manager::ineq_type t = polynomial::manager::ineq_type::EQ; + switch (k) { + case atom::EQ: t = polynomial::manager::ineq_type::EQ; break; + case atom::LT: t = polynomial::manager::ineq_type::LT; break; + case atom::GT: t = polynomial::manager::ineq_type::GT; break; + default: UNREACHABLE(); break; + } + polynomial::var_vector vars; + m_pm.vars(p, vars); + bool all_int = all_of(vars, [&](var x) { return is_int(x); }); + if (!all_int) + t = polynomial::manager::ineq_type::EQ; + m_pm.gcd_simplify(p, t); + } + uniq_ps.push_back(m_cache.mk_unique(p)); + TRACE("nlsat_table_bug", tout << "p: " << p << ", uniq: " << uniq_ps.back() << "\n";); + //verbose_stream() << "p: " << p.get() << ", uniq: " << uniq_ps.back() << "\n"; + } + void * mem = m_allocator.allocate(ineq_atom::get_obj_size(sz)); + if (sign < 0) + k = atom::flip(k); + ineq_atom * tmp_atom = new (mem) ineq_atom(k, sz, uniq_ps.data(), is_even, max); + ineq_atom * atom = m_ineq_atoms.insert_if_not_there(tmp_atom); + CTRACE("nlsat_table_bug", tmp_atom != atom, ineq_atom::hash_proc h; + tout << "mk_ineq_atom hash: " << h(tmp_atom) << "\n"; display(tout, *tmp_atom, m_display_var) << "\n";); + CTRACE("nlsat_table_bug", atom->max_var() != max, display(tout << "nonmax: ", *atom, m_display_var) << "\n";); + SASSERT(atom->max_var() == max); + is_new = (atom == tmp_atom); + if (is_new) { + for (unsigned i = 0; i < sz; i++) { + m_pm.inc_ref(atom->p(i)); + } + } + else { + deallocate(tmp_atom); + } + return atom; + } + + bool_var mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify = false) { + bool is_new = false; + ineq_atom* atom = mk_ineq_atom(k, sz, ps, is_even, is_new, simplify); + if (!is_new) { + return atom->bvar(); + } + else { + bool_var b = mk_bool_var_core(); + m_atoms[b] = atom; + atom->m_bool_var = b; + TRACE("nlsat_verbose", display(tout << "create: b" << atom->m_bool_var << " ", *atom) << "\n";); + return b; + } + } + + literal mk_ineq_literal(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify = false) { + SASSERT(k == atom::LT || k == atom::GT || k == atom::EQ); + bool is_const = true; + polynomial::manager::scoped_numeral cnst(m_pm.m()); + m_pm.m().set(cnst, 1); + for (unsigned i = 0; i < sz; ++i) { + if (m_pm.is_const(ps[i])) { + if (m_pm.is_zero(ps[i])) { + m_pm.m().set(cnst, 0); + is_const = true; + break; + } + auto const& c = m_pm.coeff(ps[i], 0); + m_pm.m().mul(cnst, c, cnst); + if (is_even[i] && m_pm.m().is_neg(c)) { + m_pm.m().neg(cnst); + } + } + else { + is_const = false; + } + } + if (is_const) { + if (m_pm.m().is_pos(cnst) && k == atom::GT) return true_literal; + if (m_pm.m().is_neg(cnst) && k == atom::LT) return true_literal; + if (m_pm.m().is_zero(cnst) && k == atom::EQ) return true_literal; + return false_literal; + } + return literal(mk_ineq_atom(k, sz, ps, is_even, simplify), false); + } + + bool_var mk_root_atom(atom::kind k, var x, unsigned i, poly * p) { + polynomial_ref p1(m_pm), uniq_p(m_pm); + p1 = m_pm.flip_sign_if_lm_neg(p); // flipping the sign of the polynomial will not change its roots. + uniq_p = m_cache.mk_unique(p1); + TRACE("nlsat_solver", tout << x << " " << p1 << " " << uniq_p << "\n";); + SASSERT(i > 0); + SASSERT(x >= max_var(p)); + SASSERT(k == atom::ROOT_LT || k == atom::ROOT_GT || k == atom::ROOT_EQ || k == atom::ROOT_LE || k == atom::ROOT_GE); + + void * mem = m_allocator.allocate(sizeof(root_atom)); + root_atom * new_atom = new (mem) root_atom(k, x, i, uniq_p); + root_atom * old_atom = m_root_atoms.insert_if_not_there(new_atom); + SASSERT(old_atom->max_var() == x); + if (old_atom != new_atom) { + deallocate(new_atom); + return old_atom->bvar(); + } + bool_var b = mk_bool_var_core(); + m_atoms[b] = new_atom; + new_atom->m_bool_var = b; + m_pm.inc_ref(new_atom->p()); + return b; + } + + void attach_clause(clause & cls) { + var x = max_var(cls); + if (x != null_var) { + m_watches[x].push_back(&cls); + } + else { + bool_var b = max_bvar(cls); + m_bwatches[b].push_back(&cls); + } + } + + void deattach_clause(clause & cls) { + var x = max_var(cls); + if (x != null_var) { + m_watches[x].erase(&cls); + } + else { + bool_var b = max_bvar(cls); + m_bwatches[b].erase(&cls); + } + } + + void deallocate(clause * cls) { + size_t obj_sz = clause::get_obj_size(cls->size()); + cls->~clause(); + m_allocator.deallocate(obj_sz, cls); + } + + void del_clause(clause * cls) { + deattach_clause(*cls); + m_cid_gen.recycle(cls->id()); + unsigned sz = cls->size(); + for (unsigned i = 0; i < sz; i++) + dec_ref((*cls)[i]); + _assumption_set a = static_cast<_assumption_set>(cls->assumptions()); + dec_ref(a); + deallocate(cls); + } + + void del_clause(clause * cls, clause_vector& clauses) { + clauses.erase(cls); + del_clause(cls); + } + + void del_clauses(ptr_vector & cs) { + for (clause* cp : cs) + del_clause(cp); + cs.reset(); + } + + void del_clauses() { + del_clauses(m_clauses); + del_clauses(m_learned); + del_clauses(m_valids); + } + + // We use a simple heuristic to sort literals + // - bool literals < arith literals + // - sort literals based on max_var + // - sort literal with the same max_var using degree + // break ties using the fact that ineqs are usually cheaper to process than eqs. + struct lit_lt { + imp & m; + lit_lt(imp & _m):m(_m) {} + + bool operator()(literal l1, literal l2) const { + atom * a1 = m.m_atoms[l1.var()]; + atom * a2 = m.m_atoms[l2.var()]; + if (a1 == nullptr && a2 == nullptr) + return l1.index() < l2.index(); + if (a1 == nullptr) + return true; + if (a2 == nullptr) + return false; + var x1 = a1->max_var(); + var x2 = a2->max_var(); + if (x1 < x2) + return true; + if (x1 > x2) + return false; + SASSERT(x1 == x2); + unsigned d1 = m.degree(a1); + unsigned d2 = m.degree(a2); + if (d1 < d2) + return true; + if (d1 > d2) + return false; + if (!a1->is_eq() && a2->is_eq()) + return true; + if (a1->is_eq() && !a2->is_eq()) + return false; + return l1.index() < l2.index(); + } + }; + + class scoped_bool_vars { + imp& s; + svector vec; + public: + scoped_bool_vars(imp& s):s(s) {} + ~scoped_bool_vars() { + for (bool_var v : vec) { + s.dec_ref(v); + } + } + void push_back(bool_var v) { + s.inc_ref(v); + vec.push_back(v); + } + bool_var const* begin() const { return vec.begin(); } + bool_var const* end() const { return vec.end(); } + bool_var operator[](bool_var v) const { return vec[v]; } + }; + + void check_lemma(unsigned n, literal const* cls, bool is_valid, assumption_set a) { + TRACE("nlsat", display(tout << "check lemma: ", n, cls) << "\n"; + display(tout);); + IF_VERBOSE(2, display(verbose_stream() << "check lemma " << (is_valid?"valid: ":"consequence: "), n, cls) << "\n"); + for (clause* c : m_learned) IF_VERBOSE(1, display(verbose_stream() << "lemma: ", *c) << "\n"); + scoped_suspend_rlimit _limit(m_rlimit); + ctx c(m_rlimit, m_ctx.m_params, m_ctx.m_incremental); + solver solver2(c); + imp& checker = *(solver2.m_imp); + checker.m_check_lemmas = false; + checker.m_log_lemmas = false; + checker.m_inline_vars = false; + + auto pconvert = [&](poly* p) { + return convert(m_pm, p, checker.m_pm); + }; + + // need to translate Boolean variables and literals + scoped_bool_vars tr(checker); + for (var x = 0; x < m_is_int.size(); ++x) { + checker.register_var(x, is_int(x)); + } + bool_var bv = 0; + tr.push_back(bv); + for (bool_var b = 1; b < m_atoms.size(); ++b) { + atom* a = m_atoms[b]; + if (a == nullptr) { + bv = checker.mk_bool_var(); + } + else if (a->is_ineq_atom()) { + ineq_atom& ia = *to_ineq_atom(a); + unsigned sz = ia.size(); + polynomial_ref_vector ps(checker.m_pm); + bool_vector is_even; + for (unsigned i = 0; i < sz; ++i) { + ps.push_back(pconvert(ia.p(i))); + is_even.push_back(ia.is_even(i)); + } + bv = checker.mk_ineq_atom(ia.get_kind(), sz, ps.data(), is_even.data()); + } + else if (a->is_root_atom()) { + root_atom& r = *to_root_atom(a); + if (r.x() >= max_var(r.p())) { + // permutation may be reverted after check completes, + // but then root atoms are not used in lemmas. + bv = checker.mk_root_atom(r.get_kind(), r.x(), r.i(), pconvert(r.p())); + } + } + else { + UNREACHABLE(); + } + tr.push_back(bv); + } + if (!is_valid) { + for (clause* c : m_clauses) { + if (!a && c->assumptions()) { + continue; + } + literal_vector lits; + for (literal lit : *c) { + lits.push_back(literal(tr[lit.var()], lit.sign())); + } + checker.mk_external_clause(lits.size(), lits.data(), nullptr); + } + } + for (unsigned i = 0; i < n; ++i) { + literal lit = cls[i]; + literal nlit(tr[lit.var()], !lit.sign()); + checker.mk_external_clause(1, &nlit, nullptr); + } + lbool r = checker.check(); + if (r == l_true) { + for (bool_var b : tr) { + literal lit(b, false); + IF_VERBOSE(0, checker.display(verbose_stream(), lit) << " := " << checker.value(lit) << "\n"); + TRACE("nlsat", checker.display(tout, lit) << " := " << checker.value(lit) << "\n";); + } + for (clause* c : m_learned) { + bool found = false; + for (literal lit: *c) { + literal tlit(tr[lit.var()], lit.sign()); + found |= checker.value(tlit) == l_true; + } + if (!found) { + IF_VERBOSE(0, display(verbose_stream() << "violdated clause: ", *c) << "\n"); + TRACE("nlsat", display(tout << "violdated clause: ", *c) << "\n";); + } + } + for (clause* c : m_valids) { + bool found = false; + for (literal lit: *c) { + literal tlit(tr[lit.var()], lit.sign()); + found |= checker.value(tlit) == l_true; + } + if (!found) { + IF_VERBOSE(0, display(verbose_stream() << "violdated tautology clause: ", *c) << "\n"); + TRACE("nlsat", display(tout << "violdated tautology clause: ", *c) << "\n";); + } + } + throw default_exception("lemma did not check"); + UNREACHABLE(); + } + } + + void log_lemma(std::ostream& out, clause const& cls) { + log_lemma(out, cls.size(), cls.data(), false); + } + + void log_lemma(std::ostream& out, unsigned n, literal const* cls, bool is_valid) { + ++m_lemma_count; + out << "(set-logic NRA)\n"; + if (is_valid) { + display_smt2_bool_decls(out); + display_smt2_arith_decls(out); + } + else + display_smt2(out); + for (unsigned i = 0; i < n; ++i) + display_smt2(out << "(assert ", ~cls[i]) << ")\n"; + display(out << "(echo \"#" << m_lemma_count << " ", n, cls) << "\")\n"; + out << "(check-sat)\n(reset)\n"; + + TRACE("nlsat", display(tout << "(echo \"#" << m_lemma_count << " ", n, cls) << "\")\n"); + } + + clause * mk_clause_core(unsigned num_lits, literal const * lits, bool learned, _assumption_set a) { + SASSERT(num_lits > 0); + unsigned cid = m_cid_gen.mk(); + void * mem = m_allocator.allocate(clause::get_obj_size(num_lits)); + clause * cls = new (mem) clause(cid, num_lits, lits, learned, a); + for (unsigned i = 0; i < num_lits; i++) + inc_ref(lits[i]); + inc_ref(a); + return cls; + } + + clause * mk_clause(unsigned num_lits, literal const * lits, bool learned, _assumption_set a) { + if (num_lits == 0) { + num_lits = 1; + lits = &false_literal; + } + SASSERT(num_lits > 0); + clause * cls = mk_clause_core(num_lits, lits, learned, a); + TRACE("nlsat_sort", display(tout << "mk_clause:\n", *cls) << "\n";); + std::sort(cls->begin(), cls->end(), lit_lt(*this)); + TRACE("nlsat", display(tout << " after sort:\n", *cls) << "\n";); + if (learned && m_log_lemmas) { + log_lemma(verbose_stream(), *cls); + } + if (learned && m_check_lemmas && false) { + check_lemma(cls->size(), cls->data(), false, cls->assumptions()); + } + if (learned) + m_learned.push_back(cls); + else + m_clauses.push_back(cls); + attach_clause(*cls); + return cls; + } + + void mk_external_clause(unsigned num_lits, literal const * lits, assumption a) { + _assumption_set as = nullptr; + if (a != nullptr) + as = m_asm.mk_leaf(a); + if (num_lits == 0) { + num_lits = 1; + lits = &false_literal; + } + mk_clause(num_lits, lits, false, as); + } + + // ----------------------- + // + // Search + // + // ----------------------- + + void save_assign_trail(bool_var b) { + m_trail.push_back(trail(b, bvar_assignment())); + } + + void save_set_updt_trail(interval_set * old_set) { + m_trail.push_back(trail(old_set)); + } + + void save_updt_eq_trail(atom * old_eq) { + m_trail.push_back(trail(old_eq)); + } + + void save_new_stage_trail() { + m_trail.push_back(trail(true, stage())); + } + + void save_new_level_trail() { + m_trail.push_back(trail(false, stage())); + } + + void undo_bvar_assignment(bool_var b) { + m_bvalues[b] = l_undef; + m_levels[b] = UINT_MAX; + del_jst(m_allocator, m_justifications[b]); + m_justifications[b] = null_justification; + if (m_atoms[b] == nullptr && b < m_bk) + m_bk = b; + } + + void undo_set_updt(interval_set * old_set) { + if (m_xk == null_var) + return; + var x = m_xk; + if (x < m_infeasible.size()) { + m_ism.dec_ref(m_infeasible[x]); + m_infeasible[x] = old_set; + } + } + + void undo_new_stage() { + if (m_xk == 0) { + m_xk = null_var; + } + else if (m_xk != null_var) { + m_xk--; + m_assignment.reset(m_xk); + } + } + + void undo_new_level() { + SASSERT(m_scope_lvl > 0); + m_scope_lvl--; + m_evaluator.pop(1); + } + + void undo_updt_eq(atom * a) { + if (m_var2eq.size() > m_xk) + m_var2eq[m_xk] = a; + } + + template + void undo_until(Predicate const & pred) { + while (pred() && !m_trail.empty()) { + trail & t = m_trail.back(); + switch (t.m_kind) { + case trail::BVAR_ASSIGNMENT: + undo_bvar_assignment(t.m_b); + break; + case trail::INFEASIBLE_UPDT: + undo_set_updt(t.m_old_set); + break; + case trail::NEW_STAGE: + undo_new_stage(); + break; + case trail::NEW_LEVEL: + undo_new_level(); + break; + case trail::UPDT_EQ: + undo_updt_eq(t.m_old_eq); + break; + default: + break; + } + m_trail.pop_back(); + } + } + + struct size_pred { + svector & m_trail; + unsigned m_old_size; + size_pred(svector & trail, unsigned old_size):m_trail(trail), m_old_size(old_size) {} + bool operator()() const { return m_trail.size() > m_old_size; } + }; + + // Keep undoing until trail has the given size + void undo_until_size(unsigned old_size) { + SASSERT(m_trail.size() >= old_size); + undo_until(size_pred(m_trail, old_size)); + } + + struct stage_pred { + var const & m_xk; + var m_target; + stage_pred(var const & xk, var target):m_xk(xk), m_target(target) {} + bool operator()() const { return m_xk != m_target; } + }; + + // Keep undoing until stage is new_xk + void undo_until_stage(var new_xk) { + undo_until(stage_pred(m_xk, new_xk)); + } + + struct level_pred { + unsigned const & m_scope_lvl; + unsigned m_new_lvl; + level_pred(unsigned const & scope_lvl, unsigned new_lvl):m_scope_lvl(scope_lvl), m_new_lvl(new_lvl) {} + bool operator()() const { return m_scope_lvl > m_new_lvl; } + }; + + // Keep undoing until level is new_lvl + void undo_until_level(unsigned new_lvl) { + undo_until(level_pred(m_scope_lvl, new_lvl)); + } + + struct unassigned_pred { + bool_var m_b; + svector const & m_bvalues; + unassigned_pred(svector const & bvalues, bool_var b): + m_b(b), + m_bvalues(bvalues) {} + bool operator()() const { return m_bvalues[m_b] != l_undef; } + }; + + // Keep undoing until b is unassigned + void undo_until_unassigned(bool_var b) { + undo_until(unassigned_pred(m_bvalues, b)); + SASSERT(m_bvalues[b] == l_undef); + } + + struct true_pred { + bool operator()() const { return true; } + }; + + void undo_until_empty() { + undo_until(true_pred()); + } + + /** + \brief Create a new scope level + */ + void new_level() { + m_evaluator.push(); + m_scope_lvl++; + save_new_level_trail(); + } + + /** + \brief Return the value of the given literal that was assigned by the search + engine. + */ + lbool assigned_value(literal l) const { + bool_var b = l.var(); + if (l.sign()) + return ~m_bvalues[b]; + else + return m_bvalues[b]; + } + + /** + \brief Assign literal using the given justification + */ + void assign(literal l, justification j) { + TRACE("nlsat_assign", + display(tout << "assigning literal: ", l); + display(tout << " <- ", j);); + + SASSERT(assigned_value(l) == l_undef); + SASSERT(j != null_justification); + SASSERT(!j.is_null()); + if (j.is_decision()) + m_stats.m_decisions++; + else + m_stats.m_propagations++; + bool_var b = l.var(); + m_bvalues[b] = to_lbool(!l.sign()); + m_levels[b] = m_scope_lvl; + m_justifications[b] = j; + save_assign_trail(b); + updt_eq(b, j); + TRACE("nlsat_assign", tout << "b" << b << " -> " << m_bvalues[b] << "\n";); + } + + /** + \brief Create a "case-split" + */ + void decide(literal l) { + new_level(); + assign(l, decided_justification); + } + + /** + \brief Return the value of a literal as defined in Dejan and Leo's paper. + */ + lbool value(literal l) { + lbool val = assigned_value(l); + if (val != l_undef) { + TRACE("nlsat_verbose", display(tout << " assigned value " << val << " for ", l) << "\n";); + return val; + } + bool_var b = l.var(); + atom * a = m_atoms[b]; + if (a == nullptr) { + TRACE("nlsat_verbose", display(tout << " no atom for ", l) << "\n";); + return l_undef; + } + var max = a->max_var(); + if (!m_assignment.is_assigned(max)) { + TRACE("nlsat_verbose", display(tout << " maximal variable not assigned ", l) << "\n";); + return l_undef; + } + val = to_lbool(m_evaluator.eval(a, l.sign())); + TRACE("nlsat_verbose", display(tout << " evaluated value " << val << " for ", l) << "\n";); + TRACE("value_bug", tout << "value of: "; display(tout, l); tout << " := " << val << "\n"; + tout << "xk: " << m_xk << ", a->max_var(): " << a->max_var() << "\n"; + display_assignment(tout);); + return val; + } + + /** + \brief Return true if the given clause is already satisfied in the current partial interpretation. + */ + bool is_satisfied(clause const & cls) const { + for (literal l : cls) { + if (const_cast(this)->value(l) == l_true) { + TRACE("value_bug:", tout << l << " := true\n";); + return true; + } + } + return false; + } + + /** + \brief Return true if the given clause is false in the current partial interpretation. + */ + bool is_inconsistent(unsigned sz, literal const * cls) { + for (unsigned i = 0; i < sz; i++) { + if (value(cls[i]) != l_false) { + TRACE("is_inconsistent", tout << "literal is not false:\n"; display(tout, cls[i]); tout << "\n";); + return false; + } + } + return true; + } + + /** + \brief Process a clauses that contains only Boolean literals. + */ + bool process_boolean_clause(clause const & cls) { + SASSERT(m_xk == null_var); + unsigned num_undef = 0; + unsigned first_undef = UINT_MAX; + unsigned sz = cls.size(); + for (unsigned i = 0; i < sz; i++) { + literal l = cls[i]; + SASSERT(m_atoms[l.var()] == nullptr); + SASSERT(value(l) != l_true); + if (value(l) == l_false) + continue; + SASSERT(value(l) == l_undef); + num_undef++; + if (first_undef == UINT_MAX) + first_undef = i; + } + if (num_undef == 0) + return false; + SASSERT(first_undef != UINT_MAX); + if (num_undef == 1) + assign(cls[first_undef], mk_clause_jst(&cls)); // unit clause + else + decide(cls[first_undef]); + return true; + } + + /** + \brief assign l to true, because l + (justification of) s is infeasible in RCF in the current interpretation. + */ + literal_vector core; + ptr_vector clauses; + void R_propagate(literal l, interval_set const * s, bool include_l = true) { + m_ism.get_justifications(s, core, clauses); + if (include_l) + core.push_back(~l); + auto j = mk_lazy_jst(m_allocator, core.size(), core.data(), clauses.size(), clauses.data()); + TRACE("nlsat_resolve", display(tout, j); display_eval(tout << "evaluated:", j)); + assign(l, j); + SASSERT(value(l) == l_true); + } + + /** + \brief m_infeasible[m_xk] <- m_infeasible[m_xk] Union s + */ + void updt_infeasible(interval_set const * s) { + SASSERT(m_xk != null_var); + interval_set * xk_set = m_infeasible[m_xk]; + save_set_updt_trail(xk_set); + interval_set_ref new_set(m_ism); + TRACE("nlsat_inf_set", tout << "updating infeasible set\n"; m_ism.display(tout, xk_set) << "\n"; m_ism.display(tout, s) << "\n";); + new_set = m_ism.mk_union(s, xk_set); + TRACE("nlsat_inf_set", tout << "new infeasible set:\n"; m_ism.display(tout, new_set) << "\n";); + SASSERT(!m_ism.is_full(new_set)); + m_ism.inc_ref(new_set); + m_infeasible[m_xk] = new_set; + } + + /** + \brief Update m_var2eq mapping. + */ + void updt_eq(bool_var b, justification j) { + if (!m_simplify_cores) + return; + if (m_bvalues[b] != l_true) + return; + atom * a = m_atoms[b]; + if (a == nullptr || a->get_kind() != atom::EQ || to_ineq_atom(a)->size() > 1 || to_ineq_atom(a)->is_even(0)) + return; + switch (j.get_kind()) { + case justification::CLAUSE: + if (j.get_clause()->assumptions() != nullptr) return; + break; + case justification::LAZY: + if (j.get_lazy()->num_clauses() > 0) return; + if (j.get_lazy()->num_lits() > 0) return; + break; + default: + break; + } + var x = m_xk; + SASSERT(a->max_var() == x); + SASSERT(x != null_var); + if (m_var2eq[x] != 0 && degree(m_var2eq[x]) <= degree(a)) + return; // we only update m_var2eq if the new equality has smaller degree + TRACE("nlsat_simplify_core", tout << "Saving equality for "; m_display_var(tout, x) << " (x" << x << ") "; + tout << "scope-lvl: " << scope_lvl() << "\n"; display(tout, literal(b, false)) << "\n"; + display(tout, j); + ); + save_updt_eq_trail(m_var2eq[x]); + m_var2eq[x] = a; + } + + /** + \brief Process a clause that contains nonlinear arithmetic literals + + If satisfy_learned is true, then learned clauses are satisfied even if m_lazy > 0 + */ + bool process_arith_clause(clause const & cls, bool satisfy_learned) { + if (!satisfy_learned && m_lazy >= 2 && cls.is_learned()) { + TRACE("nlsat", tout << "skip learned\n";); + return true; // ignore lemmas in super lazy mode + } + SASSERT(m_xk == max_var(cls)); + unsigned num_undef = 0; // number of undefined literals + unsigned first_undef = UINT_MAX; // position of the first undefined literal + interval_set_ref first_undef_set(m_ism); // infeasible region of the first undefined literal + interval_set * xk_set = m_infeasible[m_xk]; // current set of infeasible interval for current variable + SASSERT(!m_ism.is_full(xk_set)); + for (unsigned idx = 0; idx < cls.size(); ++idx) { + literal l = cls[idx]; + checkpoint(); + if (value(l) == l_false) + continue; + if (value(l) == l_true) + return true; // could happen if clause is a tautology + CTRACE("nlsat", max_var(l) != m_xk || value(l) != l_undef, display(tout); + tout << "xk: " << m_xk << ", max_var(l): " << max_var(l) << ", l: "; display(tout, l) << "\n"; + display(tout, cls) << "\n";); + SASSERT(value(l) == l_undef); + SASSERT(max_var(l) == m_xk); + bool_var b = l.var(); + atom * a = m_atoms[b]; + SASSERT(a != nullptr); + interval_set_ref curr_set(m_ism); + curr_set = m_evaluator.infeasible_intervals(a, l.sign(), &cls); + TRACE("nlsat_inf_set", tout << "infeasible set for literal: "; display(tout, l); tout << "\n"; m_ism.display(tout, curr_set); tout << "\n"; + display(tout, cls) << "\n";); + if (m_ism.is_empty(curr_set)) { + TRACE("nlsat_inf_set", tout << "infeasible set is empty, found literal\n";); + R_propagate(l, nullptr); + SASSERT(is_satisfied(cls)); + return true; + } + if (m_ism.is_full(curr_set)) { + TRACE("nlsat_inf_set", tout << "infeasible set is R, skip literal\n";); + R_propagate(~l, nullptr); + continue; + } + if (m_ism.subset(curr_set, xk_set)) { + TRACE("nlsat_inf_set", tout << "infeasible set is a subset of current set, found literal\n";); + R_propagate(l, xk_set); + return true; + } + interval_set_ref tmp(m_ism); + tmp = m_ism.mk_union(curr_set, xk_set); + if (m_ism.is_full(tmp)) { + TRACE("nlsat_inf_set", tout << "infeasible set + current set = R, skip literal\n"; + display(tout, cls) << "\n"; + m_ism.display(tout, tmp); tout << "\n"; + ); + R_propagate(~l, tmp, false); + continue; + } + num_undef++; + if (first_undef == UINT_MAX) { + first_undef = idx; + first_undef_set = curr_set; + } + } + TRACE("nlsat_inf_set", tout << "num_undef: " << num_undef << "\n";); + if (num_undef == 0) + return false; + SASSERT(first_undef != UINT_MAX); + if (num_undef == 1) { + // unit clause + assign(cls[first_undef], mk_clause_jst(&cls)); + updt_infeasible(first_undef_set); + } + else if ( satisfy_learned || + !cls.is_learned() /* must always satisfy input clauses */ || + m_lazy == 0 /* if not in lazy mode, we also satiffy lemmas */) { + decide(cls[first_undef]); + updt_infeasible(first_undef_set); + } + else { + TRACE("nlsat_lazy", tout << "skipping clause, satisfy_learned: " << satisfy_learned << ", cls.is_learned(): " << cls.is_learned() + << ", lazy: " << m_lazy << "\n";); + } + return true; + } + + /** + \brief Try to satisfy the given clause. Return true if succeeded. + + If satisfy_learned is true, then (arithmetic) learned clauses are satisfied even if m_lazy > 0 + */ + bool process_clause(clause const & cls, bool satisfy_learned) { + if (is_satisfied(cls)) + return true; + if (m_xk == null_var) + return process_boolean_clause(cls); + else + return process_arith_clause(cls, satisfy_learned); + } + + /** + \brief Try to satisfy the given "set" of clauses. + Return 0, if the set was satisfied, or the violating clause otherwise + */ + clause * process_clauses(clause_vector const & cs) { + for (clause* c : cs) { + if (!process_clause(*c, false)) + return c; + } + return nullptr; // succeeded + } + + /** + \brief Make sure m_bk is the first unassigned pure Boolean variable. + Set m_bk == null_bool_var if there is no unassigned pure Boolean variable. + */ + void peek_next_bool_var() { + while (m_bk < m_atoms.size()) { + if (!m_dead[m_bk] && m_atoms[m_bk] == nullptr && m_bvalues[m_bk] == l_undef) { + return; + } + m_bk++; + } + m_bk = null_bool_var; + } + + /** + \brief Create a new stage. See Dejan and Leo's paper. + */ + void new_stage() { + m_stats.m_stages++; + save_new_stage_trail(); + if (m_xk == null_var) + m_xk = 0; + else + m_xk++; + } + + /** + \brief Assign m_xk + */ + void select_witness() { + scoped_anum w(m_am); + SASSERT(!m_ism.is_full(m_infeasible[m_xk])); + m_ism.pick_in_complement(m_infeasible[m_xk], is_int(m_xk), w, m_randomize); + TRACE("nlsat", + tout << "infeasible intervals: "; m_ism.display(tout, m_infeasible[m_xk]); tout << "\n"; + tout << "assigning "; m_display_var(tout, m_xk) << "(x" << m_xk << ") -> " << w << "\n";); + TRACE("nlsat_root", tout << "value as root object: "; m_am.display_root(tout, w); tout << "\n";); + if (!m_am.is_rational(w)) + m_stats.m_irrational_assignments++; + m_assignment.set_core(m_xk, w); + } + + + + bool is_satisfied() { + if (m_bk == null_bool_var && m_xk >= num_vars()) { + TRACE("nlsat", tout << "found model\n"; display_assignment(tout);); + fix_patch(); + SASSERT(check_satisfied(m_clauses)); + return true; // all variables were assigned, and all clauses were satisfied. + } + else { + return false; + } + } + + + /** + \brief main procedure + */ + lbool search() { + TRACE("nlsat", tout << "starting search...\n"; display(tout); tout << "\nvar order:\n"; display_vars(tout);); + TRACE("nlsat_proof", tout << "ASSERTED\n"; display(tout);); + TRACE("nlsat_proof_sk", tout << "ASSERTED\n"; display_abst(tout);); + TRACE("nlsat_mathematica", display_mathematica(tout);); + TRACE("nlsat", display_smt2(tout);); + m_bk = 0; + m_xk = null_var; + + while (true) { + if (should_reorder()) + do_reorder(); + +#if 0 + if (should_gc()) + do_gc(); +#endif + + if (should_simplify()) + do_simplify(); + + CASSERT("nlsat", check_satisfied()); + if (m_xk == null_var) { + peek_next_bool_var(); + if (m_bk == null_bool_var) + new_stage(); // move to arith vars + } + else { + new_stage(); // peek next arith var + } + TRACE("nlsat_bug", tout << "xk: x" << m_xk << " bk: b" << m_bk << "\n";); + if (is_satisfied()) { + return l_true; + } + while (true) { + TRACE("nlsat_verbose", tout << "processing variable "; + if (m_xk != null_var) { + m_display_var(tout, m_xk); tout << " " << m_watches[m_xk].size(); + } + else { + tout << m_bwatches[m_bk].size() << " boolean b" << m_bk; + } + tout << "\n";); + checkpoint(); + clause * conflict_clause; + if (m_xk == null_var) + conflict_clause = process_clauses(m_bwatches[m_bk]); + else + conflict_clause = process_clauses(m_watches[m_xk]); + if (conflict_clause == nullptr) + break; + if (!resolve(*conflict_clause)) + return l_false; + if (m_stats.m_conflicts >= m_max_conflicts) + return l_undef; + log(); + } + + if (m_xk == null_var) { + if (m_bvalues[m_bk] == l_undef) { + decide(literal(m_bk, true)); + m_bk++; + } + } + else { + select_witness(); + } + } + } + + void gc() { + if (m_learned.size() <= 4*m_clauses.size()) + return; + reset_watches(); + reinit_cache(); + unsigned j = 0; + for (unsigned i = 0; i < m_learned.size(); ++i) { + auto cls = m_learned[i]; + if (i - j < m_clauses.size() && cls->size() > 1 && !cls->is_active()) + del_clause(cls); + else { + m_learned[j++] = cls; + cls->set_active(false); + } + } + m_learned.shrink(j); + reattach_arith_clauses(m_clauses); + reattach_arith_clauses(m_learned); + } + + + bool should_gc() { + return m_learned.size() > 10 * m_clauses.size(); + } + + void do_gc() { + undo_to_base(); + gc(); + } + + void undo_to_base() { + init_search(); + m_bk = 0; + m_xk = null_var; + } + + unsigned m_restart_threshold = 10000; + bool should_reorder() { + return m_stats.m_conflicts > 0 && m_stats.m_conflicts % m_restart_threshold == 0; + } + + void do_reorder() { + undo_to_base(); + m_stats.m_restarts++; + m_stats.m_conflicts++; + if (m_reordered) + restore_order(); + apply_reorder(); + } + + bool m_did_simplify = false; + bool should_simplify() { + return + !m_did_simplify && m_inline_vars && + !m_incremental && m_stats.m_conflicts > 100; + } + + void do_simplify() { + undo_to_base(); + m_did_simplify = true; + m_simplify(); + } + + unsigned m_next_conflict = 100; + void log() { + if (m_stats.m_conflicts != 1 && m_stats.m_conflicts < m_next_conflict) + return; + m_next_conflict += 100; + IF_VERBOSE(2, verbose_stream() << "(nlsat :conflicts " << m_stats.m_conflicts + << " :decisions " << m_stats.m_decisions + << " :propagations " << m_stats.m_propagations + << " :clauses " << m_clauses.size() + << " :learned " << m_learned.size() << ")\n"); + } + + + lbool search_check() { + lbool r = l_undef; + m_stats.m_conflicts = 0; + m_stats.m_restarts = 0; + m_next_conflict = 0; + while (true) { + r = search(); + if (r != l_true) + break; + ++m_stats.m_restarts; + vector> bounds; + + for (var x = 0; x < num_vars(); x++) { + if (is_int(x) && m_assignment.is_assigned(x) && !m_am.is_int(m_assignment.value(x))) { + scoped_anum v(m_am), vlo(m_am); + v = m_assignment.value(x); + rational lo; + m_am.int_lt(v, vlo); + if (!m_am.is_int(vlo)) + continue; + m_am.to_rational(vlo, lo); + // derive tight bounds. + while (true) { + lo++; + if (!m_am.gt(v, lo.to_mpq())) { + lo--; + break; + } + } + bounds.push_back(std::make_pair(x, lo)); + } + } + if (bounds.empty()) + break; + + gc(); + if (m_stats.m_restarts % 10 == 0) { + if (m_reordered) + restore_order(); + apply_reorder(); + } + + init_search(); + IF_VERBOSE(2, verbose_stream() << "(nlsat-b&b :conflicts " << m_stats.m_conflicts + << " :decisions " << m_stats.m_decisions + << " :propagations " << m_stats.m_propagations + << " :clauses " << m_clauses.size() + << " :learned " << m_learned.size() << ")\n"); + for (auto const& b : bounds) { + var x = b.first; + rational lo = b.second; + rational hi = lo + 1; // rational::one(); + bool is_even = false; + polynomial_ref p(m_pm); + rational one(1); + m_lemma.reset(); + p = m_pm.mk_linear(1, &one, &x, -lo); + poly* p1 = p.get(); + m_lemma.push_back(~mk_ineq_literal(atom::GT, 1, &p1, &is_even)); + p = m_pm.mk_linear(1, &one, &x, -hi); + poly* p2 = p.get(); + m_lemma.push_back(~mk_ineq_literal(atom::LT, 1, &p2, &is_even)); + + // perform branch and bound + clause * cls = mk_clause(m_lemma.size(), m_lemma.data(), true, nullptr); + IF_VERBOSE(4, display(verbose_stream(), *cls) << "\n"); + if (cls) { + TRACE("nlsat", display(tout << "conflict " << lo << " " << hi, *cls); tout << "\n";); + } + } + } + return r; + } + + bool m_reordered = false; + bool simple_check() { + literal_vector learned_unit; + simple_checker checker(m_pm, m_am, m_clauses, learned_unit, m_atoms, m_is_int.size()); + if (!checker()) + return false; + for (unsigned i = 0, sz = learned_unit.size(); i < sz; ++i) { + clause *cla = mk_clause(1, &learned_unit[i], true, nullptr); + if (m_atoms[learned_unit[i].var()] == nullptr) { + assign(learned_unit[i], mk_clause_jst(cla)); + } + } + return true; + } + + + void run_variable_ordering_strategy() { + TRACE("reorder", tout << "runing vos: " << m_variable_ordering_strategy << '\n';); + + unsigned num = num_vars(); + vos_var_info_collector vos_collector(m_pm, m_atoms, num, m_variable_ordering_strategy); + vos_collector.collect(m_clauses); + vos_collector.collect(m_learned); + + var_vector perm; + vos_collector(perm); + reorder(perm.size(), perm.data()); + } + + void apply_reorder() { + m_reordered = false; + if (!can_reorder()) + ; + else if (m_random_order) { + shuffle_vars(); + m_reordered = true; + } + else if (m_reorder) { + heuristic_reorder(); + m_reordered = true; + } + } + + lbool check() { + + if (m_simple_check) { + if (!simple_check()) { + TRACE("simple_check", tout << "real unsat\n";); + return l_false; + } + TRACE("simple_checker_learned", + tout << "simple check done\n"; + ); + } + + TRACE("nlsat_smt2", display_smt2(tout);); + TRACE("nlsat_fd", tout << "is_full_dimensional: " << is_full_dimensional() << "\n";); + init_search(); + m_explain.set_full_dimensional(is_full_dimensional()); + bool reordered = false; + + + if (!can_reorder()) { + + } + else if (m_variable_ordering_strategy > 0) { + run_variable_ordering_strategy(); + reordered = true; + } + else if (m_random_order) { + shuffle_vars(); + reordered = true; + } + else if (m_reorder) { + heuristic_reorder(); + reordered = true; + } + sort_watched_clauses(); + lbool r = search_check(); + CTRACE("nlsat_model", r == l_true, tout << "model before restore order\n"; display_assignment(tout);); + if (reordered) { + restore_order(); + } + CTRACE("nlsat_model", r == l_true, tout << "model\n"; display_assignment(tout);); + CTRACE("nlsat", r == l_false, display(tout << "unsat\n");); + SASSERT(r != l_true || check_satisfied(m_clauses)); + return r; + } + + void init_search() { + undo_until_empty(); + while (m_scope_lvl > 0) { + undo_new_level(); + } + m_xk = null_var; + for (unsigned i = 0; i < m_bvalues.size(); ++i) { + m_bvalues[i] = l_undef; + } + m_assignment.reset(); + } + + lbool check(literal_vector& assumptions) { + literal_vector result; + unsigned sz = assumptions.size(); + literal const* ptr = assumptions.data(); + for (unsigned i = 0; i < sz; ++i) { + mk_external_clause(1, ptr+i, (assumption)(ptr+i)); + } + display_literal_assumption dla(*this, assumptions); + scoped_display_assumptions _scoped_display(*this, dla); + lbool r = check(); + + if (r == l_false) { + // collect used literals from m_lemma_assumptions + vector deps; + get_core(deps); + for (unsigned i = 0; i < deps.size(); ++i) { + literal const* lp = (literal const*)(deps[i]); + if (ptr <= lp && lp < ptr + sz) { + result.push_back(*lp); + } + } + } + collect(assumptions, m_clauses); + collect(assumptions, m_learned); + del_clauses(m_valids); + if (m_check_lemmas) { + for (clause* c : m_learned) { + check_lemma(c->size(), c->data(), false, nullptr); + } + } + +#if 0 + for (clause* c : m_learned) { + IF_VERBOSE(0, display(verbose_stream() << "KEEP: ", c->size(), c->c_ptr()) << "\n"); + } +#endif + assumptions.reset(); + assumptions.append(result); + return r; + } + + void get_core(vector& deps) { + m_asm.linearize(m_lemma_assumptions.get(), deps); + } + + void collect(literal_vector const& assumptions, clause_vector& clauses) { + unsigned j = 0; + for (clause * c : clauses) { + if (collect(assumptions, *c)) { + del_clause(c); + } + else { + clauses[j++] = c; + } + } + clauses.shrink(j); + } + + bool collect(literal_vector const& assumptions, clause const& c) { + unsigned sz = assumptions.size(); + literal const* ptr = assumptions.data(); + _assumption_set asms = static_cast<_assumption_set>(c.assumptions()); + if (asms == nullptr) { + return false; + } + vector deps; + m_asm.linearize(asms, deps); + for (auto dep : deps) { + if (ptr <= dep && dep < ptr + sz) { + return true; + } + } + return false; + } + + // ----------------------- + // + // Conflict Resolution + // + // ----------------------- + svector m_marks; // bool_var -> bool temp mark used during conflict resolution + unsigned m_num_marks; + scoped_literal_vector m_lemma; + scoped_literal_vector m_lazy_clause; + assumption_set_ref m_lemma_assumptions; // assumption tracking + + // Conflict resolution invariant: a marked literal is in m_lemma or on the trail stack. + + bool check_marks() { + for (unsigned m : m_marks) { + (void)m; + SASSERT(m == 0); + } + return true; + } + + unsigned scope_lvl() const { return m_scope_lvl; } + + bool is_marked(bool_var b) const { return m_marks.get(b, 0) == 1; } + + void mark(bool_var b) { m_marks.setx(b, 1, 0); } + + void reset_mark(bool_var b) { m_marks[b] = 0; } + + void reset_marks() { + for (auto const& l : m_lemma) { + reset_mark(l.var()); + } + } + + void process_antecedent(literal antecedent) { + checkpoint(); + bool_var b = antecedent.var(); + TRACE("nlsat_resolve", display(tout << "resolving antecedent: ", antecedent) << "\n";); + if (assigned_value(antecedent) == l_undef) { + checkpoint(); + // antecedent must be false in the current arith interpretation + SASSERT(value(antecedent) == l_false || m_rlimit.is_canceled()); + if (!is_marked(b)) { + SASSERT(is_arith_atom(b) && max_var(b) < m_xk); // must be in a previous stage + TRACE("nlsat_resolve", tout << "literal is unassigned, but it is false in arithmetic interpretation, adding it to lemma\n";); + mark(b); + m_lemma.push_back(antecedent); + } + return; + } + + unsigned b_lvl = m_levels[b]; + TRACE("nlsat_resolve", tout << "b_lvl: " << b_lvl << ", is_marked(b): " << is_marked(b) << ", m_num_marks: " << m_num_marks << "\n";); + if (!is_marked(b)) { + mark(b); + if (b_lvl == scope_lvl() /* same level */ && max_var(b) == m_xk /* same stage */) { + TRACE("nlsat_resolve", tout << "literal is in the same level and stage, increasing marks\n";); + m_num_marks++; + } + else { + TRACE("nlsat_resolve", tout << "previous level or stage, adding literal to lemma\n"; + tout << "max_var(b): " << max_var(b) << ", m_xk: " << m_xk << ", lvl: " << b_lvl << ", scope_lvl: " << scope_lvl() << "\n";); + m_lemma.push_back(antecedent); + } + } + } + + void resolve_clause(bool_var b, unsigned sz, literal const * c) { + TRACE("nlsat_proof", tout << "resolving "; if (b != null_bool_var) display_atom(tout, b) << "\n"; display(tout, sz, c); tout << "\n";); + TRACE("nlsat_proof_sk", tout << "resolving "; if (b != null_bool_var) tout << "b" << b; tout << "\n"; display_abst(tout, sz, c); tout << "\n";); + + for (unsigned i = 0; i < sz; i++) { + if (c[i].var() != b) + process_antecedent(c[i]); + } + } + + void resolve_clause(bool_var b, clause & c) { + TRACE("nlsat_resolve", tout << "resolving clause "; if (b != null_bool_var) tout << "for b: " << b << "\n"; display(tout, c) << "\n";); + c.set_active(true); + resolve_clause(b, c.size(), c.data()); + m_lemma_assumptions = m_asm.mk_join(static_cast<_assumption_set>(c.assumptions()), m_lemma_assumptions); + } + + void resolve_lazy_justification(bool_var b, lazy_justification const & jst) { + TRACE("nlsat_resolve", tout << "resolving lazy_justification for b" << b << "\n";); + unsigned sz = jst.num_lits(); + + // Dump lemma as Mathematica formula that must be true, + // if the current interpretation (really) makes the core in jst infeasible. + TRACE("nlsat_mathematica", + tout << "assignment lemma\n"; + literal_vector core; + for (unsigned i = 0; i < sz; i++) { + core.push_back(~jst.lit(i)); + } + display_mathematica_lemma(tout, core.size(), core.data(), true);); + + m_lazy_clause.reset(); + m_explain(jst.num_lits(), jst.lits(), m_lazy_clause); + for (unsigned i = 0; i < sz; i++) + m_lazy_clause.push_back(~jst.lit(i)); + + // lazy clause is a valid clause + TRACE("nlsat_mathematica", display_mathematica_lemma(tout, m_lazy_clause.size(), m_lazy_clause.data());); + TRACE("nlsat_proof_sk", tout << "theory lemma\n"; display_abst(tout, m_lazy_clause.size(), m_lazy_clause.data()); tout << "\n";); + TRACE("nlsat_resolve", + tout << "m_xk: " << m_xk << ", "; m_display_var(tout, m_xk) << "\n"; + tout << "new valid clause:\n"; + display(tout, m_lazy_clause.size(), m_lazy_clause.data()) << "\n";); + + + if (m_log_lemmas) + log_lemma(verbose_stream(), m_lazy_clause.size(), m_lazy_clause.data(), true); + + if (m_check_lemmas) { + check_lemma(m_lazy_clause.size(), m_lazy_clause.data(), true, nullptr); + m_valids.push_back(mk_clause_core(m_lazy_clause.size(), m_lazy_clause.data(), false, nullptr)); + } + +#ifdef Z3DEBUG + { + unsigned sz = m_lazy_clause.size(); + for (unsigned i = 0; i < sz; i++) { + literal l = m_lazy_clause[i]; + if (l.var() != b) { + if (value(l) != l_false) + display(verbose_stream() << value(l) << " ", 1, &l); + SASSERT(value(l) == l_false || m_rlimit.is_canceled()); + } + else { + SASSERT(value(l) == l_true || m_rlimit.is_canceled()); + SASSERT(!l.sign() || m_bvalues[b] == l_false); + SASSERT(l.sign() || m_bvalues[b] == l_true); + } + } + } +#endif + checkpoint(); + resolve_clause(b, m_lazy_clause.size(), m_lazy_clause.data()); + + for (unsigned i = 0; i < jst.num_clauses(); ++i) { + clause const& c = jst.clause(i); + TRACE("nlsat", display(tout << "adding clause assumptions ", c) << "\n";); + m_lemma_assumptions = m_asm.mk_join(static_cast<_assumption_set>(c.assumptions()), m_lemma_assumptions); + } + } + + /** + \brief Return true if all literals in ls are from previous stages. + */ + bool only_literals_from_previous_stages(unsigned num, literal const * ls) const { + for (unsigned i = 0; i < num; i++) { + if (max_var(ls[i]) == m_xk) + return false; + } + return true; + } + + /** + \brief Return the maximum scope level in ls. + + \pre This method assumes value(ls[i]) is l_false for i in [0, num) + */ + unsigned max_scope_lvl(unsigned num, literal const * ls) { + unsigned max = 0; + for (unsigned i = 0; i < num; i++) { + literal l = ls[i]; + bool_var b = l.var(); + SASSERT(value(ls[i]) == l_false); + if (assigned_value(l) == l_false) { + unsigned lvl = m_levels[b]; + if (lvl > max) + max = lvl; + } + else { + // l must be a literal from a previous stage that is false in the current interpretation + SASSERT(assigned_value(l) == l_undef); + SASSERT(max_var(b) != null_var); + SASSERT(m_xk != null_var); + SASSERT(max_var(b) < m_xk); + } + } + return max; + } + + /** + \brief Remove literals of the given lvl (that are in the current stage) from lemma. + + \pre This method assumes value(ls[i]) is l_false for i in [0, num) + */ + void remove_literals_from_lvl(scoped_literal_vector & lemma, unsigned lvl) { + TRACE("nlsat_resolve", tout << "removing literals from lvl: " << lvl << " and stage " << m_xk << "\n";); + unsigned sz = lemma.size(); + unsigned j = 0; + for (unsigned i = 0; i < sz; i++) { + literal l = lemma[i]; + bool_var b = l.var(); + SASSERT(is_marked(b)); + SASSERT(value(lemma[i]) == l_false); + if (assigned_value(l) == l_false && m_levels[b] == lvl && max_var(b) == m_xk) { + m_num_marks++; + continue; + } + lemma.set(j, l); + j++; + } + lemma.shrink(j); + } + + /** + \brief Return true if it is a Boolean lemma. + */ + bool is_bool_lemma(unsigned sz, literal const * ls) const { + for (unsigned i = 0; i < sz; i++) { + if (m_atoms[ls[i].var()] != nullptr) + return false; + } + return true; + } + + + /** + Return the maximal decision level in lemma for literals in the first sz-1 positions that + are at the same stage. If all these literals are from previous stages, + we just backtrack the current level. + */ + unsigned find_new_level_arith_lemma(unsigned sz, literal const * lemma) { + SASSERT(!is_bool_lemma(sz, lemma)); + unsigned new_lvl = 0; + bool found_lvl = false; + for (unsigned i = 0; i < sz - 1; i++) { + literal l = lemma[i]; + if (max_var(l) == m_xk) { + bool_var b = l.var(); + if (!found_lvl) { + found_lvl = true; + new_lvl = m_levels[b]; + } + else { + if (m_levels[b] > new_lvl) + new_lvl = m_levels[b]; + } + } + } + SASSERT(!found_lvl || new_lvl < scope_lvl()); + if (!found_lvl) { + TRACE("nlsat_resolve", tout << "fail to find new lvl, using previous one\n";); + new_lvl = scope_lvl() - 1; + } + return new_lvl; + } + + struct scoped_reset_marks { + imp& i; + scoped_reset_marks(imp& i):i(i) {} + ~scoped_reset_marks() { if (i.m_num_marks > 0) { i.m_num_marks = 0; for (char& m : i.m_marks) m = 0; } } + }; + + + /** + \brief Return true if the conflict was solved. + */ + bool resolve(clause & conflict) { + clause * conflict_clause = &conflict; + m_lemma_assumptions = nullptr; + start: + SASSERT(check_marks()); + TRACE("nlsat_proof", tout << "STARTING RESOLUTION\n";); + TRACE("nlsat_proof_sk", tout << "STARTING RESOLUTION\n";); + m_stats.m_conflicts++; + TRACE("nlsat", tout << "resolve, conflicting clause:\n"; display(tout, *conflict_clause) << "\n"; + tout << "xk: "; if (m_xk != null_var) m_display_var(tout, m_xk); else tout << ""; tout << "\n"; + tout << "scope_lvl: " << scope_lvl() << "\n"; + tout << "current assignment\n"; display_assignment(tout);); + + m_num_marks = 0; + m_lemma.reset(); + m_lemma_assumptions = nullptr; + scoped_reset_marks _sr(*this); + resolve_clause(null_bool_var, *conflict_clause); + + unsigned top = m_trail.size(); + bool found_decision; + while (true) { + found_decision = false; + while (m_num_marks > 0) { + checkpoint(); + SASSERT(top > 0); + trail & t = m_trail[top-1]; + SASSERT(t.m_kind != trail::NEW_STAGE); // we only mark literals that are in the same stage + if (t.m_kind == trail::BVAR_ASSIGNMENT) { + bool_var b = t.m_b; + if (is_marked(b)) { + TRACE("nlsat_resolve", tout << "found marked: b" << b << "\n"; display_atom(tout, b) << "\n";); + m_num_marks--; + reset_mark(b); + justification jst = m_justifications[b]; + switch (jst.get_kind()) { + case justification::CLAUSE: + resolve_clause(b, *(jst.get_clause())); + break; + case justification::LAZY: + resolve_lazy_justification(b, *(jst.get_lazy())); + break; + case justification::DECISION: + SASSERT(m_num_marks == 0); + found_decision = true; + TRACE("nlsat_resolve", tout << "found decision\n";); + m_lemma.push_back(literal(b, m_bvalues[b] == l_true)); + break; + default: + UNREACHABLE(); + break; + } + } + } + top--; + } + + // m_lemma is an implicating clause after backtracking current scope level. + if (found_decision) + break; + + // If lemma only contains literals from previous stages, then we can stop. + // We make progress by returning to a previous stage with additional information (new lemma) + // that forces us to select a new partial interpretation + if (only_literals_from_previous_stages(m_lemma.size(), m_lemma.data())) + break; + + // Conflict does not depend on the current decision, and it is still in the current stage. + // We should find + // - the maximal scope level in the lemma + // - remove literal assigned in the scope level from m_lemma + // - backtrack to this level + // - and continue conflict resolution from there + // - we must bump m_num_marks for literals removed from m_lemma + unsigned max_lvl = max_scope_lvl(m_lemma.size(), m_lemma.data()); + TRACE("nlsat_resolve", tout << "conflict does not depend on current decision, backtracking to level: " << max_lvl << "\n";); + SASSERT(max_lvl < scope_lvl()); + remove_literals_from_lvl(m_lemma, max_lvl); + undo_until_level(max_lvl); + top = m_trail.size(); + TRACE("nlsat_resolve", tout << "scope_lvl: " << scope_lvl() << " num marks: " << m_num_marks << "\n";); + SASSERT(scope_lvl() == max_lvl); + } + + TRACE("nlsat_proof", tout << "New lemma\n"; display(tout, m_lemma); tout << "\n=========================\n";); + TRACE("nlsat_proof_sk", tout << "New lemma\n"; display_abst(tout, m_lemma); tout << "\n=========================\n";); + + if (m_lemma.empty()) { + TRACE("nlsat", tout << "empty clause generated\n";); + return false; // problem is unsat, empty clause was generated + } + + reset_marks(); // remove marks from the literals in m_lemmas. + TRACE("nlsat", tout << "new lemma:\n"; display(tout, m_lemma.size(), m_lemma.data()); tout << "\n"; + tout << "found_decision: " << found_decision << "\n";); + + if (m_check_lemmas) { + check_lemma(m_lemma.size(), m_lemma.data(), false, m_lemma_assumptions.get()); + } + + if (m_log_lemmas) + log_lemma(verbose_stream(), m_lemma.size(), m_lemma.data(), false); + + // There are two possibilities: + // 1) m_lemma contains only literals from previous stages, and they + // are false in the current interpretation. We make progress + // by returning to a previous stage with additional information (new clause) + // that forces us to select a new partial interpretation + // >>> Return to some previous stage (we may also backjump many decisions and stages). + // + // 2) m_lemma contains at most one literal from the current level (the last literal). + // Moreover, this literal was a decision, but the new lemma forces it to + // be assigned to a different value. + // >>> In this case, we remain in the same stage but, we add a new asserted literal + // in a previous scope level. We may backjump many decisions. + // + unsigned sz = m_lemma.size(); + clause * new_cls = nullptr; + if (!found_decision) { + // Case 1) + // We just have to find the maximal variable in m_lemma, and return to that stage + // Remark: the lemma may contain only boolean literals, in this case new_max_var == null_var; + var new_max_var = max_var(sz, m_lemma.data()); + TRACE("nlsat_resolve", tout << "backtracking to stage: " << new_max_var << ", curr: " << m_xk << "\n";); + undo_until_stage(new_max_var); + SASSERT(m_xk == new_max_var); + new_cls = mk_clause(sz, m_lemma.data(), true, m_lemma_assumptions.get()); + TRACE("nlsat", tout << "new_level: " << scope_lvl() << "\nnew_stage: " << new_max_var << "\n"; + if (new_max_var != null_var) m_display_var(tout, new_max_var) << "\n";); + } + else { + SASSERT(scope_lvl() >= 1); + // Case 2) + if (is_bool_lemma(m_lemma.size(), m_lemma.data())) { + // boolean lemma, we just backtrack until the last literal is unassigned. + bool_var max_bool_var = m_lemma[m_lemma.size()-1].var(); + undo_until_unassigned(max_bool_var); + } + else { + // We must find the maximal decision level in literals in the first sz-1 positions that + // are at the same stage. If all these literals are from previous stages, + // we just backtrack the current level. + unsigned new_lvl = find_new_level_arith_lemma(m_lemma.size(), m_lemma.data()); + TRACE("nlsat", tout << "backtracking to new level: " << new_lvl << ", curr: " << m_scope_lvl << "\n";); + undo_until_level(new_lvl); + } + + if (lemma_is_clause(*conflict_clause)) { + TRACE("nlsat", tout << "found decision literal in conflict clause\n";); + VERIFY(process_clause(*conflict_clause, true)); + return true; + } + new_cls = mk_clause(sz, m_lemma.data(), true, m_lemma_assumptions.get()); + } + NLSAT_VERBOSE(display(verbose_stream(), *new_cls) << "\n";); + if (!process_clause(*new_cls, true)) { + TRACE("nlsat", tout << "new clause triggered another conflict, restarting conflict resolution...\n"; + display(tout, *new_cls) << "\n"; + ); + // we are still in conflict + conflict_clause = new_cls; + goto start; + } + TRACE("nlsat_resolve_done", display_assignment(tout);); + return true; + } + + bool lemma_is_clause(clause const& cls) const { + bool same = (m_lemma.size() == cls.size()); + for (unsigned i = 0; same && i < m_lemma.size(); ++i) { + same = m_lemma[i] == cls[i]; + } + return same; + } + + + // ----------------------- + // + // Debugging + // + // ----------------------- + + bool check_watches() const { +#ifdef Z3DEBUG + for (var x = 0; x < num_vars(); x++) { + clause_vector const & cs = m_watches[x]; + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) { + SASSERT(max_var(*(cs[i])) == x); + } + } +#endif + return true; + } + + bool check_bwatches() const { +#ifdef Z3DEBUG + for (bool_var b = 0; b < m_bwatches.size(); b++) { + clause_vector const & cs = m_bwatches[b]; + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) { + clause const & c = *(cs[i]); + SASSERT(max_var(c) == null_var); + SASSERT(max_bvar(c) == b); + } + } +#endif + return true; + } + + bool check_invariant() const { + SASSERT(check_watches()); + SASSERT(check_bwatches()); + return true; + } + + bool check_satisfied(clause_vector const & cs) const { + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) { + clause const & c = *(cs[i]); + if (!is_satisfied(c)) { + TRACE("nlsat", tout << "not satisfied\n"; display(tout, c); tout << "\n";); + return false; + } + } + return true; + } + + bool check_satisfied() const { + TRACE("nlsat", tout << "bk: b" << m_bk << ", xk: x" << m_xk << "\n"; if (m_xk != null_var) { m_display_var(tout, m_xk); tout << "\n"; }); + unsigned num = m_atoms.size(); + if (m_bk != null_bool_var) + num = m_bk; + for (bool_var b = 0; b < num; b++) { + if (!check_satisfied(m_bwatches[b])) { + UNREACHABLE(); + return false; + } + } + if (m_xk != null_var) { + for (var x = 0; x < m_xk; x++) { + if (!check_satisfied(m_watches[x])) { + UNREACHABLE(); + return false; + } + } + } + return true; + } + + // ----------------------- + // + // Statistics + // + // ----------------------- + + void collect_statistics(statistics & st) { + st.update("nlsat conflicts", m_stats.m_conflicts); + st.update("nlsat propagations", m_stats.m_propagations); + st.update("nlsat decisions", m_stats.m_decisions); + st.update("nlsat restarts", m_stats.m_restarts); + st.update("nlsat stages", m_stats.m_stages); + st.update("nlsat simplifications", m_stats.m_simplifications); + st.update("nlsat irrational assignments", m_stats.m_irrational_assignments); + } + + void reset_statistics() { + m_stats.reset(); + } + + // ----------------------- + // + // Variable reordering + // + // ----------------------- + + struct var_info_collector { + pmanager & pm; + atom_vector const & m_atoms; + var_vector m_shuffle; + unsigned_vector m_max_degree; + unsigned_vector m_num_occs; + + var_info_collector(pmanager & _pm, atom_vector const & atoms, unsigned num_vars): + pm(_pm), + m_atoms(atoms) { + m_max_degree.resize(num_vars, 0); + m_num_occs.resize(num_vars, 0); + } + + var_vector m_vars; + void collect(poly * p) { + m_vars.reset(); + pm.vars(p, m_vars); + unsigned sz = m_vars.size(); + for (unsigned i = 0; i < sz; i++) { + var x = m_vars[i]; + unsigned k = pm.degree(p, x); + m_num_occs[x]++; + if (k > m_max_degree[x]) + m_max_degree[x] = k; + } + } + + void collect(literal l) { + bool_var b = l.var(); + atom * a = m_atoms[b]; + if (a == nullptr) + return; + if (a->is_ineq_atom()) { + unsigned sz = to_ineq_atom(a)->size(); + for (unsigned i = 0; i < sz; i++) { + collect(to_ineq_atom(a)->p(i)); + } + } + else { + collect(to_root_atom(a)->p()); + } + } + + void collect(clause const & c) { + unsigned sz = c.size(); + for (unsigned i = 0; i < sz; i++) + collect(c[i]); + } + + void collect(clause_vector const & cs) { + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) + collect(*(cs[i])); + } + + std::ostream& display(std::ostream & out, display_var_proc const & proc) { + unsigned sz = m_num_occs.size(); + for (unsigned i = 0; i < sz; i++) { + proc(out, i); out << " -> " << m_max_degree[i] << " : " << m_num_occs[i] << "\n"; + } + return out; + } + }; + + struct reorder_lt { + var_info_collector const & m_info; + reorder_lt(var_info_collector const & info):m_info(info) {} + bool operator()(var x, var y) const { + // high degree first + if (m_info.m_max_degree[x] < m_info.m_max_degree[y]) + return false; + if (m_info.m_max_degree[x] > m_info.m_max_degree[y]) + return true; + // more constrained first + if (m_info.m_num_occs[x] < m_info.m_num_occs[y]) + return false; + if (m_info.m_num_occs[x] > m_info.m_num_occs[y]) + return true; + return m_info.m_shuffle[x] < m_info.m_shuffle[y]; + } + }; + + // Order variables by degree and number of occurrences + void heuristic_reorder() { + unsigned num = num_vars(); + var_info_collector collector(m_pm, m_atoms, num); + collector.collect(m_clauses); + collector.collect(m_learned); + init_shuffle(collector.m_shuffle); + TRACE("nlsat_reorder", collector.display(tout, m_display_var);); + var_vector new_order; + for (var x = 0; x < num; x++) + new_order.push_back(x); + + std::sort(new_order.begin(), new_order.end(), reorder_lt(collector)); + TRACE("nlsat_reorder", + tout << "new order: "; for (unsigned i = 0; i < num; i++) tout << new_order[i] << " "; tout << "\n";); + var_vector perm; + perm.resize(num, 0); + for (var x = 0; x < num; x++) { + perm[new_order[x]] = x; + } + reorder(perm.size(), perm.data()); + SASSERT(check_invariant()); + } + + void init_shuffle(var_vector& p) { + unsigned num = num_vars(); + for (var x = 0; x < num; x++) + p.push_back(x); + + random_gen r(++m_random_seed); + shuffle(p.size(), p.data(), r); + } + + void shuffle_vars() { + var_vector p; + init_shuffle(p); + reorder(p.size(), p.data()); + } + + bool can_reorder() const { + return all_of(m_learned, [&](clause* c) { return !has_root_atom(*c); }) + && all_of(m_clauses, [&](clause* c) { return !has_root_atom(*c); }); + } + + /** + \brief Reorder variables using the giving permutation. + p maps internal variables to their new positions + */ + + + void reorder(unsigned sz, var const * p) { + + remove_learned_roots(); + SASSERT(can_reorder()); + TRACE("nlsat_reorder", tout << "solver before variable reorder\n"; display(tout); + display_vars(tout); + tout << "\npermutation:\n"; + for (unsigned i = 0; i < sz; i++) tout << p[i] << " "; tout << "\n"; + ); + // verbose_stream() << "\npermutation: " << p[0] << " count " << count << " " << m_rlimit.is_canceled() << "\n"; + reinit_cache(); + SASSERT(num_vars() == sz); + TRACE("nlsat_bool_assignment_bug", tout << "before reset watches\n"; display_bool_assignment(tout);); + reset_watches(); + assignment new_assignment(m_am); + for (var x = 0; x < num_vars(); x++) { + if (m_assignment.is_assigned(x)) + new_assignment.set(p[x], m_assignment.value(x)); + } + var_vector new_inv_perm; + new_inv_perm.resize(sz); + // the undo_until_size(0) statement erases the Boolean assignment. + // undo_until_size(0) + undo_until_stage(null_var); + m_cache.reset(); +#ifdef Z3DEBUG + for (var x = 0; x < num_vars(); x++) { + SASSERT(m_watches[x].empty()); + } +#endif + // update m_perm mapping + for (unsigned ext_x = 0; ext_x < sz; ext_x++) { + // p: internal -> new pos + // m_perm: internal -> external + // m_inv_perm: external -> internal + new_inv_perm[ext_x] = p[m_inv_perm[ext_x]]; + m_perm.set(new_inv_perm[ext_x], ext_x); + } + bool_vector is_int; + is_int.swap(m_is_int); + for (var x = 0; x < sz; x++) { + m_is_int.setx(p[x], is_int[x], false); + SASSERT(m_infeasible[x] == 0); + } + m_inv_perm.swap(new_inv_perm); +#ifdef Z3DEBUG + for (var x = 0; x < num_vars(); x++) { + SASSERT(x == m_inv_perm[m_perm[x]]); + SASSERT(m_watches[x].empty()); + } +#endif + m_pm.rename(sz, p); + for (auto& b : m_bounds) + b.x = p[b.x]; + TRACE("nlsat_bool_assignment_bug", tout << "before reinit cache\n"; display_bool_assignment(tout);); + reinit_cache(); + m_assignment.swap(new_assignment); + reattach_arith_clauses(m_clauses); + reattach_arith_clauses(m_learned); + TRACE("nlsat_reorder", tout << "solver after variable reorder\n"; display(tout); display_vars(tout);); + } + + + /** + \brief Restore variable order. + */ + void restore_order() { + // m_perm: internal -> external + // m_inv_perm: external -> internal + var_vector p; + p.append(m_perm); + reorder(p.size(), p.data()); +#ifdef Z3DEBUG + for (var x = 0; x < num_vars(); x++) { + SASSERT(m_perm[x] == x); + SASSERT(m_inv_perm[x] == x); + } +#endif + } + + /** + \brief After variable reordering some lemmas containing root atoms may be ill-formed. + */ + void remove_learned_roots() { + unsigned j = 0; + for (clause* c : m_learned) { + if (has_root_atom(*c)) { + del_clause(c); + } + else { + m_learned[j++] = c; + } + } + m_learned.shrink(j); + } + + /** + \brief Return true if the clause contains an ill formed root atom + */ + bool has_root_atom(clause const & c) const { + for (literal lit : c) { + bool_var b = lit.var(); + atom * a = m_atoms[b]; + if (a && a->is_root_atom()) + return true; + } + return false; + } + + /** + \brief reinsert all polynomials in the unique cache + */ + void reinit_cache() { + reinit_cache(m_clauses); + reinit_cache(m_learned); + for (atom* a : m_atoms) + reinit_cache(a); + } + void reinit_cache(clause_vector const & cs) { + for (clause* c : cs) + reinit_cache(*c); + } + void reinit_cache(clause const & c) { + for (literal l : c) + reinit_cache(l); + } + void reinit_cache(literal l) { + bool_var b = l.var(); + reinit_cache(m_atoms[b]); + } + void reinit_cache(atom* a) { + if (a == nullptr) { + + } + else if (a->is_ineq_atom()) { + var max = 0; + unsigned sz = to_ineq_atom(a)->size(); + for (unsigned i = 0; i < sz; i++) { + poly * p = to_ineq_atom(a)->p(i); + VERIFY(m_cache.mk_unique(p) == p); + var x = m_pm.max_var(p); + if (x > max) + max = x; + } + a->m_max_var = max; + } + else { + poly * p = to_root_atom(a)->p(); + VERIFY(m_cache.mk_unique(p) == p); + a->m_max_var = m_pm.max_var(p); + } + } + + void reset_watches() { + unsigned num = num_vars(); + for (var x = 0; x < num; x++) { + m_watches[x].reset(); + } + } + + void reattach_arith_clauses(clause_vector const & cs) { + for (clause* cp : cs) { + var x = max_var(*cp); + if (x != null_var) + m_watches[x].push_back(cp); + } + } + + // ----------------------- + // + // Solver initialization + // + // ----------------------- + + struct degree_lt { + unsigned_vector & m_degrees; + degree_lt(unsigned_vector & ds):m_degrees(ds) {} + bool operator()(unsigned i1, unsigned i2) const { + if (m_degrees[i1] < m_degrees[i2]) + return true; + if (m_degrees[i1] > m_degrees[i2]) + return false; + return i1 < i2; + } + }; + + unsigned_vector m_cs_degrees; + unsigned_vector m_cs_p; + void sort_clauses_by_degree(unsigned sz, clause ** cs) { + if (sz <= 1) + return; + TRACE("nlsat_reorder_clauses", tout << "before:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); + m_cs_degrees.reset(); + m_cs_p.reset(); + for (unsigned i = 0; i < sz; i++) { + m_cs_p.push_back(i); + m_cs_degrees.push_back(degree(*(cs[i]))); + } + std::sort(m_cs_p.begin(), m_cs_p.end(), degree_lt(m_cs_degrees)); + TRACE("nlsat_reorder_clauses", tout << "permutation: "; ::display(tout, m_cs_p.begin(), m_cs_p.end()); tout << "\n";); + apply_permutation(sz, cs, m_cs_p.data()); + TRACE("nlsat_reorder_clauses", tout << "after:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); + } + + + struct degree_lit_num_lt { + unsigned_vector & m_degrees; + unsigned_vector & m_lit_num; + degree_lit_num_lt(unsigned_vector & ds, unsigned_vector & ln) : + m_degrees(ds), + m_lit_num(ln) { + } + bool operator()(unsigned i1, unsigned i2) const { + if (m_lit_num[i1] == 1 && m_lit_num[i2] > 1) + return true; + if (m_lit_num[i1] > 1 && m_lit_num[i2] == 1) + return false; + if (m_degrees[i1] != m_degrees[i2]) + return m_degrees[i1] < m_degrees[i2]; + if (m_lit_num[i1] != m_lit_num[i2]) + return m_lit_num[i1] < m_lit_num[i2]; + return i1 < i2; + } + }; + + unsigned_vector m_dl_degrees; + unsigned_vector m_dl_lit_num; + unsigned_vector m_dl_p; + void sort_clauses_by_degree_lit_num(unsigned sz, clause ** cs) { + if (sz <= 1) + return; + TRACE("nlsat_reorder_clauses", tout << "before:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); + m_dl_degrees.reset(); + m_dl_lit_num.reset(); + m_dl_p.reset(); + for (unsigned i = 0; i < sz; i++) { + m_dl_degrees.push_back(degree(*(cs[i]))); + m_dl_lit_num.push_back(cs[i]->size()); + m_dl_p.push_back(i); + } + std::sort(m_dl_p.begin(), m_dl_p.end(), degree_lit_num_lt(m_dl_degrees, m_dl_lit_num)); + TRACE("nlsat_reorder_clauses", tout << "permutation: "; ::display(tout, m_dl_p.begin(), m_dl_p.end()); tout << "\n";); + apply_permutation(sz, cs, m_dl_p.data()); + TRACE("nlsat_reorder_clauses", tout << "after:\n"; for (unsigned i = 0; i < sz; i++) { display(tout, *(cs[i])); tout << "\n"; }); + } + + void sort_watched_clauses() { + unsigned num = num_vars(); + for (unsigned i = 0; i < num; i++) { + clause_vector & ws = m_watches[i]; + // sort_clauses_by_degree(ws.size(), ws.data()); + if (m_simple_check) { + sort_clauses_by_degree_lit_num(ws.size(), ws.data()); + } + else { + sort_clauses_by_degree(ws.size(), ws.data()); + } + } + } + + // ----------------------- + // + // Full dimensional + // + // A problem is in the full dimensional fragment if it does + // not contain equalities or non-strict inequalities. + // + // ----------------------- + + bool is_full_dimensional(literal l) const { + atom * a = m_atoms[l.var()]; + if (a == nullptr) + return true; + switch (a->get_kind()) { + case atom::EQ: return l.sign(); + case atom::LT: return !l.sign(); + case atom::GT: return !l.sign(); + case atom::ROOT_EQ: return l.sign(); + case atom::ROOT_LT: return !l.sign(); + case atom::ROOT_GT: return !l.sign(); + case atom::ROOT_LE: return l.sign(); + case atom::ROOT_GE: return l.sign(); + default: + UNREACHABLE(); + return false; + } + } + + bool is_full_dimensional(clause const & c) const { + for (literal l : c) { + if (!is_full_dimensional(l)) + return false; + } + return true; + } + + bool is_full_dimensional(clause_vector const & cs) const { + for (clause* c : cs) { + if (!is_full_dimensional(*c)) + return false; + } + return true; + } + + bool is_full_dimensional() const { + return is_full_dimensional(m_clauses); + } + + + // ----------------------- + // + // Simplification + // + // ----------------------- + + // solve simple equalities + // TBD WU-Reit decomposition? + + // - elim_unconstrained + // - solve_eqs + // - fm + + /** + \brief isolate variables in unit equalities. + Assume a clause is c == v*p + q + and the context implies p > 0 + + replace v by -q/p + remove clause c, + The for other occurrences of v, + replace v*r + v*v*r' > 0 by + by p*p*v*r + p*p*v*v*r' > 0 + by p*q*r + q*q*r' > 0 + + The method ignores lemmas and assumes constraints don't use roots. + */ + + + + // Eliminated variables are tracked in m_bounds. + // Each element in m_bounds tracks the eliminated variable and an upper or lower bound + // that has to be satisfied. Variables that are eliminated through equalities are tracked + // by non-strict bounds. A satisfiable solution is required to provide an evaluation that + // is consistent with the bounds. For equalities, the non-strict lower or upper bound can + // always be assigned as a value to the variable. + + void fix_patch() { + m_lo.reset(); m_hi.reset(); + for (auto& b : m_bounds) + m_assignment.reset(b.x); + for (unsigned i = m_bounds.size(); i-- > 0; ) + fix_patch(m_bounds[i]); + } + + // x is unassigned, lo < x -> x <- lo + 1 + // x is unassigned, x < hi -> x <- hi - 1 + // x is unassigned, lo <= x -> x <- lo + // x is unassigned, x <= hi -> x <- hi + // x is assigned above hi, lo is strict lo < x < hi -> set x <- (lo + hi)/2 + // x is assigned below hi, above lo -> no-op + // x is assigned below lo, hi is strict lo < x < hi -> set x <-> (lo + hi)/2 + // x is assigned above hi, x <= hi -> x <- hi + // x is assigned blow lo, lo <= x -> x <- lo + void fix_patch(bound_constraint& b) { + var x = b.x; + scoped_anum Av(m_am), Bv(m_am), val(m_am); + m_pm.eval(b.A, m_assignment, Av); + m_pm.eval(b.B, m_assignment, Bv); + m_am.neg(Bv); + val = Bv / Av; + // Ax >= B + // is-lower : A > 0 + // is-upper: A < 0 + // x <- B / A + bool is_lower = m_am.is_pos(Av); + TRACE("nlsat", + m_display_var(tout << "patch v" << x << " ", x) << "\n"; + if (m_assignment.is_assigned(x)) m_am.display(tout << "previous value: ", m_assignment.value(x)); tout << "\n"; + m_am.display(tout << "updated value: ", val); tout << "\n"; + ); + + if (!m_assignment.is_assigned(x)) { + if (!b.is_strict) + m_assignment.set_core(x, val); + else if (is_lower) + m_assignment.set_core(x, val + 1); + else + m_assignment.set_core(x, val - 1); + } + else { + auto& aval = m_assignment.value(x); + if (is_lower) { + // lo < value(x), lo < x -> x is unchanged + if (b.is_strict && m_am.lt(val, aval)) + ; + else if (!b.is_strict && m_am.le(val, aval)) + ; + else if (!b.is_strict) + m_assignment.set_core(x, val); + // aval < lo < x, hi is unassigned: x <- lo + 1 + else if (!m_hi.is_assigned(x)) + m_assignment.set_core(x, val + 1); + // aval < lo < x, hi is assigned: x <- (lo + hi) / 2 + else { + scoped_anum mid(m_am); + m_am.add(m_hi.value(x), val, mid); + mid = mid / 2; + m_assignment.set_core(x, mid); + } + } + else { + // dual to lower bounds + if (b.is_strict && m_am.lt(aval, val)) + ; + else if (!b.is_strict && m_am.le(aval, val)) + ; + else if (!b.is_strict) + m_assignment.set_core(x, val); + else if (!m_lo.is_assigned(x)) + m_assignment.set_core(x, val - 1); + else { + scoped_anum mid(m_am); + m_am.add(m_lo.value(x), val, mid); + mid = mid / 2; + m_assignment.set_core(x, mid); + } + } + } + + if (is_lower) { + if (!m_lo.is_assigned(x) || m_am.lt(m_lo.value(x), val)) + m_lo.set_core(x, val); + } + else { + if (!m_hi.is_assigned(x) || m_am.gt(m_hi.value(x), val)) + m_hi.set_core(x, val); + } + } + + bool is_unit_ineq(clause const& c) const { + return + c.size() == 1 && + m_atoms[c[0].var()] && + m_atoms[c[0].var()]->is_ineq_atom(); + } + + bool is_unit_eq(clause const& c) const { + return + is_unit_ineq(c) && + !c[0].sign() && + m_atoms[c[0].var()]->is_eq(); + } + + /** + \brief determine whether the clause is a comparison v > k or v < k', where k >= 0 or k' <= 0. + */ + lbool is_cmp0(clause const& c, var& v) { + if (!is_unit_ineq(c)) + return l_undef; + literal lit = c[0]; + ineq_atom const& a = *to_ineq_atom(m_atoms[lit.var()]); + bool sign = lit.sign(); + poly * p0; + if (!is_single_poly(a, p0)) + return l_undef; + if (m_pm.is_var(p0, v)) { + if (!sign && a.get_kind() == atom::GT) { + return l_true; + } + if (!sign && a.get_kind() == atom::LT) { + return l_false; + } + return l_undef; + } + polynomial::scoped_numeral n(m_pm.m()); + if (m_pm.is_var_num(p0, v, n)) { + // x - k > 0 + if (!sign && a.get_kind() == atom::GT && m_pm.m().is_nonneg(n)) { + return l_true; + } + // x + k < 0 + if (!sign && a.get_kind() == atom::LT && m_pm.m().is_nonpos(n)) { + return l_false; + } + // !(x + k > 0) + if (sign && a.get_kind() == atom::GT && m_pm.m().is_pos(n)) { + return l_false; + } + // !(x - k < 0) + if (sign && a.get_kind() == atom::LT && m_pm.m().is_neg(n)) { + return l_true; + } + } + return l_undef; + } + + bool is_single_poly(ineq_atom const& a, poly*& p) { + unsigned sz = a.size(); + return sz == 1 && a.is_odd(0) && (p = a.p(0), true); + } + + bool is_unit(polynomial_ref const& p) { + if (!m_pm.is_const(p)) + return false; + auto const& c = m_pm.coeff(p, 0); + return m_pm.m().is_one(c) || m_pm.m().is_minus_one(c); + } + + // ----------------------- + // + // Pretty printing + // + // ----------------------- + + std::ostream& display_num_assignment(std::ostream & out, display_var_proc const & proc) const { + for (var x = 0; x < num_vars(); x++) { + if (m_assignment.is_assigned(x)) { + proc(out, x); + out << " -> "; + m_am.display_decimal(out, m_assignment.value(x)); + out << "\n"; + } + } + return out; + } + + std::ostream& display_bool_assignment(std::ostream & out) const { + unsigned sz = m_atoms.size(); + for (bool_var b = 0; b < sz; b++) { + if (m_atoms[b] == nullptr && m_bvalues[b] != l_undef) { + out << "b" << b << " -> " << (m_bvalues[b] == l_true ? "true" : "false") << " @" << m_levels[b] << "\n"; + } + else if (m_atoms[b] != nullptr && m_bvalues[b] != l_undef) { + display(out << "b" << b << " ", *m_atoms[b]) << " -> " << (m_bvalues[b] == l_true ? "true" : "false") << " @" << m_levels[b] << "\n"; + } + } + TRACE("nlsat_bool_assignment", + for (bool_var b = 0; b < sz; b++) { + out << "b" << b << " -> " << m_bvalues[b] << " "; + if (m_atoms[b]) display(out, *m_atoms[b]); + out << "\n"; + }); + return out; + } + + bool display_mathematica_assignment(std::ostream & out) const { + bool first = true; + for (var x = 0; x < num_vars(); x++) { + if (m_assignment.is_assigned(x)) { + if (first) + first = false; + else + out << " && "; + out << "x" << x << " == "; + m_am.display_mathematica(out, m_assignment.value(x)); + } + } + return !first; + } + + std::ostream& display_num_assignment(std::ostream & out) const { + return display_num_assignment(out, m_display_var); + } + + std::ostream& display_assignment(std::ostream& out) const { + display_bool_assignment(out); + display_num_assignment(out); + return out; + } + + std::ostream& display(std::ostream& out, justification j) const { + switch (j.get_kind()) { + case justification::CLAUSE: + display(out, *j.get_clause()) << "\n"; + break; + case justification::LAZY: { + lazy_justification const& lz = *j.get_lazy(); + display_not(out, lz.num_lits(), lz.lits()) << "\n"; + for (unsigned i = 0; i < lz.num_clauses(); ++i) { + display(out, lz.clause(i)) << "\n"; + } + break; + } + default: + out << j.get_kind() << "\n"; + break; + } + return out; + } + + bool m_display_eval = false; + std::ostream& display_eval(std::ostream& out, justification j) { + flet _display(m_display_eval, true); + return display(out, j); + } + + std::ostream& display_ineq(std::ostream & out, ineq_atom const & a, display_var_proc const & proc, bool use_star = false) const { + unsigned sz = a.size(); + for (unsigned i = 0; i < sz; i++) { + if (use_star && i > 0) + out << "*"; + bool is_even = a.is_even(i); + if (is_even || sz > 1) + out << "("; + display_polynomial(out, a.p(i), proc, use_star); + if (is_even || sz > 1) + out << ")"; + if (is_even) + out << "^2"; + } + switch (a.get_kind()) { + case atom::LT: out << " < 0"; break; + case atom::GT: out << " > 0"; break; + case atom::EQ: out << " = 0"; break; + default: UNREACHABLE(); break; + } + return out; + } + + std::ostream& display_mathematica(std::ostream & out, ineq_atom const & a) const { + unsigned sz = a.size(); + for (unsigned i = 0; i < sz; i++) { + if (i > 0) + out << "*"; + bool is_even = a.is_even(i); + if (sz > 1) + out << "("; + if (is_even) + out << "("; + m_pm.display(out, a.p(i), display_var_proc(), true); + if (is_even) + out << "^2)"; + if (sz > 1) + out << ")"; + } + switch (a.get_kind()) { + case atom::LT: out << " < 0"; break; + case atom::GT: out << " > 0"; break; + case atom::EQ: out << " == 0"; break; + default: UNREACHABLE(); break; + } + return out; + } + + std::ostream& display_polynomial_smt2(std::ostream & out, poly const* p, display_var_proc const & proc) const { + return m_pm.display_smt2(out, p, proc); + } + + std::ostream& display_ineq_smt2(std::ostream & out, ineq_atom const & a, display_var_proc const & proc) const { + switch (a.get_kind()) { + case atom::LT: out << "(< "; break; + case atom::GT: out << "(> "; break; + case atom::EQ: out << "(= "; break; + default: UNREACHABLE(); break; + } + unsigned sz = a.size(); + if (sz > 1) + out << "(* "; + for (unsigned i = 0; i < sz; i++) { + if (i > 0) out << " "; + if (a.is_even(i)) { + out << "(* "; + display_polynomial_smt2(out, a.p(i), proc); + out << " "; + display_polynomial_smt2(out, a.p(i), proc); + out << ")"; + } + else { + display_polynomial_smt2(out, a.p(i), proc); + } + } + if (sz > 1) + out << ")"; + out << " 0)"; + return out; + } + + std::ostream& display_poly_root(std::ostream& out, char const* y, root_atom const& a, display_var_proc const& proc) const { + out << "(exists (("; proc(out,a.x()); out << " Real))\n"; + out << "(and (= " << y << " "; + proc(out, a.x()); + out << ") (= 0 "; + display_polynomial_smt2(out, a.p(), proc); + out << ")))\n"; + return out; + } + + std::ostream& display_binary_smt2(std::ostream& out, poly const* p1, char const* rel, poly const* p2, display_var_proc const& proc) const { + out << "(" << rel << " "; + display_polynomial_smt2(out, p1, proc); + out << " "; + display_polynomial_smt2(out, p2, proc); + out << ")"; + return out; + } + + + std::ostream& display_linear_root_smt2(std::ostream & out, root_atom const & a, display_var_proc const & proc) const { + polynomial_ref A(m_pm), B(m_pm), Z(m_pm), Ax(m_pm); + polynomial::scoped_numeral zero(m_qm); + m_pm.m().set(zero, 0); + A = m_pm.derivative(a.p(), a.x()); + B = m_pm.neg(m_pm.substitute(a.p(), a.x(), zero)); + Z = m_pm.mk_zero(); + + Ax = m_pm.mul(m_pm.mk_polynomial(a.x()), A); + + // x < root[1](ax + b) == (a > 0 => ax + b < 0) & (a < 0 => ax + b > 0) + // x < root[1](ax + b) == (a > 0 => ax < -b) & (a < 0 => ax > -b) + + char const* rel1 = "<", *rel2 = ">"; + switch (a.get_kind()) { + case atom::ROOT_LT: rel1 = "<"; rel2 = ">"; break; + case atom::ROOT_GT: rel1 = ">"; rel2 = "<"; break; + case atom::ROOT_LE: rel1 = "<="; rel2 = ">="; break; + case atom::ROOT_GE: rel1 = ">="; rel2 = "<="; break; + case atom::ROOT_EQ: rel1 = rel2 = "="; break; + default: UNREACHABLE(); break; + } + + out << "(and "; + out << "(=> "; display_binary_smt2(out, A, ">", Z, proc); display_binary_smt2(out, Ax, rel1, B, proc); out << ") "; + out << "(=> "; display_binary_smt2(out, A, "<", Z, proc); display_binary_smt2(out, Ax, rel2, B, proc); out << ") "; + out << ")"; + + return out; + } + + + std::ostream& display_root_smt2(std::ostream& out, root_atom const& a, display_var_proc const& proc) const { + if (a.i() == 1 && m_pm.degree(a.p(), a.x()) == 1) + return display_linear_root_smt2(out, a, proc); +#if 1 + out << "(exists ("; + for (unsigned j = 0; j < a.i(); ++j) { + std::string y = std::string("y") + std::to_string(j); + out << "(" << y << " Real) "; + } + out << ")\n"; + out << "(and\n"; + for (unsigned j = 0; j < a.i(); ++j) { + std::string y = std::string("y") + std::to_string(j); + display_poly_root(out, y.c_str(), a, proc); + } + for (unsigned j = 0; j + 1 < a.i(); ++j) { + std::string y1 = std::string("y") + std::to_string(j); + std::string y2 = std::string("y") + std::to_string(j+1); + out << "(< " << y1 << " " << y2 << ")\n"; + } + + std::string yn = "y" + std::to_string(a.i() - 1); + + // TODO we need (forall z : z < yn . p(z) => z = y1 or ... z = y_{n-1}) + // to say y1, .., yn are the first n distinct roots. + // + out << "(forall ((z Real)) (=> (and (< z " << yn << ") "; display_poly_root(out, "z", a, proc) << ") "; + if (a.i() == 1) { + out << "false))\n"; + } + else { + out << "(or "; + for (unsigned j = 0; j + 1 < a.i(); ++j) { + std::string y1 = std::string("y") + std::to_string(j); + out << "(= z " << y1 << ") "; + } + out << ")))\n"; + } + switch (a.get_kind()) { + case atom::ROOT_LT: out << "(< "; proc(out, a.x()); out << " " << yn << ")"; break; + case atom::ROOT_GT: out << "(> "; proc(out, a.x()); out << " " << yn << ")"; break; + case atom::ROOT_LE: out << "(<= "; proc(out, a.x()); out << " " << yn << ")"; break; + case atom::ROOT_GE: out << "(>= "; proc(out, a.x()); out << " " << yn << ")"; break; + case atom::ROOT_EQ: out << "(= "; proc(out, a.x()); out << " " << yn << ")"; NOT_IMPLEMENTED_YET(); break; + default: UNREACHABLE(); break; + } + out << "))"; + return out; +#endif + + + return display_root(out, a, proc); + } + + std::ostream& display_root(std::ostream & out, root_atom const & a, display_var_proc const & proc) const { + proc(out, a.x()); + switch (a.get_kind()) { + case atom::ROOT_LT: out << " < "; break; + case atom::ROOT_GT: out << " > "; break; + case atom::ROOT_LE: out << " <= "; break; + case atom::ROOT_GE: out << " >= "; break; + case atom::ROOT_EQ: out << " = "; break; + default: UNREACHABLE(); break; + } + out << "root[" << a.i() << "]("; + display_polynomial(out, a.p(), proc); + out << ")"; + return out; + } + + struct mathematica_var_proc : public display_var_proc { + var m_x; + public: + mathematica_var_proc(var x):m_x(x) {} + std::ostream& operator()(std::ostream & out, var x) const override { + if (m_x == x) + return out << "#1"; + else + return out << "x" << x; + } + }; + + std::ostream& display_mathematica(std::ostream & out, root_atom const & a) const { + out << "x" << a.x(); + switch (a.get_kind()) { + case atom::ROOT_LT: out << " < "; break; + case atom::ROOT_GT: out << " > "; break; + case atom::ROOT_LE: out << " <= "; break; + case atom::ROOT_GE: out << " >= "; break; + case atom::ROOT_EQ: out << " == "; break; + default: UNREACHABLE(); break; + } + out << "Root["; + display_polynomial(out, a.p(), mathematica_var_proc(a.x()), true); + out << " &, " << a.i() << "]"; + return out; + } + + std::ostream& display(std::ostream & out, atom const & a, display_var_proc const & proc) const { + if (a.is_ineq_atom()) + return display_ineq(out, static_cast(a), proc); + else + return display_root(out, static_cast(a), proc); + } + + std::ostream& display(std::ostream & out, atom const & a) const { + return display(out, a, m_display_var); + } + + std::ostream& display_mathematica(std::ostream & out, atom const & a) const { + if (a.is_ineq_atom()) + return display_mathematica(out, static_cast(a)); + else + return display_mathematica(out, static_cast(a)); + } + + std::ostream& display_smt2(std::ostream & out, atom const & a, display_var_proc const & proc) const { + if (a.is_ineq_atom()) + return display_ineq_smt2(out, static_cast(a), proc); + else + return display_root_smt2(out, static_cast(a), proc); + } + + std::ostream& display_atom(std::ostream & out, bool_var b, display_var_proc const & proc) const { + if (b == 0) + out << "true"; + else if (m_atoms[b] == 0) + out << "b" << b; + else + display(out, *(m_atoms[b]), proc); + return out; + } + + std::ostream& display_atom(std::ostream & out, bool_var b) const { + return display_atom(out, b, m_display_var); + } + + std::ostream& display_mathematica_atom(std::ostream & out, bool_var b) const { + if (b == 0) + out << "(0 < 1)"; + else if (m_atoms[b] == 0) + out << "b" << b; + else + display_mathematica(out, *(m_atoms[b])); + return out; + } + + std::ostream& display_smt2_atom(std::ostream & out, bool_var b, display_var_proc const & proc) const { + if (b == 0) + out << "true"; + else if (m_atoms[b] == 0) + out << "b" << b; + else + display_smt2(out, *(m_atoms[b]), proc); + return out; + } + + std::ostream& display(std::ostream & out, literal l, display_var_proc const & proc) const { + if (l.sign()) { + bool_var b = l.var(); + out << "!"; + if (m_atoms[b] != 0) + out << "("; + display_atom(out, b, proc); + if (m_atoms[b] != 0) + out << ")"; + } + else { + display_atom(out, l.var(), proc); + } + return out; + } + + std::ostream& display(std::ostream & out, literal l) const { + return display(out, l, m_display_var); + } + + std::ostream& display_smt2(std::ostream & out, literal l) const { + return display_smt2(out, l, m_display_var); + } + + std::ostream& display_mathematica(std::ostream & out, literal l) const { + if (l.sign()) { + bool_var b = l.var(); + out << "!"; + if (m_atoms[b] != 0) + out << "("; + display_mathematica_atom(out, b); + if (m_atoms[b] != 0) + out << ")"; + } + else { + display_mathematica_atom(out, l.var()); + } + return out; + } + + std::ostream& display_smt2(std::ostream & out, literal l, display_var_proc const & proc) const { + if (l.sign()) { + bool_var b = l.var(); + out << "(not "; + display_smt2_atom(out, b, proc); + out << ")"; + } + else { + display_smt2_atom(out, l.var(), proc); + } + return out; + } + + std::ostream& display_assumptions(std::ostream & out, _assumption_set s) const { + if (!m_display_assumption) + return out; + vector deps; + m_asm.linearize(s, deps); + bool first = true; + for (auto dep : deps) { + if (first) first = false; else out << " "; + (*m_display_assumption)(out, dep); + } + return out; + } + + std::ostream& display(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { + for (unsigned i = 0; i < num; i++) { + if (i > 0) + out << " or "; + display(out, ls[i], proc); + } + return out; + } + + std::ostream& display(std::ostream & out, unsigned num, literal const * ls) const { + return display(out, num, ls, m_display_var); + } + + std::ostream& display_not(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { + for (unsigned i = 0; i < num; i++) { + if (i > 0) + out << " or "; + display(out, ~ls[i], proc); + } + return out; + } + + std::ostream& display_not(std::ostream & out, unsigned num, literal const * ls) const { + return display_not(out, num, ls, m_display_var); + } + + std::ostream& display(std::ostream & out, scoped_literal_vector const & cs) { + return display(out, cs.size(), cs.data(), m_display_var); + } + + std::ostream& display(std::ostream & out, clause const & c, display_var_proc const & proc) const { + if (c.assumptions() != nullptr) { + display_assumptions(out, static_cast<_assumption_set>(c.assumptions())); + out << " |- "; + } + return display(out, c.size(), c.data(), proc); + } + + std::ostream& display(std::ostream & out, clause const & c) const { + return display(out, c, m_display_var); + } + + + std::ostream& display_polynomial(std::ostream& out, poly* p, display_var_proc const & proc, bool use_star = false) const { + if (m_display_eval) { + polynomial_ref q(m_pm); + q = p; + for (var x = 0; x < num_vars(); x++) + if (m_assignment.is_assigned(x)) { + auto& a = m_assignment.value(x); + if (!m_am.is_rational(a)) + continue; + mpq r; + m_am.to_rational(a, r); + q = m_pm.substitute(q, 1, &x, &r); + } + m_pm.display(out, q, proc, use_star); + } + else + m_pm.display(out, p, proc, use_star); + return out; + } + + // -- + + std::ostream& display_smt2(std::ostream & out, unsigned n, literal const* ls) const { + return display_smt2(out, n, ls, display_var_proc()); + } + + + std::ostream& display_smt2(std::ostream & out, unsigned num, literal const * ls, display_var_proc const & proc) const { + if (num == 0) { + out << "false"; + } + else if (num == 1) { + display_smt2(out, ls[0], proc); + } + else { + out << "(or"; + for (unsigned i = 0; i < num; i++) { + out << " "; + display_smt2(out, ls[i], proc); + } + out << ")"; + } + return out; + } + + std::ostream& display_smt2(std::ostream & out, clause const & c, display_var_proc const & proc = display_var_proc()) const { + return display_smt2(out, c.size(), c.data(), proc); + } + + std::ostream& display_abst(std::ostream & out, literal l) const { + if (l.sign()) { + bool_var b = l.var(); + out << "!"; + if (b == true_bool_var) + out << "true"; + else + out << "b" << b; + } + else { + out << "b" << l.var(); + } + return out; + } + + std::ostream& display_abst(std::ostream & out, unsigned num, literal const * ls) const { + for (unsigned i = 0; i < num; i++) { + if (i > 0) + out << " or "; + display_abst(out, ls[i]); + } + return out; + } + + std::ostream& display_abst(std::ostream & out, scoped_literal_vector const & cs) const { + return display_abst(out, cs.size(), cs.data()); + } + + std::ostream& display_abst(std::ostream & out, clause const & c) const { + return display_abst(out, c.size(), c.data()); + } + + std::ostream& display_mathematica(std::ostream & out, clause const & c) const { + out << "("; + unsigned sz = c.size(); + for (unsigned i = 0; i < sz; i++) { + if (i > 0) + out << " || "; + display_mathematica(out, c[i]); + } + out << ")"; + return out; + } + + // Debugging support: + // Display generated lemma in Mathematica format. + // Mathematica must reduce lemma to True (modulo resource constraints). + std::ostream& display_mathematica_lemma(std::ostream & out, unsigned num, literal const * ls, bool include_assignment = false) const { + out << "Resolve[ForAll[{"; + // var definition + for (unsigned i = 0; i < num_vars(); i++) { + if (i > 0) + out << ", "; + out << "x" << i; + } + out << "}, "; + if (include_assignment) { + out << "!("; + if (!display_mathematica_assignment(out)) + out << "0 < 1"; // nothing was printed + out << ") || "; + } + for (unsigned i = 0; i < num; i++) { + if (i > 0) + out << " || "; + display_mathematica(out, ls[i]); + } + out << "], Reals]\n"; // end of exists + return out; + } + + std::ostream& display(std::ostream & out, clause_vector const & cs, display_var_proc const & proc) const { + for (clause* c : cs) { + display(out, *c, proc) << "\n"; + } + return out; + } + + std::ostream& display(std::ostream & out, clause_vector const & cs) const { + return display(out, cs, m_display_var); + } + + std::ostream& display_mathematica(std::ostream & out, clause_vector const & cs) const { + unsigned sz = cs.size(); + for (unsigned i = 0; i < sz; i++) { + if (i > 0) out << ",\n"; + display_mathematica(out << " ", *(cs[i])); + } + return out; + } + + std::ostream& display_abst(std::ostream & out, clause_vector const & cs) const { + for (clause* c : cs) { + display_abst(out, *c) << "\n"; + } + return out; + } + + std::ostream& display(std::ostream & out, display_var_proc const & proc) const { + display(out, m_clauses, proc); + if (!m_learned.empty()) { + display(out << "Lemmas:\n", m_learned, proc); + } + return out; + } + + std::ostream& display_mathematica(std::ostream & out) const { + return display_mathematica(out << "{\n", m_clauses) << "}\n"; + } + + std::ostream& display_abst(std::ostream & out) const { + display_abst(out, m_clauses); + if (!m_learned.empty()) { + display_abst(out << "Lemmas:\n", m_learned); + } + return out; + } + + std::ostream& display(std::ostream & out) const { + display(out, m_display_var); + display_assignment(out << "assignment:\n"); + return out << "---\n"; + } + + std::ostream& display_vars(std::ostream & out) const { + for (unsigned i = 0; i < num_vars(); i++) { + out << i << " -> "; m_display_var(out, i); out << "\n"; + } + return out; + } + + std::ostream& display_smt2_arith_decls(std::ostream & out) const { + unsigned sz = m_is_int.size(); + for (unsigned i = 0; i < sz; i++) { + if (is_int(i)) { + out << "(declare-fun "; m_display_var(out, i) << " () Int)\n"; + } + else { + out << "(declare-fun "; m_display_var(out, i) << " () Real)\n"; + } + } + return out; + } + + std::ostream& display_smt2_bool_decls(std::ostream & out) const { + unsigned sz = m_atoms.size(); + for (unsigned i = 0; i < sz; i++) { + if (m_atoms[i] == nullptr) + out << "(declare-fun b" << i << " () Bool)\n"; + } + return out; + } + + std::ostream& display_smt2(std::ostream & out) const { + display_smt2_bool_decls(out); + display_smt2_arith_decls(out); + out << "(assert (and true\n"; + for (clause* c : m_clauses) { + display_smt2(out, *c, m_display_var) << "\n"; + } + out << "))\n" << std::endl; + return out; + } + }; + + solver::solver(reslimit& rlim, params_ref const & p, bool incremental) { + m_ctx = alloc(ctx, rlim, p, incremental); + m_imp = alloc(imp, *this, *m_ctx); + } + + solver::solver(ctx& ctx) { + m_ctx = nullptr; + m_imp = alloc(imp, *this, ctx); + } + + solver::~solver() { + dealloc(m_imp); + dealloc(m_ctx); + } + + lbool solver::check() { + return m_imp->check(); + } + + lbool solver::check(literal_vector& assumptions) { + return m_imp->check(assumptions); + } + + void solver::get_core(vector& assumptions) { + return m_imp->get_core(assumptions); + } + + void solver::reset() { + m_imp->reset(); + } + + + void solver::updt_params(params_ref const & p) { + m_imp->updt_params(p); + } + + + void solver::collect_param_descrs(param_descrs & d) { + algebraic_numbers::manager::collect_param_descrs(d); + nlsat_params::collect_param_descrs(d); + } + + unsynch_mpq_manager & solver::qm() { + return m_imp->m_qm; + } + + anum_manager & solver::am() { + return m_imp->m_am; + } + + pmanager & solver::pm() { + return m_imp->m_pm; + } + + void solver::set_display_var(display_var_proc const & proc) { + m_imp->m_display_var.m_proc = &proc; + } + + void solver::set_display_assumption(display_assumption_proc const& proc) { + m_imp->m_display_assumption = &proc; + } + + + unsigned solver::num_vars() const { + return m_imp->num_vars(); + } + + bool solver::is_int(var x) const { + return m_imp->is_int(x); + } + + bool_var solver::mk_bool_var() { + return m_imp->mk_bool_var(); + } + + literal solver::mk_true() { + return literal(0, false); + } + + atom * solver::bool_var2atom(bool_var b) { + return m_imp->m_atoms[b]; + } + + void solver::vars(literal l, var_vector& vs) { + m_imp->vars(l, vs); + } + + atom_vector const& solver::get_atoms() { + return m_imp->m_atoms; + } + + atom_vector const& solver::get_var2eq() { + return m_imp->m_var2eq; + } + + evaluator& solver::get_evaluator() { + return m_imp->m_evaluator; + } + + explain& solver::get_explain() { + return m_imp->m_explain; + } + + void solver::reorder(unsigned sz, var const* p) { + m_imp->reorder(sz, p); + } + + void solver::restore_order() { + m_imp->restore_order(); + } + + void solver::set_rvalues(assignment const& as) { + m_imp->m_assignment.copy(as); + } + + void solver::get_rvalues(assignment& as) { + as.copy(m_imp->m_assignment); + } + + void solver::get_bvalues(svector const& bvars, svector& vs) { + vs.reset(); + for (bool_var b : bvars) { + vs.reserve(b + 1, l_undef); + if (!m_imp->m_atoms[b]) { + vs[b] = m_imp->m_bvalues[b]; + } + } + TRACE("nlsat", display(tout);); + } + + void solver::set_bvalues(svector const& vs) { + TRACE("nlsat", display(tout);); + for (bool_var b = 0; b < vs.size(); ++b) { + if (vs[b] != l_undef) { + m_imp->m_bvalues[b] = vs[b]; + SASSERT(!m_imp->m_atoms[b]); + } + } +#if 0 + m_imp->m_bvalues.reset(); + m_imp->m_bvalues.append(vs); + m_imp->m_bvalues.resize(m_imp->m_atoms.size(), l_undef); + for (unsigned i = 0; i < m_imp->m_atoms.size(); ++i) { + atom* a = m_imp->m_atoms[i]; + SASSERT(!a); + if (a) { + m_imp->m_bvalues[i] = to_lbool(m_imp->m_evaluator.eval(a, false)); + } + } +#endif + TRACE("nlsat", display(tout);); + } + + void solver::del_clause(clause* c) { + m_imp->del_clause(c); + } + + var solver::mk_var(bool is_int) { + return m_imp->mk_var(is_int); + } + + bool_var solver::mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even) { + return m_imp->mk_ineq_atom(k, sz, ps, is_even); + } + + literal solver::mk_ineq_literal(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify) { + return m_imp->mk_ineq_literal(k, sz, ps, is_even, simplify); + } + + bool_var solver::mk_root_atom(atom::kind k, var x, unsigned i, poly * p) { + return m_imp->mk_root_atom(k, x, i, p); + } + + void solver::inc_ref(bool_var b) { + m_imp->inc_ref(b); + } + + void solver::dec_ref(bool_var b) { + m_imp->dec_ref(b); + } + + void solver::inc_ref(assumption a) { + m_imp->inc_ref(static_cast(a)); + } + + void solver::dec_ref(assumption a) { + m_imp->dec_ref(static_cast(a)); + } + + void solver::mk_clause(unsigned num_lits, literal * lits, assumption a) { + return m_imp->mk_external_clause(num_lits, lits, a); + } + + std::ostream& solver::display(std::ostream & out) const { + return m_imp->display(out); + } + + std::ostream& solver::display(std::ostream & out, literal l) const { + return m_imp->display(out, l); + } + + std::ostream& solver::display(std::ostream & out, unsigned n, literal const* ls) const { + for (unsigned i = 0; i < n; ++i) { + display(out, ls[i]); + out << "; "; + } + return out; + } + + std::ostream& solver::display(std::ostream & out, literal_vector const& ls) const { + return display(out, ls.size(), ls.data()); + } + + std::ostream& solver::display_smt2(std::ostream & out, literal l) const { + return m_imp->display_smt2(out, l); + } + + std::ostream& solver::display_smt2(std::ostream & out, unsigned n, literal const* ls) const { + for (unsigned i = 0; i < n; ++i) { + display_smt2(out, ls[i]); + out << " "; + } + return out; + } + + std::ostream& solver::display(std::ostream& out, clause const& c) const { + return m_imp->display(out, c); + } + + std::ostream& solver::display_smt2(std::ostream & out) const { + return m_imp->display_smt2(out); + } + + std::ostream& solver::display_smt2(std::ostream & out, literal_vector const& ls) const { + return display_smt2(out, ls.size(), ls.data()); + } + + std::ostream& solver::display(std::ostream & out, var x) const { + return m_imp->m_display_var(out, x); + } + + std::ostream& solver::display(std::ostream & out, atom const& a) const { + return m_imp->display(out, a, m_imp->m_display_var); + } + + display_var_proc const & solver::display_proc() const { + return m_imp->m_display_var; + } + + anum const & solver::value(var x) const { + if (m_imp->m_assignment.is_assigned(x)) + return m_imp->m_assignment.value(x); + return m_imp->m_zero; + } + + lbool solver::bvalue(bool_var b) const { + return m_imp->m_bvalues[b]; + } + + lbool solver::value(literal l) const { + return m_imp->value(l); + } + + bool solver::is_interpreted(bool_var b) const { + return m_imp->m_atoms[b] != 0; + } + + void solver::reset_statistics() { + return m_imp->reset_statistics(); + } + + void solver::collect_statistics(statistics & st) { + return m_imp->collect_statistics(st); + } + + clause* solver::mk_clause(unsigned n, literal const* lits, bool learned, internal_assumption a) { + return m_imp->mk_clause(n, lits, learned, static_cast(a)); + } + + void solver::inc_simplify() { + m_imp->m_stats.m_simplifications++; + } + + bool solver::has_root_atom(clause const& c) const { + return m_imp->has_root_atom(c); + } + + void solver::add_bound(bound_constraint const& c) { + m_imp->m_bounds.push_back(c); + } + + assumption solver::join(assumption a, assumption b) { + return (m_imp->m_asm.mk_join(static_cast(a), static_cast(b))); + } + +}; diff --git a/src/qe/mbp/mbp_arrays_tg.cpp b/src/qe/mbp/mbp_arrays_tg.cpp index c3d91ae64..da1bb1837 100644 --- a/src/qe/mbp/mbp_arrays_tg.cpp +++ b/src/qe/mbp/mbp_arrays_tg.cpp @@ -116,7 +116,7 @@ struct mbp_array_tg::impl { bool is_rd_wr(expr* t, expr*& wr_ind, expr*& rd_ind, expr*& b, expr*& v) { if (!is_rd_wr(t)) return false; - expr* a; + expr* a = nullptr; VERIFY(m_array_util.is_select1(t, a, rd_ind)); VERIFY(m_array_util.is_store1(a, b, wr_ind, v)); return true; @@ -185,7 +185,7 @@ struct mbp_array_tg::impl { // or &&_{i \in indices} j \neq i && // !(select(y, j) = elem) void elimwreq(peq p, bool is_neg) { - expr* a, *j, *elem; + expr* a = nullptr, *j = nullptr, *elem = nullptr; VERIFY(is_arr_write(p.lhs(), a, j, elem)); TRACE("mbp_tg", tout << "applying elimwreq on " << expr_ref(p.mk_peq(), m) << " is neg: " << is_neg;); @@ -279,7 +279,7 @@ struct mbp_array_tg::impl { // rewrite select(store(a, i, k), j) into either select(a, j) or k void elimrdwr(expr *term) { TRACE("mbp_tg", tout << "applying elimrdwr on " << expr_ref(term, m);); - expr* wr_ind, *rd_ind, *b, *v; + expr* wr_ind = nullptr, *rd_ind = nullptr, *b = nullptr, *v = nullptr; VERIFY(is_rd_wr(term, wr_ind, rd_ind, b, v)); if (m_mdl.are_equal(wr_ind, rd_ind)) m_tg.add_eq(wr_ind, rd_ind); diff --git a/src/sat/sat_aig_cuts.cpp b/src/sat/sat_aig_cuts.cpp index 20f62cbdd..df736e4ba 100644 --- a/src/sat/sat_aig_cuts.cpp +++ b/src/sat/sat_aig_cuts.cpp @@ -534,7 +534,7 @@ namespace sat { } cut_val aig_cuts::eval(node const& n, cut_eval const& env) const { - uint64_t result; + uint64_t result = 0; switch (n.op()) { case var_op: UNREACHABLE(); From b84b4e7f9ace073a6d2a3c65e699b35a8e20f400 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 26 Aug 2024 11:38:27 -0700 Subject: [PATCH 070/187] fix attribute order Signed-off-by: Nikolaj Bjorner --- src/nlsat/nlsat_explain.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp index 12db1d3da..a188206b4 100644 --- a/src/nlsat/nlsat_explain.cpp +++ b/src/nlsat/nlsat_explain.cpp @@ -146,11 +146,10 @@ namespace nlsat { m_factors(m_pm), m_factors_save(m_pm), m_roots_tmp(m_am), + m_cell_sample(is_sample), m_todo(u), m_core1(s), m_core2(s), - m_cell_sample(is_sample), - m_evaluator(ev) { m_simplify_cores = false; m_full_dimensional = false; From 84da614de3cd2cb67118ebe7ab0764d74af4521c Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 26 Aug 2024 11:40:01 -0700 Subject: [PATCH 071/187] make gcc linting happy Signed-off-by: Nikolaj Bjorner --- src/muz/spacer/spacer_legacy_frames.cpp | 4 ++-- src/muz/spacer/spacer_proof_utils.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/muz/spacer/spacer_legacy_frames.cpp b/src/muz/spacer/spacer_legacy_frames.cpp index a21df5038..15b37b127 100644 --- a/src/muz/spacer/spacer_legacy_frames.cpp +++ b/src/muz/spacer/spacer_legacy_frames.cpp @@ -90,10 +90,10 @@ bool pred_transformer::legacy_frames::propagate_to_next_level(unsigned src_level for (unsigned i = 0; i < m_levels[src_level].size();) { expr_ref_vector &src = m_levels[src_level]; expr * curr = src[i].get(); - unsigned stored_lvl; + unsigned stored_lvl = 0; VERIFY(m_prop2level.find(curr, stored_lvl)); SASSERT(stored_lvl >= src_level); - unsigned solver_level; + unsigned solver_level = 0; if (stored_lvl > src_level) { TRACE("spacer", tout << "at level: " << stored_lvl << " " << mk_pp(curr, m) << "\n";); src[i] = src.back(); diff --git a/src/muz/spacer/spacer_proof_utils.cpp b/src/muz/spacer/spacer_proof_utils.cpp index 9fbd4e01c..114dfc885 100644 --- a/src/muz/spacer/spacer_proof_utils.cpp +++ b/src/muz/spacer/spacer_proof_utils.cpp @@ -432,8 +432,8 @@ namespace spacer { ptr_buffer args; for (unsigned i = 0, sz = m.get_num_parents(p); i < sz; ++i) { - proof *pp, *tmp; - pp = m.get_parent(p, i); + proof *tmp = nullptr; + proof* pp = m.get_parent(p, i); VERIFY(m_cache.find(pp, tmp)); args.push_back(tmp); dirty |= (pp != tmp); @@ -455,8 +455,8 @@ namespace spacer { } } - proof* res; - VERIFY(m_cache.find(pr,res)); + proof* res = nullptr; + VERIFY(m_cache.find(pr, res)); DEBUG_CODE( proof_checker pc(m); expr_ref_vector side(m); From 349ebd0a5b2486779c1375873a0794a8c2c0825f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 26 Aug 2024 14:22:28 -0700 Subject: [PATCH 072/187] #7344 --- src/smt/smt_context.cpp | 7 ++++++- src/smt/smt_context.h | 1 + src/smt/smt_model_generator.cpp | 1 - 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 428460801..4ff8c12e7 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -1858,8 +1858,10 @@ namespace smt { lbool phase = l_undef; m_case_split_queue->next_case_split(var, phase); used_queue = true; - if (var == null_bool_var) + if (var == null_bool_var) { + push_trail(value_trail(m_has_case_split, false)); return false; + } TRACE_CODE({ static unsigned counter = 0; @@ -4642,6 +4644,9 @@ namespace smt { } bool context::has_case_splits() { + if (!m_has_case_split) + return false; + for (unsigned i = get_num_b_internalized(); i-- > 0; ) { if (is_relevant(i) && get_assignment(i) == l_undef) return true; diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index 4feeae1b5..da7cde7e7 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -1155,6 +1155,7 @@ namespace smt { bool guess(bool_var var, lbool phase); protected: + bool m_has_case_split = true; bool decide(); void update_phase_cache_counter(); diff --git a/src/smt/smt_model_generator.cpp b/src/smt/smt_model_generator.cpp index 6537e638d..8f408d5cf 100644 --- a/src/smt/smt_model_generator.cpp +++ b/src/smt/smt_model_generator.cpp @@ -99,7 +99,6 @@ namespace smt { if (m.is_bool(s)) { CTRACE("model", m_context->get_assignment(r) == l_undef, tout << mk_pp(r->get_expr(), m) << "\n";); - SASSERT(m_context->get_assignment(r) != l_undef); if (m_context->get_assignment(r) == l_true) proc = alloc(expr_wrapper_proc, m.mk_true()); else From e1f1d677ff53f9dd559a75950c4590fb738c53c7 Mon Sep 17 00:00:00 2001 From: Audrey Dutcher Date: Tue, 27 Aug 2024 17:12:31 -0700 Subject: [PATCH 073/187] New python packaging and tests (#7356) * Simplify/modernize python packaging * Modify azure CI to utilize new python packaging --- azure-pipelines.yml | 29 +++++++---- src/api/python/pyproject.toml | 2 +- src/api/python/setup.py | 96 ++--------------------------------- 3 files changed, 25 insertions(+), 102 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 48dcf094a..ac3b9105c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -43,8 +43,20 @@ jobs: - ${{if eq(variables['runRegressions'], 'True')}}: - template: scripts/test-regressions.yml -- job: LinuxBuildsArm64 - displayName: "ManyLinux ARM64 build" +- job: "ManylinuxPythonBuildAmd64" + displayName: "Python bindings (manylinux Centos AMD64) build" + pool: + vmImage: "ubuntu-latest" + container: "quay.io/pypa/manylinux2014_x86_64:latest" + steps: + - script: "/opt/python/cp38-cp38/bin/python -m venv $PWD/env" + - script: 'echo "##vso[task.prependpath]$PWD/env/bin"' + - script: "pip install build git+https://github.com/rhelmot/auditwheel" # @TODO remove when patches make it upstream + - script: "cd src/api/python && python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." + - script: "pip install ./src/api/python/wheelhouse/*.whl && python - =46.4.0", "wheel", "cmake"] +requires = ["setuptools>=59", "wheel", "cmake"] build-backend = "setuptools.build_meta" diff --git a/src/api/python/setup.py b/src/api/python/setup.py index c7af0e646..f17527a01 100644 --- a/src/api/python/setup.py +++ b/src/api/python/setup.py @@ -7,14 +7,12 @@ import multiprocessing import re import glob from setuptools import setup -from distutils.util import get_platform -from distutils.errors import LibError -from distutils.command.build import build as _build -from distutils.command.sdist import sdist as _sdist -from distutils.command.clean import clean as _clean +from setuptools.command.build import build as _build +from setuptools.command.sdist import sdist as _sdist from setuptools.command.develop import develop as _develop -from setuptools.command.bdist_egg import bdist_egg as _bdist_egg +class LibError(Exception): + pass build_env = dict(os.environ) build_env['PYTHON'] = sys.executable @@ -238,27 +236,12 @@ class develop(_develop): self.execute(_copy_bins, (), msg="Copying binaries") _develop.run(self) -class bdist_egg(_bdist_egg): - def run(self): - self.run_command('build') - _bdist_egg.run(self) - class sdist(_sdist): def run(self): self.execute(_clean_bins, (), msg="Cleaning binary files and headers") self.execute(_copy_sources, (), msg="Copying source files") _sdist.run(self) -class clean(_clean): - def run(self): - self.execute(_clean_bins, (), msg="Cleaning binary files and headers") - self.execute(_clean_native_build, (), msg="Cleaning native build") - _clean.run(self) - -# the build directory needs to exist -#try: os.makedirs(os.path.join(ROOT_DIR, 'build')) -#except OSError: pass - # platform.freedesktop_os_release was added in 3.10 os_id = '' if hasattr(platform, 'freedesktop_os_release'): @@ -269,75 +252,6 @@ if hasattr(platform, 'freedesktop_os_release'): except OSError: pass -if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv: - if RELEASE_DIR is None: - name = get_platform() - if 'linux' in name: - # linux_* platform tags are disallowed because the python ecosystem is fubar - # linux builds should be built in the centos 5 vm for maximum compatibility - # see https://github.com/pypa/manylinux - # see also https://github.com/angr/angr-dev/blob/master/admin/bdist.py - plat_name = 'manylinux_2_28_' + platform.machine() - elif 'mingw' in name: - if platform.architecture()[0] == '64bit': - plat_name = 'win_amd64' - else: - plat_name ='win32' - else: - # https://www.python.org/dev/peps/pep-0425/ - plat_name = name.replace('.', '_').replace('-', '_') - else: - # extract the architecture of the release from the directory name - arch = RELEASE_METADATA[1] - distos = RELEASE_METADATA[2] - if distos in ('debian', 'ubuntu'): - raise Exception( - "Linux binary distributions must be built on centos to conform to PEP 513 or alpine if targeting musl" - ) - elif distos == 'glibc': - if arch == 'x64': - plat_name = 'manylinux_2_28_x86_64' - elif arch == 'arm64' or arch == 'aarch64': - # context on why are we match on arm64 - # but use aarch64 on the plat_name is - # due to a workaround current python - # legacy build doesn't support aarch64 - # so using the currently supported arm64 - # build and simply rename it to aarch64 - # see full context on #7148 - plat_name = 'manylinux_2_28_aarch64' - else: - plat_name = 'manylinux_2_28_i686' - elif distos == 'linux' and os_id == 'alpine': - if arch == 'x64': - plat_name = 'musllinux_1_1_x86_64' - else: - plat_name = 'musllinux_1_1_i686' - elif distos == 'win': - if arch == 'x64': - plat_name = 'win_amd64' - else: - plat_name = 'win32' - elif distos == 'osx': - osver = RELEASE_METADATA[3] - if osver.count('.') > 1: - osver = '.'.join(osver.split('.')[:2]) - if osver.startswith("11"): - osver = "11_0" - if arch == 'x64': - plat_name ='macosx_%s_x86_64' % osver.replace('.', '_') - elif arch == 'arm64': - plat_name ='macosx_%s_arm64' % osver.replace('.', '_') - else: - raise Exception(f"idk how os {distos} {osver} works. what goes here?") - else: - raise Exception(f"idk how to translate between this z3 release os {distos} and the python naming scheme") - - idx = sys.argv.index('bdist_wheel') + 1 - sys.argv.insert(idx, '--plat-name') - sys.argv.insert(idx + 1, plat_name) - sys.argv.insert(idx + 2, '--universal') # supports py2+py3. if --plat-name is not specified this will also mean that the package can be installed on any machine regardless of architecture, so watch out! - setup( name='z3-solver', version=_z3_version(), @@ -356,5 +270,5 @@ setup( 'z3': [os.path.join('lib', '*'), os.path.join('include', '*.h'), os.path.join('include', 'c++', '*.h')] }, data_files=[('bin',[os.path.join('bin',EXECUTABLE_FILE)])], - cmdclass={'build': build, 'develop': develop, 'sdist': sdist, 'bdist_egg': bdist_egg, 'clean': clean}, + cmdclass={'build': build, 'develop': develop, 'sdist': sdist}, ) From f6dbaee6ce32bbe83c285939731e3e36c1d6bcfc Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 27 Aug 2024 17:17:53 -0700 Subject: [PATCH 074/187] adding to nightly Signed-off-by: Nikolaj Bjorner --- azure-pipelines.yml | 1 - scripts/nightly.yaml | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ac3b9105c..4be3f33af 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -73,7 +73,6 @@ jobs: - script: echo '##vso[task.prependpath]/tmp/arm-toolchain/aarch64-none-linux-gnu/libc/usr/bin' - script: echo $PATH - script: "stat `which aarch64-none-linux-gnu-gcc`" - - script: "pip install build git+https://github.com/rhelmot/auditwheel" # @TODO remove when patches make it upstream - script: "cd src/api/python && CC=aarch64-none-linux-gnu-gcc CXX=aarch64-none-linux-gnu-g++ AR=aarch64-none-linux-gnu-ar LD=aarch64-none-linux-gnu-ld python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." - job: "Ubuntu20OCaml" diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index 62976cce2..fae95d2d2 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -167,7 +167,41 @@ stages: inputs: artifactName: 'UbuntuDoc' targetPath: $(Build.ArtifactStagingDirectory) - + # TODO copy artifacts + + - job: "ManylinuxPythonBuildAmd64" + displayName: "Python bindings (manylinux Centos AMD64) build" + pool: + vmImage: "ubuntu-latest" + container: "quay.io/pypa/manylinux2014_x86_64:latest" + steps: + - script: "/opt/python/cp38-cp38/bin/python -m venv $PWD/env" + - script: 'echo "##vso[task.prependpath]$PWD/env/bin"' + - script: "pip install build git+https://github.com/rhelmot/auditwheel" # @TODO remove when patches make it upstream + - script: "cd src/api/python && python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." + - script: "pip install ./src/api/python/wheelhouse/*.whl && python - Date: Wed, 28 Aug 2024 09:32:00 -0700 Subject: [PATCH 075/187] Bump docker/build-push-action from 6.6.1 to 6.7.0 (#7350) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.6.1 to 6.7.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.6.1...v6.7.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 0b3827479..7e8ca0b12 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -41,7 +41,7 @@ jobs: type=edge type=sha,prefix=ubuntu-20.04-bare-z3-sha- - name: Build and push Bare Z3 Docker Image - uses: docker/build-push-action@v6.6.1 + uses: docker/build-push-action@v6.7.0 with: context: . push: true From 5360656440cbe39d9d646ec9780b69b513d0dfc1 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 28 Aug 2024 09:40:51 -0700 Subject: [PATCH 076/187] fix expected Signed-off-by: Nikolaj Bjorner --- src/api/python/z3/z3.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/python/z3/z3.py b/src/api/python/z3/z3.py index c3f40a52b..bd38d5baa 100644 --- a/src/api/python/z3/z3.py +++ b/src/api/python/z3/z3.py @@ -6798,7 +6798,7 @@ class Statistics: sat >>> st = s.statistics() >>> len(st) - 6 + 7 """ return int(Z3_stats_size(self.ctx.ref(), self.stats)) @@ -6812,11 +6812,11 @@ class Statistics: sat >>> st = s.statistics() >>> len(st) - 6 + 7 >>> st[0] ('nlsat propagations', 2) >>> st[1] - ('nlsat stages', 2) + ('nlsat restarts', 1) """ if idx >= len(self): raise IndexError @@ -10220,7 +10220,7 @@ def FPs(names, fpsort, ctx=None): >>> x.ebits() 8 >>> fpMul(RNE(), fpAdd(RNE(), x, y), z) - x + y * z + (x + y) * z """ ctx = _get_ctx(ctx) if isinstance(names, str): From 954dddbfb3e045566c4a19680c0ad43ca16cd7d7 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 28 Aug 2024 09:44:28 -0700 Subject: [PATCH 077/187] retain pip install build, remove audit Signed-off-by: Nikolaj Bjorner --- azure-pipelines.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4be3f33af..ca74633ca 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -51,7 +51,7 @@ jobs: steps: - script: "/opt/python/cp38-cp38/bin/python -m venv $PWD/env" - script: 'echo "##vso[task.prependpath]$PWD/env/bin"' - - script: "pip install build git+https://github.com/rhelmot/auditwheel" # @TODO remove when patches make it upstream + - script: "pip install build" - script: "cd src/api/python && python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." - script: "pip install ./src/api/python/wheelhouse/*.whl && python - Date: Wed, 28 Aug 2024 10:32:07 -0700 Subject: [PATCH 078/187] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e6db550c0..0254160c7 100644 --- a/README.md +++ b/README.md @@ -236,4 +236,7 @@ to Z3's C API. For more information, see [MachineArithmetic/README.md](https://g * [Julia](https://github.com/ahumenberger/Z3.jl) * [Smalltalk](https://github.com/shingarov/MachineArithmetic/blob/pure-z3/MachineArithmetic/README.md) (supports Pharo and Smalltalk/X) +## Power Tools +* The [Axiom Profiler](https://github.com/viperproject/axiom-profiler-2) currently developed by ETH Zurich + From cd898673202f0bf242b1d03d10578b98a7570a99 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 28 Aug 2024 14:10:16 -0700 Subject: [PATCH 079/187] add back auditwheel Signed-off-by: Nikolaj Bjorner --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ca74633ca..ee852a6e9 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -51,7 +51,7 @@ jobs: steps: - script: "/opt/python/cp38-cp38/bin/python -m venv $PWD/env" - script: 'echo "##vso[task.prependpath]$PWD/env/bin"' - - script: "pip install build" + - script: "pip install build git+https://github.com/rhelmot/auditwheel"" - script: "cd src/api/python && python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." - script: "pip install ./src/api/python/wheelhouse/*.whl && python - Date: Wed, 28 Aug 2024 15:41:18 -0700 Subject: [PATCH 080/187] Update azure-pipelines.yml --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ee852a6e9..b7ad2ab1e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -51,7 +51,7 @@ jobs: steps: - script: "/opt/python/cp38-cp38/bin/python -m venv $PWD/env" - script: 'echo "##vso[task.prependpath]$PWD/env/bin"' - - script: "pip install build git+https://github.com/rhelmot/auditwheel"" + - script: "pip install build git+https://github.com/rhelmot/auditwheel" - script: "cd src/api/python && python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." - script: "pip install ./src/api/python/wheelhouse/*.whl && python - Date: Wed, 28 Aug 2024 17:41:49 -0700 Subject: [PATCH 081/187] update nightly Signed-off-by: Nikolaj Bjorner --- scripts/nightly.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index fae95d2d2..0de2d3ed6 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -199,6 +199,7 @@ stages: - script: echo '##vso[task.prependpath]/tmp/arm-toolchain/aarch64-none-linux-gnu/libc/usr/bin' - script: echo $PATH - script: "stat `which aarch64-none-linux-gnu-gcc`" + - script: "pip install build git+https://github.com/rhelmot/auditwheel" - script: "cd src/api/python && CC=aarch64-none-linux-gnu-gcc CXX=aarch64-none-linux-gnu-g++ AR=aarch64-none-linux-gnu-ar LD=aarch64-none-linux-gnu-ld python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." # TODO copy artifacts From 59853d070bb3f1ccbe9b7b169b13258f2106a7f1 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 29 Aug 2024 10:41:03 -0700 Subject: [PATCH 082/187] Update nightly.yaml create build artifacts --- scripts/nightly.yaml | 90 ++++++++++---------------------------------- 1 file changed, 20 insertions(+), 70 deletions(-) diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index 0de2d3ed6..8198d3437 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -180,6 +180,15 @@ stages: - script: "pip install build git+https://github.com/rhelmot/auditwheel" # @TODO remove when patches make it upstream - script: "cd src/api/python && python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." - script: "pip install ./src/api/python/wheelhouse/*.whl && python - Date: Thu, 29 Aug 2024 10:43:31 -0700 Subject: [PATCH 083/187] Update nightly.yaml disable signing options --- scripts/nightly.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index 8198d3437..74ceb2a54 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -410,6 +410,7 @@ stages: patchVersion: $(Patch) arguments: 'pack $(Agent.TempDirectory)\package\out\Microsoft.Z3.x86.sym.nuspec -Version $(NightlyVersion) -OutputDirectory $(Build.ArtifactStagingDirectory) -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -BasePath $(Agent.TempDirectory)\package\out' - task: EsrpCodeSigning@2 + condition: eq(1,0) continueOnError: true displayName: 'Sign Package' inputs: @@ -438,6 +439,7 @@ stages: MaxConcurrency: '50' MaxRetryAttempts: '5' - task: EsrpCodeSigning@2 + condition: eq(1,0) continueOnError: true displayName: 'Sign Symbol Package' inputs: From dcdb7c4506c931fc332f44787ef40191e6dd6e08 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 29 Aug 2024 11:34:47 -0700 Subject: [PATCH 084/187] wheelhouse Signed-off-by: Nikolaj Bjorner --- scripts/nightly.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index 74ceb2a54..adbdd04b9 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -182,7 +182,7 @@ stages: - script: "pip install ./src/api/python/wheelhouse/*.whl && python - Date: Thu, 29 Aug 2024 17:10:36 -0700 Subject: [PATCH 085/187] Update nightly.yaml for Azure Pipelines --- scripts/nightly.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index adbdd04b9..60aca338b 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -182,7 +182,7 @@ stages: - script: "pip install ./src/api/python/wheelhouse/*.whl && python - Date: Fri, 30 Aug 2024 11:52:01 -0700 Subject: [PATCH 086/187] update gitignore to prepare for genaiscript Signed-off-by: Nikolaj Bjorner --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 710ce4b7e..cb3d0190c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,11 @@ callgrind.out.* # .hpp files are automatically generated *.hpp .z3-trace +.env +.genaiscript +package-lock.json +package.json +node_modules # OCaml generated files *.a *.o From 9a87bb109723cbddecaad2ce7d6884316ec59162 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 30 Aug 2024 14:30:14 -0700 Subject: [PATCH 087/187] #7362 Signed-off-by: Nikolaj Bjorner --- src/model/model_evaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index 2446609c6..6db52a98e 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -457,7 +457,7 @@ struct evaluator_cfg : public default_rewriter_cfg { if (interp) { var_subst vs(m, false); result = vs(fi->get_interp(), num, args); - result = m.mk_ite(m.mk_eq(m_au.mk_real(rational(0)), args[1]), result, m.mk_app(f, num, args)); + result = m.mk_ite(m.mk_eq(m_au.mk_numeral(rational(0), args[1]->get_sort()), args[1]), result, m.mk_app(f, num, args)); return BR_DONE; } } From 01a419546fed8c501c772363a603e6491ad42478 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 30 Aug 2024 14:35:37 -0700 Subject: [PATCH 088/187] #7362 Signed-off-by: Nikolaj Bjorner --- src/smt/smt_context.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 4ff8c12e7..84cdc6e69 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -99,13 +99,16 @@ namespace smt { m_model_generator->set_context(this); } - + :: /** \brief retrieve flag for when cancelation is possible. */ bool context::get_cancel_flag() { - return !m.limit().inc(); + if (m.limit().inc()) + return false; + m_last_search_failure = CANCELED; + return true; } void context::updt_params(params_ref const& p) { @@ -3745,8 +3748,9 @@ namespace smt { VERIFY(!resolve_conflict()); return l_false; } - if (get_cancel_flag()) + if (get_cancel_flag()) return l_undef; + timeit tt(get_verbosity_level() >= 100, "smt.stats"); reset_model(); SASSERT(at_search_level()); @@ -3959,10 +3963,8 @@ namespace smt { if (m_last_search_failure != OK) return true; - if (get_cancel_flag()) { - m_last_search_failure = CANCELED; - return true; - } + if (get_cancel_flag()) + return true; if (m_progress_callback) { m_progress_callback->fast_progress_sample(); @@ -3973,10 +3975,8 @@ namespace smt { } } - if (get_cancel_flag()) { - m_last_search_failure = CANCELED; - return true; - } + if (get_cancel_flag()) + return true; if (memory::above_high_watermark()) { m_last_search_failure = MEMOUT; From a1bcf136a6c3a5cec5522cebd34b99ebbec90a8c Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 30 Aug 2024 17:34:54 -0700 Subject: [PATCH 089/187] fix build Signed-off-by: Nikolaj Bjorner --- src/smt/smt_context.cpp | 1 - src/util/vector.h | 618 ++++++++++++++++++++++++++++++++++------ 2 files changed, 527 insertions(+), 92 deletions(-) diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 84cdc6e69..c11084e56 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -99,7 +99,6 @@ namespace smt { m_model_generator->set_context(this); } - :: /** \brief retrieve flag for when cancelation is possible. */ diff --git a/src/util/vector.h b/src/util/vector.h index d684f43eb..e8ccf5ae8 100644 --- a/src/util/vector.h +++ b/src/util/vector.h @@ -45,120 +45,556 @@ Revision History: template using std_vector = std::vector>; -#if 0 +#if 1 -// portability guide to std::vector. -// memory allocator should be based on memory_allocator -// -// template -// struct memory_allocator { -// typedef T value_type; -// etc (interface seems to change between C++17, 20 versions) -// }; -// +template +class vector { + SZ m_capacity = 0; + SZ m_size = 0; + T* m_data = nullptr; -// Note: -// polynomial.h contains declaration -// typedef svector numeral_vector; -// it is crucial that it uses svector and not vector. The destructors on elements of the numeral vector are handled outside. -// Numeral gets instantiated by mpz and mpz does not support copy constructors. -// porting svector to vector is therefore blocked on the semantics of svector being -// copy-constructor free. -// + void destroy_elements() { + std::destroy_n(m_data, size()); + } -#include + void free_memory() { + memory::deallocate(m_data); + m_data = nullptr; + } + + void expand_vector() { + // ensure that the data is sufficiently aligned + // better fail to compile than produce code that may crash + + if (m_data == nullptr) { + m_capacity = 2; + m_size = 0; + m_data = reinterpret_cast(memory::allocate(sizeof(T) * m_capacity)); + } + else { + static_assert(std::is_nothrow_move_constructible::value); + SASSERT(capacity() > 0); + SZ old_capacity = m_capacity; + SZ new_capacity = (3 * old_capacity + 1) >> 1; + if (new_capacity <= old_capacity) { + throw default_exception("Overflow encountered when expanding vector"); + } + if (std::is_trivially_copyable::value) { + m_data = (T*)memory::reallocate(m_data, new_capacity); + } + else { + T* new_data = (T*)memory::allocate(new_capacity); + auto old_size = size(); + std::uninitialized_move_n(m_data, old_size, new_data); + destroy(); + m_data = new_data; + } + m_capacity = new_capacity; + } + } + + void copy_core(vector const& source) { + SASSERT(!m_data); + SZ size = source.size(); + SZ capacity = source.capacity(); + m_data = reinterpret_cast(memory::allocate(sizeof(T) * capacity)); + m_capacity = capacity; + m_size = size; + std::uninitialized_copy(source.begin(), source.end(), begin()); + } + + void destroy() { + if (m_data) { + if (CallDestructors) + destroy_elements(); + free_memory(); + } + } -template -class vector : public std::vector { public: typedef T data_t; - typedef typename std::vector::iterator iterator; + typedef T* iterator; + typedef const T* const_iterator; + + vector() = default; - vector() {} vector(SZ s) { - // TODO resize(s, T()); - } - vector(SZ s, T const& e) { - // TODO resize(s, e); + init(s); } - vector(SZ s, T const* e) { - // TODO - } - - void reset() { clear(); } - void finalize() { clear(); } - void reserve(SZ s, T const & d) { - if (s > size()) - resize(s, d); - } - void reserve(SZ s) { - - } - - void setx(SZ idx, T const & elem, T const & d) { - if (idx >= size()) - resize(idx+1, d); - (*this)[idx] = elem; - } - - T const & get(SZ idx, T const & d) const { - if (idx >= size()) { - return d; + void init(SZ s) { + SASSERT(m_data == nullptr); + if (s == 0) { + return; } - return (*this)[idx]; - } - - void insert(T const & elem) { - push_back(elem); - } - - void erase(iterator pos) { - // TODO - } - - void erase(T const& e) { - // TODO - } - void fill(T const & elem) { - for (auto& e : *this) - e = elem; - } - - void fill(unsigned sz, T const & elem) { - resize(sz); - fill(elem); - } - - void shrink(SZ s) { - resize(s); - } - void reverse() { - SZ sz = size(); - for (SZ i = 0; i < sz/2; ++i) { - std::swap((*this)[i], (*this)[sz-i-1]); + m_data = reinterpret_cast(memory::allocate(sizeof(T) * s)); + m_capacity = s; + m_size = s; + // initialize elements + iterator it = begin(); + iterator e = end(); + for (; it != e; ++it) { + new (it) T(); } } - void append(vector const & other) { - for(SZ i = 0; i < other.size(); ++i) { - push_back(other[i]); + vector(SZ s, T const& elem) { + resize(s, elem); + } + + vector(vector const& source) { + if (source.m_data) { + copy_core(source); + } + SASSERT(size() == source.size()); + } + + vector(vector&& other) noexcept { + std::swap(m_data, other.m_data); + } + + vector(SZ s, T const* data) { + for (SZ i = 0; i < s; i++) { + push_back(data[i]); } } - void append(unsigned n, T const* elems) { - // TODO + + ~vector() { + destroy(); } - bool contains(T const & elem) const { - for (auto const& e : *this) - if (e == elem) + void finalize() { + destroy(); + m_data = nullptr; + } + + bool operator==(vector const& other) const { + if (this == &other) { + return true; + } + if (size() != other.size()) + return false; + for (unsigned i = 0; i < size(); i++) { + if ((*this)[i] != other[i]) + return false; + } + return true; + } + + bool operator!=(vector const& other) const { + return !(*this == other); + } + + vector& operator=(vector const& source) { + if (this == &source) { + return *this; + } + destroy(); + if (source.m_data) + copy_core(source); + return *this; + } + + vector& operator=(vector&& source) noexcept { + if (this == &source) { + return *this; + } + destroy(); + std::swap(m_data, source.m_data); + return *this; + } + + bool containsp(std::function& predicate) const { + for (auto const& t : *this) + if (predicate(t)) return true; return false; } - -}; + /** + * retain elements that satisfy predicate. aka 'where'. + */ + vector filter_pure(std::function& predicate) const { + vector result; + for (auto& t : *this) + if (predicate(t)) + result.push_back(t); + return result; + } + + vector& filter_update(std::function& predicate) { + unsigned j = 0; + for (auto& t : *this) + if (predicate(t)) + set(j++, t); + shrink(j); + return *this; + } + + /** + * update elements using f, aka 'select' + */ + template + vector map_pure(std::function& f) const { + vector result; + for (auto& t : *this) + result.push_back(f(t)); + return result; + } + + vector& map_update(std::function& f) { + unsigned j = 0; + for (auto& t : *this) + set(j++, f(t)); + return *this; + } + + void reset() { + if (m_data) { + if (CallDestructors) { + destroy_elements(); + } + m_size = 0; + } + } + + void clear() { reset(); } + + bool empty() const { + return m_data == nullptr || m_size == 0; + } + + SZ size() const { + if (m_data == nullptr) { + return 0; + } + return m_size; + } + + SZ capacity() const { + if (m_data == nullptr) { + return 0; + } + return m_capacity; + } + + iterator begin() { + return m_data; + } + + iterator end() { + return m_data + size(); + } + + const_iterator begin() const { + return m_data; + } + + const_iterator end() const { + return m_data + size(); + } + + class reverse_iterator { + T* v; + public: + reverse_iterator(T* v) :v(v) {} + + T operator*() { return *v; } + reverse_iterator operator++(int) { + reverse_iterator tmp = *this; + --v; + return tmp; + } + reverse_iterator& operator++() { + --v; + return *this; + } + + bool operator==(reverse_iterator const& other) const { + return other.v == v; + } + bool operator!=(reverse_iterator const& other) const { + return other.v != v; + } + }; + + reverse_iterator rbegin() { return reverse_iterator(end() - 1); } + reverse_iterator rend() { return reverse_iterator(begin() - 1); } + + void set_end(iterator it) { + if (m_data) { + SZ new_sz = static_cast(it - m_data); + if (CallDestructors) { + iterator e = end(); + for (; it != e; ++it) { + it->~T(); + } + } + m_size = new_sz; + } + else { + SASSERT(it == 0); + } + } + + T& operator[](SZ idx) { + SASSERT(idx < size()); + return m_data[idx]; + } + + T const& operator[](SZ idx) const { + SASSERT(idx < size()); + return m_data[idx]; + } + + T& get(SZ idx) { + SASSERT(idx < size()); + return m_data[idx]; + } + + T const& get(SZ idx) const { + SASSERT(idx < size()); + return m_data[idx]; + } + + void set(SZ idx, T const& val) { + SASSERT(idx < size()); + m_data[idx] = val; + } + + void set(SZ idx, T&& val) { + SASSERT(idx < size()); + m_data[idx] = std::move(val); + } + + T& back() { + SASSERT(!empty()); + return operator[](size() - 1); + } + + T const& back() const { + SASSERT(!empty()); + return operator[](size() - 1); + } + + void pop_back() { + SASSERT(!empty()); + if (CallDestructors) { + back().~T(); + } + m_size--; + } + + vector& push_back(T const& elem) { + if (m_data == nullptr || m_size == m_capacity) { + expand_vector(); + } + new (m_data + m_size) T(elem); + m_size++; + return *this; + } + + template + vector& push_back(T const& elem, T elem2, Args ... elems) { + push_back(elem); + push_back(elem2, elems ...); + return *this; + } + + vector& push_back(T&& elem) { + if (m_data == nullptr || m_size == m_capacity) { + expand_vector(); + } + new (m_data + m_size) T(std::move(elem)); + ++m_size; + return *this; + } + + void insert(T const& elem) { + push_back(elem); + } + + void erase(iterator pos) { + SASSERT(pos >= begin() && pos < end()); + iterator prev = pos; + ++pos; + iterator e = end(); + for (; pos != e; ++pos, ++prev) { + *prev = std::move(*pos); + } + pop_back(); + } + + void erase(T const& elem) { + iterator it = std::find(begin(), end(), elem); + if (it != end()) { + erase(it); + } + } + + /** Erase all elements that satisfy the given predicate. Returns the number of erased elements. */ + template + SZ erase_if(UnaryPredicate should_erase) { + iterator i = begin(); + iterator const e = end(); + for (iterator j = begin(); j != e; ++j) + if (!should_erase(std::as_const(*j))) + *(i++) = std::move(*j); + SZ const count = e - i; + SASSERT_EQ(i - begin(), size() - count); + shrink(size() - count); + return count; + } + + void shrink(SZ s) { + if (m_data) { + SASSERT(s <= m_size); + if (CallDestructors) { + iterator it = m_data + s; + iterator e = end(); + for (; it != e; ++it) { + it->~T(); + } + } + m_size = s; + } + else { + SASSERT(s == 0); + } + } + + template + void resize(SZ s, Args args...) { + SZ sz = size(); + if (s <= sz) { shrink(s); return; } + while (s > capacity()) { + expand_vector(); + } + SASSERT(m_data != 0); + m_size = s; + iterator it = m_data + sz; + iterator end = m_data + s; + for (; it != end; ++it) { + new (it) T(std::forward(args)); + } + } + + void resize(SZ s) { + SZ sz = size(); + if (s <= sz) { shrink(s); return; } + while (s > capacity()) { + expand_vector(); + } + SASSERT(m_data != 0); + m_size = s; + iterator it = m_data + sz; + iterator end = m_data + s; + for (; it != end; ++it) { + new (it) T(); + } + } + + void append(vector const& other) { + for (SZ i = 0; i < other.size(); ++i) { + push_back(other[i]); + } + } + + void append(SZ sz, T const* data) { + for (SZ i = 0; i < sz; ++i) { + push_back(data[i]); + } + } + + void init(vector const& other) { + if (this == &other) + return; + reset(); + append(other); + } + + void init(SZ sz, T const* data) { + reset(); + append(sz, data); + } + + T* data() const { + return m_data; + } + + void swap(vector& other) noexcept { + std::swap(m_data, other.m_data); + } + + void reverse() { + SZ sz = size(); + for (SZ i = 0; i < sz / 2; ++i) { + std::swap(m_data[i], m_data[sz - i - 1]); + } + } + + void fill(T const& elem) { + iterator i = begin(); + iterator e = end(); + for (; i != e; ++i) { + *i = elem; + } + } + + void fill(unsigned sz, T const& elem) { + resize(sz); + fill(elem); + } + + bool contains(T const& elem) const { + const_iterator it = begin(); + const_iterator e = end(); + for (; it != e; ++it) { + if (*it == elem) { + return true; + } + } + return false; + } + + // set pos idx with elem. If idx >= size, then expand using default. + void setx(SZ idx, T const& elem, T const& d) { + if (idx >= size()) { + resize(idx + 1, d); + } + m_data[idx] = elem; + } + + // return element at position idx, if idx >= size, then return default + T const& get(SZ idx, T const& d) const { + if (idx >= size()) { + return d; + } + return m_data[idx]; + } + + void reserve(SZ s, T const& d) { + if (s > size()) + resize(s, d); + } + + void reserve(SZ s) { + if (s > size()) + resize(s); + } + + struct scoped_stack { + vector& s; + unsigned sz; + scoped_stack(vector& s) :s(s), sz(s.size()) {} + ~scoped_stack() { s.shrink(sz); } + }; + +}; + + + #else From a3eb2ff58d9da628c98a6e06faf3e449d04b6a54 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 30 Aug 2024 17:43:15 -0700 Subject: [PATCH 090/187] revert update to vector for testing #6902 Signed-off-by: Nikolaj Bjorner --- src/util/vector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/vector.h b/src/util/vector.h index e8ccf5ae8..31ced7f4b 100644 --- a/src/util/vector.h +++ b/src/util/vector.h @@ -45,7 +45,7 @@ Revision History: template using std_vector = std::vector>; -#if 1 +#if 0 template class vector { From ef58376c1463780af3ea1545ddb3e305f2bf2a2b Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Mon, 2 Sep 2024 16:13:46 +0100 Subject: [PATCH 091/187] replace a few old-school constructors for a 0.5% reduction in code size don't waste those 128 KB! --- src/ast/pattern/pattern_inference.h | 6 +++--- src/util/chashtable.h | 3 +-- src/util/memory_manager.h | 9 +++------ src/util/obj_hashtable.h | 5 ++--- src/util/symbol.h | 6 ++---- src/util/symbol_table.h | 7 ++++--- 6 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/ast/pattern/pattern_inference.h b/src/ast/pattern/pattern_inference.h index 8d179ba33..09c4e333b 100644 --- a/src/ast/pattern/pattern_inference.h +++ b/src/ast/pattern/pattern_inference.h @@ -114,9 +114,9 @@ class pattern_inference_cfg : public default_rewriter_cfg { // class collect { struct entry { - expr * m_node; - unsigned m_delta; - entry():m_node(nullptr), m_delta(0) {} + expr * m_node = nullptr; + unsigned m_delta = 0; + entry() = default; entry(expr * n, unsigned d):m_node(n), m_delta(d) {} unsigned hash() const { return hash_u_u(m_node->get_id(), m_delta); diff --git a/src/util/chashtable.h b/src/util/chashtable.h index b15d6017f..394e5998c 100644 --- a/src/util/chashtable.h +++ b/src/util/chashtable.h @@ -52,9 +52,8 @@ public: protected: struct cell { - cell * m_next; + cell * m_next = (cell*)1; T m_data; - cell():m_next(reinterpret_cast(1)) {} bool is_free() const { return GET_TAG(m_next) == 1; } void mark_free() { m_next = TAG(cell*, m_next, 1); } void unmark_free() { m_next = UNTAG(cell*, m_next); } diff --git a/src/util/memory_manager.h b/src/util/memory_manager.h index af56c4507..a52e3e3bd 100644 --- a/src/util/memory_manager.h +++ b/src/util/memory_manager.h @@ -19,6 +19,7 @@ Revision History: #pragma once #include +#include #include #include #include "util/z3_exception.h" @@ -105,18 +106,14 @@ ALLOC_ATTR T * alloc_vect(unsigned sz); template T * alloc_vect(unsigned sz) { T * r = static_cast(memory::allocate(sizeof(T) * sz)); - T * curr = r; - for (unsigned i = 0; i < sz; i++, curr++) - new (curr) T(); + std::uninitialized_default_construct_n(r, sz); return r; } template void dealloc_vect(T * ptr, unsigned sz) { if (ptr == nullptr) return; - T * curr = ptr; - for (unsigned i = 0; i < sz; i++, curr++) - curr->~T(); + std::destroy_n(ptr, sz); memory::deallocate(ptr); } diff --git a/src/util/obj_hashtable.h b/src/util/obj_hashtable.h index 49b37ca61..dbb2b776e 100644 --- a/src/util/obj_hashtable.h +++ b/src/util/obj_hashtable.h @@ -56,10 +56,9 @@ template class obj_map { public: struct key_data { - Key * m_key; + Key * m_key = nullptr; Value m_value; - key_data():m_key(nullptr), m_value() { - } + key_data() = default; key_data(Key * k): m_key(k), m_value() { } diff --git a/src/util/symbol.h b/src/util/symbol.h index ab7d41c98..721351b7e 100644 --- a/src/util/symbol.h +++ b/src/util/symbol.h @@ -29,7 +29,7 @@ template class symbol_table; class symbol { - char const * m_data; + char const * m_data = nullptr; template friend class symbol_table; @@ -50,9 +50,7 @@ class symbol { } static symbol m_dummy; public: - symbol(): - m_data(nullptr) { - } + symbol() = default; explicit symbol(char const * d); explicit symbol(const std::string & str) : symbol(str.c_str()) {} explicit symbol(unsigned idx): diff --git a/src/util/symbol_table.h b/src/util/symbol_table.h index 6a683f201..1a805ff35 100644 --- a/src/util/symbol_table.h +++ b/src/util/symbol_table.h @@ -31,8 +31,7 @@ class symbol_table { symbol m_key; T m_data; - key_data() { - } + key_data() = default; explicit key_data(symbol k): m_key(k) { @@ -59,10 +58,12 @@ class symbol_table { struct hash_entry { typedef key_data data; key_data m_data; - + +#if 0 hash_entry() { SASSERT(m_data.m_key == symbol::null); } +#endif unsigned get_hash() const { return m_data.m_key.hash(); From db4176adf41e7386e5b1f6f0fd3968486659f122 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 2 Sep 2024 17:01:25 -0700 Subject: [PATCH 092/187] #6902 See discussion under #6902. Add genaiscript for commit messages for future use. --- genaisrc/gcm.genai.mts | 81 +++++++++++++++++++++++++++++++++++++ src/util/memory_manager.cpp | 24 ++++++----- 2 files changed, 94 insertions(+), 11 deletions(-) create mode 100644 genaisrc/gcm.genai.mts diff --git a/genaisrc/gcm.genai.mts b/genaisrc/gcm.genai.mts new file mode 100644 index 000000000..b39e9a8e0 --- /dev/null +++ b/genaisrc/gcm.genai.mts @@ -0,0 +1,81 @@ +import { select, input, confirm } from "@inquirer/prompts" + +// Check for staged changes and stage all changes if none are staged +let diff = await host.exec("git", ["diff", "--cached"]) +if (!diff.stdout) { + const stage = await confirm({ + message: "No staged changes. Stage all changes?", + default: true, + }) + if (stage) { + await host.exec("git", ["add", "."]) + diff = await host.exec("git", [ + "diff", + "--cached", + "--", + ".", + ":!**/genaiscript.d.ts", + ]) + } + if (!diff.stdout) cancel("no staged changes") +} + +console.log(diff.stdout) + +let choice +let message +do { + // Generate commit message + message = ( + await runPrompt( + (_) => { + _.def("GIT_DIFF", diff, { maxTokens: 20000 }) + _.$`GIT_DIFF is a diff of all staged changes, coming from the command: +\`\`\` +git diff --cached +\`\`\` +Please generate a concise, one-line commit message for these changes. +- do NOT add quotes` + }, + { cache: false, temperature: 0.8 } + ) + ).text + + // Prompt user for commit message + choice = await select({ + message, + choices: [ + { + name: "commit", + value: "commit", + description: "accept message and commit", + }, + { + name: "edit", + value: "edit", + description: "edit message and commit", + }, + { + name: "regenerate", + value: "regenerate", + description: "regenerate message", + }, + ], + }) + + // Handle user choice + if (choice === "edit") { + message = await input({ + message: "Edit commit message", + required: true, + }) + choice = "commit" + } + // Regenerate message + if (choice === "commit" && message) { + console.log((await host.exec("git", ["commit", "-m", message])).stdout) + if (await confirm({ message: "Push changes?", default: true })) + console.log((await host.exec("git", ["push"])).stdout) + break + } +} while (choice !== "commit") diff --git a/src/util/memory_manager.cpp b/src/util/memory_manager.cpp index 290881ba5..4ef1cac66 100644 --- a/src/util/memory_manager.cpp +++ b/src/util/memory_manager.cpp @@ -29,6 +29,8 @@ Copyright (c) 2015 Microsoft Corporation # define malloc_usable_size _msize #endif +#define SIZE_T_ALIGN 2 + // The following two function are automatically generated by the mk_make.py script. // The script collects ADD_INITIALIZER and ADD_FINALIZER commands in the .h files. // For example, rational.h contains @@ -278,7 +280,7 @@ void memory::deallocate(void * p) { size_t sz = malloc_usable_size(p); void * real_p = p; #else - size_t * sz_p = reinterpret_cast(p) - 1; + size_t * sz_p = reinterpret_cast(p) - SIZE_T_ALIGN; size_t sz = *sz_p; void * real_p = reinterpret_cast(sz_p); #endif @@ -291,7 +293,7 @@ void memory::deallocate(void * p) { void * memory::allocate(size_t s) { #ifndef HAS_MALLOC_USABLE_SIZE - s = s + sizeof(size_t); // we allocate an extra field! + s = s + SIZE_T_ALIGN * sizeof(size_t); // we allocate an extra field! #endif g_memory_thread_alloc_size += s; g_memory_thread_alloc_count += 1; @@ -308,7 +310,7 @@ void * memory::allocate(size_t s) { return r; #else *(static_cast(r)) = s; - return static_cast(r) + 1; // we return a pointer to the location after the extra field + return static_cast(r) + SIZE_T_ALIGN; // we return a pointer to the location after the extra field #endif } @@ -323,7 +325,7 @@ void* memory::reallocate(void *p, size_t s) { size_t *sz_p = reinterpret_cast(p)-1; size_t sz = *sz_p; void *real_p = reinterpret_cast(sz_p); - s = s + sizeof(size_t); // we allocate an extra field! + s = s + SIZE_T_ALIGN * sizeof(size_t); // we allocate an extra field! #endif g_memory_thread_alloc_size += s - sz; g_memory_thread_alloc_count += 1; @@ -341,7 +343,7 @@ void* memory::reallocate(void *p, size_t s) { return r; #else *(static_cast(r)) = s; - return static_cast(r) + 1; // we return a pointer to the location after the extra field + return static_cast(r) + SIZE_T_ALIGN; // we return a pointer to the location after the extra field #endif } @@ -358,7 +360,7 @@ void memory::deallocate(void * p) { size_t sz = malloc_usable_size(p); void * real_p = p; #else - size_t * sz_p = reinterpret_cast(p) - 1; + size_t * sz_p = reinterpret_cast(p) - SIZE_T_ALIGN; size_t sz = *sz_p; void * real_p = reinterpret_cast(sz_p); #endif @@ -368,7 +370,7 @@ void memory::deallocate(void * p) { void * memory::allocate(size_t s) { #ifndef HAS_MALLOC_USABLE_SIZE - s = s + sizeof(size_t); // we allocate an extra field! + s = s + SIZE_T_ALIGN * sizeof(size_t); // we allocate an extra field! #endif g_memory_alloc_size += s; g_memory_alloc_count += 1; @@ -389,7 +391,7 @@ void * memory::allocate(size_t s) { return r; #else *(static_cast(r)) = s; - return static_cast(r) + 1; // we return a pointer to the location after the extra field + return static_cast(r) + SIZE_T_ALIGN; // we return a pointer to the location after the extra field #endif } @@ -401,10 +403,10 @@ void* memory::reallocate(void *p, size_t s) { if (sz >= s) return p; #else - size_t * sz_p = reinterpret_cast(p) - 1; + size_t * sz_p = reinterpret_cast(p) - SIZE_T_ALIGN; size_t sz = *sz_p; void * real_p = reinterpret_cast(sz_p); - s = s + sizeof(size_t); // we allocate an extra field! + s = s + SIZE_T_ALIGN * sizeof(size_t); // we allocate an extra field! #endif g_memory_alloc_size += s - sz; g_memory_alloc_count += 1; @@ -425,7 +427,7 @@ void* memory::reallocate(void *p, size_t s) { return r; #else *(static_cast(r)) = s; - return static_cast(r) + 1; // we return a pointer to the location after the extra field + return static_cast(r) + SIZE_T_ALIGN; // we return a pointer to the location after the extra field #endif } From 6086a30c071b7a3905c722810f3b53369edb32c0 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 2 Sep 2024 17:15:49 -0700 Subject: [PATCH 093/187] Add reference URL to GenAI script file for auto Git commit guide --- genaisrc/gcm.genai.mts | 1 + 1 file changed, 1 insertion(+) diff --git a/genaisrc/gcm.genai.mts b/genaisrc/gcm.genai.mts index b39e9a8e0..54f6762a8 100644 --- a/genaisrc/gcm.genai.mts +++ b/genaisrc/gcm.genai.mts @@ -1,3 +1,4 @@ +// https://microsoft.github.io/genaiscript/guides/auto-git-commit-message/ import { select, input, confirm } from "@inquirer/prompts" // Check for staged changes and stage all changes if none are staged From 5237e7def20fdbdace592ea60bd68ab51f9389b5 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 3 Sep 2024 11:17:47 -0700 Subject: [PATCH 094/187] Adjust memory reallocation to consider SIZE_T_ALIGN in memory_manager --- src/util/memory_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/memory_manager.cpp b/src/util/memory_manager.cpp index 4ef1cac66..8c6bfc7e7 100644 --- a/src/util/memory_manager.cpp +++ b/src/util/memory_manager.cpp @@ -322,7 +322,7 @@ void* memory::reallocate(void *p, size_t s) { if (sz >= s) return p; #else - size_t *sz_p = reinterpret_cast(p)-1; + size_t *sz_p = reinterpret_cast(p) - SIZE_T_ALIGN; size_t sz = *sz_p; void *real_p = reinterpret_cast(sz_p); s = s + SIZE_T_ALIGN * sizeof(size_t); // we allocate an extra field! From 0837e3b8e8736a6bd00f3f00976b1da1e2f762fc Mon Sep 17 00:00:00 2001 From: Audrey Dutcher Date: Tue, 3 Sep 2024 16:11:42 -0700 Subject: [PATCH 095/187] Fix nightly (#7365) - add some logic to setup.py to handle cross platform tagging correctly this adds a dependency on setuptools>=70 - rearrange the nightly CI to use these new builds correctly --- scripts/nightly.yaml | 13 +++++------- src/api/python/pyproject.toml | 2 +- src/api/python/setup.py | 38 +++++++++++++++++++++++++---------- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index 60aca338b..ccbed95f8 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -183,7 +183,7 @@ stages: - task: CopyFiles@2 inputs: sourceFolder: src/api/python/wheelhouse - contents: '*.zip' + contents: '*.whl' targetFolder: $(Build.ArtifactStagingDirectory) - task: PublishPipelineArtifact@0 inputs: @@ -209,11 +209,11 @@ stages: - script: echo $PATH - script: "stat `which aarch64-none-linux-gnu-gcc`" - script: "pip install build git+https://github.com/rhelmot/auditwheel" - - script: "cd src/api/python && CC=aarch64-none-linux-gnu-gcc CXX=aarch64-none-linux-gnu-g++ AR=aarch64-none-linux-gnu-ar LD=aarch64-none-linux-gnu-ld python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." + - script: "cd src/api/python && CC=aarch64-none-linux-gnu-gcc CXX=aarch64-none-linux-gnu-g++ AR=aarch64-none-linux-gnu-ar LD=aarch64-none-linux-gnu-ld Z3_CROSS_COMPILING=aarch64 python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." - task: CopyFiles@2 inputs: sourceFolder: src/api/python/wheelhouse - contents: '*.zip' + contents: '*.whl' targetFolder: $(Build.ArtifactStagingDirectory) - task: PublishPipelineArtifact@0 inputs: @@ -504,21 +504,18 @@ stages: targetPath: $(Agent.TempDirectory) - script: cd $(Agent.TempDirectory); mkdir osx-x64-bin; cd osx-x64-bin; unzip ../*x64-osx*.zip - script: cd $(Agent.TempDirectory); mkdir osx-arm64-bin; cd osx-arm64-bin; unzip ../*arm64-osx*.zip - - script: cd $(Agent.TempDirectory); mkdir libc-x64-bin; cd libc-x64-bin; unzip ../*x64-glibc*.zip - - script: cd $(Agent.TempDirectory); mkdir libc-arm64-bin; cd libc-arm64-bin; unzip ../*arm64-glibc*.zip # - script: cd $(Agent.TempDirectory); mkdir musl-bin; cd musl-bin; unzip ../*-linux.zip - script: cd $(Agent.TempDirectory); mkdir win32-bin; cd win32-bin; unzip ../*x86-win*.zip - script: cd $(Agent.TempDirectory); mkdir win64-bin; cd win64-bin; unzip ../*x64-win*.zip - - script: python3 -m pip install --user -U setuptools wheel + - script: python3 -m pip install --user -U setuptools - script: cd src/api/python; python3 setup.py sdist # take a look at this PREMIUM HACK I came up with to get around the fact that the azure variable syntax overloads the bash syntax for subshells - - script: cd src/api/python; echo $(Agent.TempDirectory)/libc-x64-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel - - script: cd src/api/python; echo $(Agent.TempDirectory)/libc-arm64-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel # - script: cd src/api/python; echo $(Agent.TempDirectory)/musl-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel - script: cd src/api/python; echo $(Agent.TempDirectory)/win32-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel - script: cd src/api/python; echo $(Agent.TempDirectory)/win64-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel - script: cd src/api/python; echo $(Agent.TempDirectory)/osx-x64-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel - script: cd src/api/python; echo $(Agent.TempDirectory)/osx-arm64-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel + - script: cp $(Agent.TempDirectory)/*.whl src/api/python/dist - task: PublishPipelineArtifact@0 inputs: artifactName: 'Python packages' diff --git a/src/api/python/pyproject.toml b/src/api/python/pyproject.toml index 62f43b591..ead5d1b2d 100644 --- a/src/api/python/pyproject.toml +++ b/src/api/python/pyproject.toml @@ -1,3 +1,3 @@ [build-system] -requires = ["setuptools>=59", "wheel", "cmake"] +requires = ["setuptools>=70", "cmake"] build-backend = "setuptools.build_meta" diff --git a/src/api/python/setup.py b/src/api/python/setup.py index f17527a01..f788aaf69 100644 --- a/src/api/python/setup.py +++ b/src/api/python/setup.py @@ -9,6 +9,7 @@ import glob from setuptools import setup from setuptools.command.build import build as _build from setuptools.command.sdist import sdist as _sdist +from setuptools.command.bdist_wheel import bdist_wheel as _bdist_wheel from setuptools.command.develop import develop as _develop class LibError(Exception): @@ -31,6 +32,8 @@ if RELEASE_DIR is None: HEADER_DIRS = [os.path.join(SRC_DIR, 'src', 'api'), os.path.join(SRC_DIR, 'src', 'api', 'c++')] RELEASE_METADATA = None BUILD_PLATFORM = sys.platform + BUILD_ARCH = os.environ.get("Z3_CROSS_COMPILING", platform.machine()) + BUILD_OS_VERSION = platform.mac_ver()[0].split(".") else: if not os.path.isdir(RELEASE_DIR): raise Exception("RELEASE_DIR (%s) is not a directory!" % RELEASE_DIR) @@ -41,6 +44,11 @@ else: raise Exception("RELEASE_DIR (%s) must be in the format z3-version-arch-os[-osversion] so we can extract metadata from it. Sorry!" % RELEASE_DIR) RELEASE_METADATA.pop(0) BUILD_PLATFORM = RELEASE_METADATA[2] + BUILD_ARCH = RELEASE_METADATA[1] + if len(RELEASE_METADATA) == 4: + BUILD_OS_VERSION = RELEASE_METADATA[3].split(".") + else: + BUILD_OS_VERSION = None # determine where destinations are LIBS_DIR = os.path.join(ROOT_DIR, 'z3', 'lib') @@ -242,21 +250,29 @@ class sdist(_sdist): self.execute(_copy_sources, (), msg="Copying source files") _sdist.run(self) -# platform.freedesktop_os_release was added in 3.10 -os_id = '' -if hasattr(platform, 'freedesktop_os_release'): - try: - osr = platform.freedesktop_os_release() - print(osr) - os_id = osr['ID'] - except OSError: - pass +class bdist_wheel(_bdist_wheel): + def finalize_options(self): + if BUILD_ARCH is not None and BUILD_PLATFORM is not None: + os_version_tag = '_'.join(BUILD_OS_VERSION[:2]) if BUILD_OS_VERSION is not None else 'xxxxxx' + TAGS = { + # linux tags cannot be deployed - they must be auditwheel'd to pick the right compatibility tag based on imported libc symbol versions + ("linux", "x86_64"): "linux_x86_64", + ("linux", "aarch64"): "linux_aarch64", + # windows arm64 is not supported by pypi yet + ("win", "x64"): "win_amd64", + ("win", "x86"): "win32", + ("osx", "x64"): f"macosx_{os_version_tag}_x86_64", + ("osx", "arm64"): f"macosx_{os_version_tag}_arm64", + } # type: dict[tuple[str, str], str] + self.plat_name = TAGS[(BUILD_PLATFORM, BUILD_ARCH)] + return super().finalize_options() + setup( name='z3-solver', version=_z3_version(), description='an efficient SMT solver library', - long_description='Z3 is a theorem prover from Microsoft Research with support for bitvectors, booleans, arrays, floating point numbers, strings, and other data types.\n\nFor documentation, please read http://z3prover.github.io/api/html/z3.html\n\nIn the event of technical difficulties related to configuration, compilation, or installation, please submit issues to https://github.com/z3prover/z3.git', + long_description='Z3 is a theorem prover from Microsoft Research with support for bitvectors, booleans, arrays, floating point numbers, strings, and other data types.\n\nFor documentation, please read http://z3prover.github.io/api/html/z3.html', author="The Z3 Theorem Prover Project", maintainer="Audrey Dutcher and Nikolaj Bjorner", maintainer_email="audrey@rhelmot.io", @@ -270,5 +286,5 @@ setup( 'z3': [os.path.join('lib', '*'), os.path.join('include', '*.h'), os.path.join('include', 'c++', '*.h')] }, data_files=[('bin',[os.path.join('bin',EXECUTABLE_FILE)])], - cmdclass={'build': build, 'develop': develop, 'sdist': sdist}, + cmdclass={'build': build, 'develop': develop, 'sdist': sdist, 'bdist_wheel': bdist_wheel}, ) From 8061765574aa9224e5f1d572b08c0881efe51285 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Wed, 4 Sep 2024 22:30:23 +0100 Subject: [PATCH 096/187] remove default destructors & some default constructors Another ~700 KB reduction in binary size --- src/ackermannization/lackr_model_constructor.cpp | 2 -- src/ast/ast_pp_dot.cpp | 2 -- src/ast/euf/euf_ac_plugin.h | 3 --- src/ast/euf/euf_arith_plugin.h | 2 -- src/ast/euf/euf_bv_plugin.h | 2 -- src/ast/euf/euf_specrel_plugin.h | 2 -- src/ast/rewriter/label_rewriter.cpp | 2 -- src/ast/rewriter/label_rewriter.h | 1 - src/ast/rewriter/rewriter.h | 2 -- src/ast/simplifiers/reduce_args_simplifier.cpp | 2 -- src/muz/base/rule_properties.cpp | 2 -- src/muz/base/rule_properties.h | 1 - src/muz/bmc/dl_bmc_engine.cpp | 2 -- src/muz/bmc/dl_bmc_engine.h | 2 -- src/muz/clp/clp_context.cpp | 2 -- src/muz/ddnf/ddnf.cpp | 6 ------ src/muz/spacer/spacer_expand_bnd_generalizer.h | 1 - src/muz/spacer/spacer_global_generalizer.h | 1 - src/muz/tab/tab_context.cpp | 2 -- src/muz/transforms/dl_mk_array_eq_rewrite.h | 1 - src/muz/transforms/dl_mk_array_instantiation.h | 1 - src/muz/transforms/dl_mk_backwards.cpp | 2 -- src/muz/transforms/dl_mk_backwards.h | 1 - src/muz/transforms/dl_mk_bit_blast.cpp | 2 -- src/muz/transforms/dl_mk_elim_term_ite.cpp | 2 -- src/muz/transforms/dl_mk_elim_term_ite.h | 1 - src/muz/transforms/dl_mk_karr_invariants.cpp | 2 -- src/muz/transforms/dl_mk_karr_invariants.h | 2 -- src/muz/transforms/dl_mk_loop_counter.cpp | 2 -- src/muz/transforms/dl_mk_loop_counter.h | 1 - src/muz/transforms/dl_mk_magic_symbolic.cpp | 2 -- src/muz/transforms/dl_mk_magic_symbolic.h | 1 - src/qe/mbp/mbp_arith.cpp | 2 -- src/qe/mbp/mbp_arrays.cpp | 1 - src/qe/mbp/mbp_term_graph.cpp | 2 -- src/qe/nlqsat.cpp | 1 - src/sat/sat_model_converter.h | 1 - src/sat/sat_mus.cpp | 2 -- src/sat/sat_mus.h | 1 - src/sat/smt/arith_sls.h | 1 - src/sat/smt/array_solver.cpp | 2 -- src/sat/smt/array_solver.h | 1 - src/sat/smt/intblast_solver.h | 2 -- src/smt/arith_eq_adapter.cpp | 2 -- src/smt/smt_model_finder.cpp | 2 -- src/smt/smt_relevancy.h | 2 -- src/smt/theory_seq.h | 1 - src/solver/simplifier_solver.cpp | 1 - src/solver/solver_na2as.cpp | 2 -- src/solver/solver_na2as.h | 1 - src/tactic/arith/nla2bv_tactic.cpp | 2 -- src/tactic/bv/bv_bound_chk_tactic.cpp | 6 +----- src/tactic/bv/bv_bounds_tactic.cpp | 2 -- src/tactic/core/ctx_simplify_tactic.cpp | 5 ++--- src/tactic/core/symmetry_reduce_tactic.cpp | 10 +++------- src/tactic/probe.h | 3 +-- src/tactic/tactic.cpp | 2 -- src/tactic/tactic.h | 4 +--- src/util/chashtable.h | 2 +- src/util/optional.h | 6 +++--- src/util/params.cpp | 3 +-- src/util/queue.h | 7 ++----- src/util/rational.h | 4 ++-- src/util/s_integer.h | 4 ++-- src/util/small_object_allocator.h | 3 +-- src/util/vector.h | 4 ++-- 66 files changed, 22 insertions(+), 131 deletions(-) diff --git a/src/ackermannization/lackr_model_constructor.cpp b/src/ackermannization/lackr_model_constructor.cpp index 76c1803f2..ec4727152 100644 --- a/src/ackermannization/lackr_model_constructor.cpp +++ b/src/ackermannization/lackr_model_constructor.cpp @@ -41,8 +41,6 @@ public: , m_ackr_helper(m) {} - ~imp() { } - // // Returns true iff model was successfully constructed. // Conflicts are saved as a side effect. diff --git a/src/ast/ast_pp_dot.cpp b/src/ast/ast_pp_dot.cpp index 47da4d4f4..1298239a2 100644 --- a/src/ast/ast_pp_dot.cpp +++ b/src/ast/ast_pp_dot.cpp @@ -45,8 +45,6 @@ struct ast_pp_dot_st { m_printed(), m_to_print(), m_first(true) {} - - ~ast_pp_dot_st() {}; void push_term(const expr * a) { m_to_print.push_back(a); } diff --git a/src/ast/euf/euf_ac_plugin.h b/src/ast/euf/euf_ac_plugin.h index 7da346dba..2963c1f8b 100644 --- a/src/ast/euf/euf_ac_plugin.h +++ b/src/ast/euf/euf_ac_plugin.h @@ -47,7 +47,6 @@ namespace euf { unsigned_vector eqs; // equality occurrences unsigned root_id() const { return root->n->get_id(); } - ~node() {} static node* mk(region& r, enode* n); }; @@ -270,8 +269,6 @@ namespace euf { ac_plugin(egraph& g, unsigned fid, unsigned op); ac_plugin(egraph& g, func_decl* f); - - ~ac_plugin() override {} theory_id get_id() const override { return m_fid; } diff --git a/src/ast/euf/euf_arith_plugin.h b/src/ast/euf/euf_arith_plugin.h index 4c2a88d36..0cc122d99 100644 --- a/src/ast/euf/euf_arith_plugin.h +++ b/src/ast/euf/euf_arith_plugin.h @@ -33,8 +33,6 @@ namespace euf { public: arith_plugin(egraph& g); - ~arith_plugin() override {} - theory_id get_id() const override { return a.get_family_id(); } void register_node(enode* n) override; diff --git a/src/ast/euf/euf_bv_plugin.h b/src/ast/euf/euf_bv_plugin.h index ec2c0b448..6bf48df2a 100644 --- a/src/ast/euf/euf_bv_plugin.h +++ b/src/ast/euf/euf_bv_plugin.h @@ -95,8 +95,6 @@ namespace euf { public: bv_plugin(egraph& g); - ~bv_plugin() override {} - theory_id get_id() const override { return bv.get_family_id(); } void register_node(enode* n) override; diff --git a/src/ast/euf/euf_specrel_plugin.h b/src/ast/euf/euf_specrel_plugin.h index ae93bd2a5..5e3578ccf 100644 --- a/src/ast/euf/euf_specrel_plugin.h +++ b/src/ast/euf/euf_specrel_plugin.h @@ -34,8 +34,6 @@ namespace euf { public: specrel_plugin(egraph& g); - - ~specrel_plugin() override {} theory_id get_id() const override { return sp.get_family_id(); } diff --git a/src/ast/rewriter/label_rewriter.cpp b/src/ast/rewriter/label_rewriter.cpp index 8adefb896..548d4fa82 100644 --- a/src/ast/rewriter/label_rewriter.cpp +++ b/src/ast/rewriter/label_rewriter.cpp @@ -26,8 +26,6 @@ label_rewriter::label_rewriter(ast_manager & m) : m_label_fid(m.get_label_family_id()), m_rwr(m, false, *this) {} -label_rewriter::~label_rewriter() {} - br_status label_rewriter::reduce_app( func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { diff --git a/src/ast/rewriter/label_rewriter.h b/src/ast/rewriter/label_rewriter.h index 8bec62ed6..a4720853c 100644 --- a/src/ast/rewriter/label_rewriter.h +++ b/src/ast/rewriter/label_rewriter.h @@ -27,7 +27,6 @@ class label_rewriter : public default_rewriter_cfg { rewriter_tpl m_rwr; public: label_rewriter(ast_manager & m); - ~label_rewriter(); br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr); diff --git a/src/ast/rewriter/rewriter.h b/src/ast/rewriter/rewriter.h index cd89bb2f9..1afa19f84 100644 --- a/src/ast/rewriter/rewriter.h +++ b/src/ast/rewriter/rewriter.h @@ -346,8 +346,6 @@ public: ast_manager & m() const { return this->m_manager; } Config & cfg() { return m_cfg; } Config const & cfg() const { return m_cfg; } - - ~rewriter_tpl() override {}; void reset(); void cleanup(); diff --git a/src/ast/simplifiers/reduce_args_simplifier.cpp b/src/ast/simplifiers/reduce_args_simplifier.cpp index f9c788792..96607734b 100644 --- a/src/ast/simplifiers/reduce_args_simplifier.cpp +++ b/src/ast/simplifiers/reduce_args_simplifier.cpp @@ -375,8 +375,6 @@ public: m_bv(m) {} - ~reduce_args_simplifier() override {} - char const* name() const override { return "reduce-args"; } void collect_statistics(statistics& st) const override { diff --git a/src/muz/base/rule_properties.cpp b/src/muz/base/rule_properties.cpp index 239fa73b6..abd79c515 100644 --- a/src/muz/base/rule_properties.cpp +++ b/src/muz/base/rule_properties.cpp @@ -31,8 +31,6 @@ rule_properties::rule_properties(ast_manager & m, rule_manager& rm, context& ctx m_dt(m), m_dl(m), m_a(m), m_bv(m), m_ar(m), m_rec(m), m_generate_proof(false), m_collected(false), m_is_monotone(true) {} -rule_properties::~rule_properties() {} - void rule_properties::collect(rule_set const& rules) { reset(); m_collected = true; diff --git a/src/muz/base/rule_properties.h b/src/muz/base/rule_properties.h index a7ef9a0de..3159c28a6 100644 --- a/src/muz/base/rule_properties.h +++ b/src/muz/base/rule_properties.h @@ -58,7 +58,6 @@ namespace datalog { bool check_accessor(app* n); public: rule_properties(ast_manager & m, rule_manager& rm, context& ctx, i_expr_pred& is_predicate); - ~rule_properties(); void set_generate_proof(bool generate_proof) { m_generate_proof = generate_proof; } void collect(rule_set const& r); void check_quantifier_free(); diff --git a/src/muz/bmc/dl_bmc_engine.cpp b/src/muz/bmc/dl_bmc_engine.cpp index 913e35f36..e83569e0e 100644 --- a/src/muz/bmc/dl_bmc_engine.cpp +++ b/src/muz/bmc/dl_bmc_engine.cpp @@ -1443,8 +1443,6 @@ namespace datalog { m_rule_trace(ctx.get_rule_manager()) { } - bmc::~bmc() {} - lbool bmc::query(expr* query) { m_solver = nullptr; m_answer = nullptr; diff --git a/src/muz/bmc/dl_bmc_engine.h b/src/muz/bmc/dl_bmc_engine.h index 90c4ab862..05d5707a6 100644 --- a/src/muz/bmc/dl_bmc_engine.h +++ b/src/muz/bmc/dl_bmc_engine.h @@ -51,8 +51,6 @@ namespace datalog { public: bmc(context& ctx); - ~bmc() override; - lbool query(expr* query) override; void display_certificate(std::ostream& out) const override; diff --git a/src/muz/clp/clp_context.cpp b/src/muz/clp/clp_context.cpp index 89ae71e36..9d4baa4ae 100644 --- a/src/muz/clp/clp_context.cpp +++ b/src/muz/clp/clp_context.cpp @@ -59,8 +59,6 @@ namespace datalog { m_fparams.m_mbqi = false; } - ~imp() {} - lbool query(expr* query) { m_ctx.ensure_opened(); m_solver.reset(); diff --git a/src/muz/ddnf/ddnf.cpp b/src/muz/ddnf/ddnf.cpp index cf759c76e..f4f946d09 100644 --- a/src/muz/ddnf/ddnf.cpp +++ b/src/muz/ddnf/ddnf.cpp @@ -78,8 +78,6 @@ namespace datalog { m_descendants(DEFAULT_HASHTABLE_INITIAL_CAPACITY, m_hash, m_eq) { } - ~ddnf_node() {} - unsigned inc_ref() { return ++m_refs; } @@ -429,8 +427,6 @@ namespace datalog { class ddnfs { u_map m_mgrs; public: - ddnfs() {} - ~ddnfs() { u_map::iterator it = m_mgrs.begin(), end = m_mgrs.end(); for (; it != end; ++it) { @@ -503,8 +499,6 @@ namespace datalog { m_inner_ctx.updt_params(params); } - ~imp() {} - lbool query(expr* query) { m_ctx.ensure_opened(); rule_set& old_rules = m_ctx.get_rules(); diff --git a/src/muz/spacer/spacer_expand_bnd_generalizer.h b/src/muz/spacer/spacer_expand_bnd_generalizer.h index 91ba3b417..6d4e68d17 100644 --- a/src/muz/spacer/spacer_expand_bnd_generalizer.h +++ b/src/muz/spacer/spacer_expand_bnd_generalizer.h @@ -43,7 +43,6 @@ class lemma_expand_bnd_generalizer : public lemma_generalizer { public: lemma_expand_bnd_generalizer(context &ctx); - ~lemma_expand_bnd_generalizer() override {} void operator()(lemma_ref &lemma) override; diff --git a/src/muz/spacer/spacer_global_generalizer.h b/src/muz/spacer/spacer_global_generalizer.h index 00b85ecd5..b7ee05757 100644 --- a/src/muz/spacer/spacer_global_generalizer.h +++ b/src/muz/spacer/spacer_global_generalizer.h @@ -161,7 +161,6 @@ class lemma_global_generalizer : public lemma_generalizer { public: lemma_global_generalizer(context &ctx); - ~lemma_global_generalizer() override {} void operator()(lemma_ref &lemma) override; diff --git a/src/muz/tab/tab_context.cpp b/src/muz/tab/tab_context.cpp index f65661e9e..175c8aeb8 100644 --- a/src/muz/tab/tab_context.cpp +++ b/src/muz/tab/tab_context.cpp @@ -1354,8 +1354,6 @@ namespace datalog { m_fparams.m_mbqi = false; } - ~imp() {} - lbool query(expr* query) { m_ctx.ensure_opened(); m_index.reset(); diff --git a/src/muz/transforms/dl_mk_array_eq_rewrite.h b/src/muz/transforms/dl_mk_array_eq_rewrite.h index 7f6a29bf3..eabef4792 100644 --- a/src/muz/transforms/dl_mk_array_eq_rewrite.h +++ b/src/muz/transforms/dl_mk_array_eq_rewrite.h @@ -40,7 +40,6 @@ namespace datalog { public: mk_array_eq_rewrite(context & ctx, unsigned priority); rule_set * operator()(rule_set const & source) override; - ~mk_array_eq_rewrite() override{} }; diff --git a/src/muz/transforms/dl_mk_array_instantiation.h b/src/muz/transforms/dl_mk_array_instantiation.h index 0002f4ecd..71924288f 100644 --- a/src/muz/transforms/dl_mk_array_instantiation.h +++ b/src/muz/transforms/dl_mk_array_instantiation.h @@ -112,7 +112,6 @@ namespace datalog { public: mk_array_instantiation(context & ctx, unsigned priority); rule_set * operator()(rule_set const & source) override; - ~mk_array_instantiation() override{} }; diff --git a/src/muz/transforms/dl_mk_backwards.cpp b/src/muz/transforms/dl_mk_backwards.cpp index 5d124336b..5024d4631 100644 --- a/src/muz/transforms/dl_mk_backwards.cpp +++ b/src/muz/transforms/dl_mk_backwards.cpp @@ -27,8 +27,6 @@ namespace datalog { m(ctx.get_manager()), m_ctx(ctx) { } - - mk_backwards::~mk_backwards() { } rule_set * mk_backwards::operator()(rule_set const & source) { context& ctx = source.get_context(); diff --git a/src/muz/transforms/dl_mk_backwards.h b/src/muz/transforms/dl_mk_backwards.h index 78a9d2fd0..4d1522e02 100644 --- a/src/muz/transforms/dl_mk_backwards.h +++ b/src/muz/transforms/dl_mk_backwards.h @@ -27,7 +27,6 @@ namespace datalog { context& m_ctx; public: mk_backwards(context & ctx, unsigned priority = 33000); - ~mk_backwards() override; rule_set * operator()(rule_set const & source) override; }; diff --git a/src/muz/transforms/dl_mk_bit_blast.cpp b/src/muz/transforms/dl_mk_bit_blast.cpp index 439cb4540..0072f0078 100644 --- a/src/muz/transforms/dl_mk_bit_blast.cpp +++ b/src/muz/transforms/dl_mk_bit_blast.cpp @@ -146,8 +146,6 @@ namespace datalog { m_dst(nullptr) {} - ~expand_mkbv_cfg() {} - void set_src(rule_set const* src) { m_src = src; } void set_dst(rule_set* dst) { m_dst = dst; } func_decl_ref_vector const& old_funcs() const { return m_old_funcs; } diff --git a/src/muz/transforms/dl_mk_elim_term_ite.cpp b/src/muz/transforms/dl_mk_elim_term_ite.cpp index 753b82cea..98bd3c41a 100644 --- a/src/muz/transforms/dl_mk_elim_term_ite.cpp +++ b/src/muz/transforms/dl_mk_elim_term_ite.cpp @@ -80,8 +80,6 @@ namespace datalog { rm(ctx.get_rule_manager()), m_ground(m) {} - mk_elim_term_ite::~mk_elim_term_ite() {} - /** \brief map free variables in e to ground, fresh, constants m_ground is reset on every new rule so it is safe to assume diff --git a/src/muz/transforms/dl_mk_elim_term_ite.h b/src/muz/transforms/dl_mk_elim_term_ite.h index 98acd12f1..d42a7d773 100644 --- a/src/muz/transforms/dl_mk_elim_term_ite.h +++ b/src/muz/transforms/dl_mk_elim_term_ite.h @@ -35,7 +35,6 @@ namespace datalog { expr_ref ground(expr* e); public: mk_elim_term_ite(context &ctx, unsigned priority); - ~mk_elim_term_ite() override; rule_set * operator()(const rule_set &source) override; }; } diff --git a/src/muz/transforms/dl_mk_karr_invariants.cpp b/src/muz/transforms/dl_mk_karr_invariants.cpp index 18d67f549..955c3ca92 100644 --- a/src/muz/transforms/dl_mk_karr_invariants.cpp +++ b/src/muz/transforms/dl_mk_karr_invariants.cpp @@ -58,8 +58,6 @@ namespace datalog { m_inner_ctx.updt_params(params); } - mk_karr_invariants::~mk_karr_invariants() { } - void matrix::display_row( std::ostream& out, vector const& row, rational const& b, bool is_eq) { for (unsigned j = 0; j < row.size(); ++j) { diff --git a/src/muz/transforms/dl_mk_karr_invariants.h b/src/muz/transforms/dl_mk_karr_invariants.h index ac1015d14..9ba579a60 100644 --- a/src/muz/transforms/dl_mk_karr_invariants.h +++ b/src/muz/transforms/dl_mk_karr_invariants.h @@ -62,8 +62,6 @@ namespace datalog { rule_set* update_rules(rule_set const& src); public: mk_karr_invariants(context & ctx, unsigned priority); - - ~mk_karr_invariants() override; rule_set * operator()(rule_set const & source) override; diff --git a/src/muz/transforms/dl_mk_loop_counter.cpp b/src/muz/transforms/dl_mk_loop_counter.cpp index 91aaa8d8b..a20224eb2 100644 --- a/src/muz/transforms/dl_mk_loop_counter.cpp +++ b/src/muz/transforms/dl_mk_loop_counter.cpp @@ -30,8 +30,6 @@ namespace datalog { m_refs(m) { } - mk_loop_counter::~mk_loop_counter() { } - app_ref mk_loop_counter::add_arg(rule_set const& src, rule_set& dst, app* fn, unsigned idx) { expr_ref_vector args(m); func_decl* new_fn, *old_fn = fn->get_decl(); diff --git a/src/muz/transforms/dl_mk_loop_counter.h b/src/muz/transforms/dl_mk_loop_counter.h index 067945caf..b2758df67 100644 --- a/src/muz/transforms/dl_mk_loop_counter.h +++ b/src/muz/transforms/dl_mk_loop_counter.h @@ -35,7 +35,6 @@ namespace datalog { app_ref del_arg(app* fn); public: mk_loop_counter(context & ctx, unsigned priority = 33000); - ~mk_loop_counter() override; rule_set * operator()(rule_set const & source) override; diff --git a/src/muz/transforms/dl_mk_magic_symbolic.cpp b/src/muz/transforms/dl_mk_magic_symbolic.cpp index 59529e630..afadfd6c3 100644 --- a/src/muz/transforms/dl_mk_magic_symbolic.cpp +++ b/src/muz/transforms/dl_mk_magic_symbolic.cpp @@ -63,8 +63,6 @@ namespace datalog { m(ctx.get_manager()), m_ctx(ctx) { } - - mk_magic_symbolic::~mk_magic_symbolic() { } rule_set * mk_magic_symbolic::operator()(rule_set const & source) { if (!m_ctx.magic()) { diff --git a/src/muz/transforms/dl_mk_magic_symbolic.h b/src/muz/transforms/dl_mk_magic_symbolic.h index 208f79f45..ac29194bc 100644 --- a/src/muz/transforms/dl_mk_magic_symbolic.h +++ b/src/muz/transforms/dl_mk_magic_symbolic.h @@ -29,7 +29,6 @@ namespace datalog { app_ref mk_query(app* q); public: mk_magic_symbolic(context & ctx, unsigned priority = 33037); - ~mk_magic_symbolic() override; rule_set * operator()(rule_set const & source) override; }; diff --git a/src/qe/mbp/mbp_arith.cpp b/src/qe/mbp/mbp_arith.cpp index 255c4f814..ef4428fa7 100644 --- a/src/qe/mbp/mbp_arith.cpp +++ b/src/qe/mbp/mbp_arith.cpp @@ -43,8 +43,6 @@ namespace mbp { imp(ast_manager& m) : m(m), a(m) {} - ~imp() {} - void insert_mul(expr* x, rational const& v, obj_map& ts) { rational w; if (ts.find(x, w)) diff --git a/src/qe/mbp/mbp_arrays.cpp b/src/qe/mbp/mbp_arrays.cpp index bf3ad08ed..fa7ec8cb5 100644 --- a/src/qe/mbp/mbp_arrays.cpp +++ b/src/qe/mbp/mbp_arrays.cpp @@ -1058,7 +1058,6 @@ namespace mbp { scoped_ptr m_var; imp(ast_manager& m): m(m), a(m), m_stores(m) {} - ~imp() {} bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) { return false; diff --git a/src/qe/mbp/mbp_term_graph.cpp b/src/qe/mbp/mbp_term_graph.cpp index e5e5309f3..6ecaa5de2 100644 --- a/src/qe/mbp/mbp_term_graph.cpp +++ b/src/qe/mbp/mbp_term_graph.cpp @@ -187,8 +187,6 @@ class term { m_is_peq = is_partial_eq(to_app(m_expr)); } - ~term() {} - class parents { term const &t; diff --git a/src/qe/nlqsat.cpp b/src/qe/nlqsat.cpp index 8a6f910bc..37cf62c61 100644 --- a/src/qe/nlqsat.cpp +++ b/src/qe/nlqsat.cpp @@ -558,7 +558,6 @@ namespace qe { vector
m_divs; public: div_rewriter_cfg(nlqsat& s): m(s.m), a(s.m), m_zero(a.mk_real(0), m) {} - ~div_rewriter_cfg() {} br_status reduce_app(func_decl* f, unsigned sz, expr* const* args, expr_ref& result, proof_ref& pr) { rational r1, r(1); if (a.is_div(f) && sz == 2 && a.is_numeral(args[0], r1) && a.is_numeral(args[1], r) && !r.is_zero()) { diff --git a/src/sat/sat_model_converter.h b/src/sat/sat_model_converter.h index a331bef8e..7393dc1bb 100644 --- a/src/sat/sat_model_converter.h +++ b/src/sat/sat_model_converter.h @@ -58,7 +58,6 @@ namespace sat { m_stack(std::move(stack)) { m_counter = ++counter; } - ~elim_stack() { } void inc_ref() { ++m_refcount; } void dec_ref() { if (0 == --m_refcount) { dealloc(this); } } elim_stackv const& stack() const { return m_stack; } diff --git a/src/sat/sat_mus.cpp b/src/sat/sat_mus.cpp index cbbf01b20..5b7542cb2 100644 --- a/src/sat/sat_mus.cpp +++ b/src/sat/sat_mus.cpp @@ -24,8 +24,6 @@ Notes: namespace sat { mus::mus(solver& s):s(s), m_is_active(false), m_max_num_restarts(UINT_MAX) {} - - mus::~mus() {} void mus::reset() { m_core.reset(); diff --git a/src/sat/sat_mus.h b/src/sat/sat_mus.h index 5f67f6acd..672e90185 100644 --- a/src/sat/sat_mus.h +++ b/src/sat/sat_mus.h @@ -30,7 +30,6 @@ namespace sat { public: mus(solver& s); - ~mus(); lbool operator()(); bool is_active() const { return m_is_active; } model const& get_model() const { return m_model; } diff --git a/src/sat/smt/arith_sls.h b/src/sat/smt/arith_sls.h index 55d39b252..a65ca686d 100644 --- a/src/sat/smt/arith_sls.h +++ b/src/sat/smt/arith_sls.h @@ -153,7 +153,6 @@ namespace arith { public: sls(solver& s); - ~sls() override {} void set(sat::ddfw* d); void init_search() override; void finish_search() override; diff --git a/src/sat/smt/array_solver.cpp b/src/sat/smt/array_solver.cpp index 7a8f31f1e..1343577d9 100644 --- a/src/sat/smt/array_solver.cpp +++ b/src/sat/smt/array_solver.cpp @@ -88,8 +88,6 @@ namespace array { m_constraint->initialize(m_constraint.get(), this); } - solver::~solver() {} - sat::check_result solver::check() { force_push(); // flet _is_redundant(m_is_redundant, true); diff --git a/src/sat/smt/array_solver.h b/src/sat/smt/array_solver.h index 8dc6e4e84..0a7c854fd 100644 --- a/src/sat/smt/array_solver.h +++ b/src/sat/smt/array_solver.h @@ -268,7 +268,6 @@ namespace array { void validate_extensionality(euf::enode* s, euf::enode* t) const; public: solver(euf::solver& ctx, theory_id id); - ~solver() override; bool is_external(bool_var v) override { return false; } void get_antecedents(literal l, sat::ext_justification_idx idx, literal_vector& r, bool probing) override {} void asserted(literal l) override {} diff --git a/src/sat/smt/intblast_solver.h b/src/sat/smt/intblast_solver.h index 34f876be6..ee8d6fb19 100644 --- a/src/sat/smt/intblast_solver.h +++ b/src/sat/smt/intblast_solver.h @@ -103,8 +103,6 @@ namespace intblast { public: solver(euf::solver& ctx); - - ~solver() override {} lbool check_axiom(sat::literal_vector const& lits); lbool check_core(sat::literal_vector const& lits, euf::enode_pair_vector const& eqs); diff --git a/src/smt/arith_eq_adapter.cpp b/src/smt/arith_eq_adapter.cpp index f251d01ae..b77a38927 100644 --- a/src/smt/arith_eq_adapter.cpp +++ b/src/smt/arith_eq_adapter.cpp @@ -67,8 +67,6 @@ namespace smt { m_ge(ge) { } - ~arith_eq_relevancy_eh() override {} - void operator()(relevancy_propagator & rp) override { if (!rp.is_relevant(m_n1)) return; diff --git a/src/smt/smt_model_finder.cpp b/src/smt/smt_model_finder.cpp index 4139b3109..7a567d5a9 100644 --- a/src/smt/smt_model_finder.cpp +++ b/src/smt/smt_model_finder.cpp @@ -223,8 +223,6 @@ namespace smt { m_sort(s) { } - ~node() {} - unsigned get_id() const { return m_id; } sort* get_sort() const { return m_sort; } diff --git a/src/smt/smt_relevancy.h b/src/smt/smt_relevancy.h index f6e3c4659..8dea2842f 100644 --- a/src/smt/smt_relevancy.h +++ b/src/smt/smt_relevancy.h @@ -48,7 +48,6 @@ namespace smt { expr * m_target; public: simple_relevancy_eh(expr * t):m_target(t) {} - ~simple_relevancy_eh() override {} void operator()(relevancy_propagator & rp) override; }; @@ -61,7 +60,6 @@ namespace smt { expr * m_target; public: pair_relevancy_eh(expr * s1, expr * s2, expr * t):m_source1(s1), m_source2(s2), m_target(t) {} - ~pair_relevancy_eh() override {} void operator()(relevancy_propagator & rp) override; }; diff --git a/src/smt/theory_seq.h b/src/smt/theory_seq.h index 6ed4fc41f..d469097d8 100644 --- a/src/smt/theory_seq.h +++ b/src/smt/theory_seq.h @@ -134,7 +134,6 @@ namespace smt { unsigned_vector m_limit; public: exclusion_table(ast_manager& m): m(m), m_lhs(m), m_rhs(m) {} - ~exclusion_table() { } bool empty() const { return m_table.empty(); } void update(expr* e, expr* r); bool contains(expr* e, expr* r) const; diff --git a/src/solver/simplifier_solver.cpp b/src/solver/simplifier_solver.cpp index ed645dae0..8995049f0 100644 --- a/src/solver/simplifier_solver.cpp +++ b/src/solver/simplifier_solver.cpp @@ -38,7 +38,6 @@ class simplifier_solver : public solver { model_reconstruction_trail m_reconstruction_trail; bool m_updated = false; dep_expr_state(simplifier_solver& s) :dependent_expr_state(s.m), s(s), m_reconstruction_trail(s.m, m_trail) {} - ~dep_expr_state() override {} unsigned qtail() const override { return s.m_fmls.size(); } dependent_expr const& operator[](unsigned i) override { return s.m_fmls[i]; } void update(unsigned i, dependent_expr const& j) override { diff --git a/src/solver/solver_na2as.cpp b/src/solver/solver_na2as.cpp index 605a32ae1..31c4ad9f3 100644 --- a/src/solver/solver_na2as.cpp +++ b/src/solver/solver_na2as.cpp @@ -28,8 +28,6 @@ solver_na2as::solver_na2as(ast_manager & m): m_assumptions(m) { } -solver_na2as::~solver_na2as() {} - void solver_na2as::assert_expr_core2(expr * t, expr * a) { if (a == nullptr) { assert_expr_core(t); diff --git a/src/solver/solver_na2as.h b/src/solver/solver_na2as.h index 81a58fb39..fd0a7dc5e 100644 --- a/src/solver/solver_na2as.h +++ b/src/solver/solver_na2as.h @@ -30,7 +30,6 @@ class solver_na2as : public solver { void restore_assumptions(unsigned old_sz); public: solver_na2as(ast_manager & m); - ~solver_na2as() override; void assert_expr_core2(expr * t, expr * a) override; diff --git a/src/tactic/arith/nla2bv_tactic.cpp b/src/tactic/arith/nla2bv_tactic.cpp index c791841ec..31ca836ac 100644 --- a/src/tactic/arith/nla2bv_tactic.cpp +++ b/src/tactic/arith/nla2bv_tactic.cpp @@ -79,8 +79,6 @@ class nla2bv_tactic : public tactic { m_default_bv_size = m_num_bits = p.get_uint("nla2bv_bv_size", 4); } - ~imp() {} - void updt_params(params_ref const& p) {} void operator()(goal & g, model_converter_ref & mc) { diff --git a/src/tactic/bv/bv_bound_chk_tactic.cpp b/src/tactic/bv/bv_bound_chk_tactic.cpp index f6db3c30e..93491f7b2 100644 --- a/src/tactic/bv/bv_bound_chk_tactic.cpp +++ b/src/tactic/bv/bv_bound_chk_tactic.cpp @@ -41,8 +41,6 @@ struct bv_bound_chk_rewriter_cfg : public default_rewriter_cfg { bv_bound_chk_rewriter_cfg(ast_manager & m, bv_bound_chk_stats& stats) : m_m(m), m_b_rw(m), m_stats(stats) {} - ~bv_bound_chk_rewriter_cfg() {} - void updt_params(params_ref const & _p) { rewriter_params p(_p); m_bv_ineq_consistency_test_max = p.bv_ineq_consistency_test_max(); @@ -146,8 +144,6 @@ public: imp(ast_manager & m, params_ref const & p, bv_bound_chk_stats& stats) : m_rw(m, p, stats) { } - virtual ~imp() = default; - ast_manager& m() { return m_rw.m(); } void operator()(goal_ref const & g) { @@ -164,7 +160,7 @@ public: m_rw.m_cfg.cleanup(); } - virtual void updt_params(params_ref const & p) { + void updt_params(params_ref const & p) { m_rw.updt_params(p); } diff --git a/src/tactic/bv/bv_bounds_tactic.cpp b/src/tactic/bv/bv_bounds_tactic.cpp index 5f856800e..6ddc49c7f 100644 --- a/src/tactic/bv/bv_bounds_tactic.cpp +++ b/src/tactic/bv/bv_bounds_tactic.cpp @@ -48,8 +48,6 @@ namespace { r.insert("propagate-eq", CPK_BOOL, "propagate equalities from inequalities", "false"); } - ~bv_bounds_simplifier() override {} - bool assert_expr(expr * t, bool sign) override { return assert_expr_core(t, sign); } diff --git a/src/tactic/core/ctx_simplify_tactic.cpp b/src/tactic/core/ctx_simplify_tactic.cpp index aa4358e9c..e3cd7893a 100644 --- a/src/tactic/core/ctx_simplify_tactic.cpp +++ b/src/tactic/core/ctx_simplify_tactic.cpp @@ -144,9 +144,8 @@ struct ctx_simplify_tactic::imp { }; struct cache_cell { - expr * m_from; - cached_result * m_result; - cache_cell():m_from(nullptr), m_result(nullptr) {} + expr * m_from = nullptr; + cached_result * m_result = nullptr; }; ast_manager & m; diff --git a/src/tactic/core/symmetry_reduce_tactic.cpp b/src/tactic/core/symmetry_reduce_tactic.cpp index 9ad12d504..c5cba0b9a 100644 --- a/src/tactic/core/symmetry_reduce_tactic.cpp +++ b/src/tactic/core/symmetry_reduce_tactic.cpp @@ -117,8 +117,6 @@ public: m_replace = mk_default_expr_replacer(m, false); } - ~imp() {} - void operator()(goal & g) { if (g.inconsistent()) return; @@ -202,10 +200,10 @@ private: // a |-> c1, b |-> c2 |-> c // struct u_pair { - unsigned m_first; - unsigned m_second; + unsigned m_first = 0; + unsigned m_second = 0; u_pair(unsigned f, unsigned s) : m_first(f), m_second(s) {} - u_pair(): m_first(0), m_second(0) {} + u_pair() = default; struct hash { unsigned operator()(u_pair const& p) const { @@ -324,8 +322,6 @@ private: class parents { app_parents m_use_funs; public: - parents() {} - app_parents const& get_parents() { return m_use_funs; } void operator()(app* n) { diff --git a/src/tactic/probe.h b/src/tactic/probe.h index 4d1af66a8..452f2cb70 100644 --- a/src/tactic/probe.h +++ b/src/tactic/probe.h @@ -40,10 +40,9 @@ public: }; private: - unsigned m_ref_count; + unsigned m_ref_count = 0; public: - probe():m_ref_count(0) {} virtual ~probe() = default; void inc_ref() { ++m_ref_count; } diff --git a/src/tactic/tactic.cpp b/src/tactic/tactic.cpp index 179a42ab8..f7dcfb3ea 100644 --- a/src/tactic/tactic.cpp +++ b/src/tactic/tactic.cpp @@ -146,8 +146,6 @@ tactic * mk_trace_tactic(char const * tag) { class fail_if_undecided_tactic : public skip_tactic { public: - fail_if_undecided_tactic() {} - void operator()(goal_ref const & in, goal_ref_buffer& result) override { if (!in->is_decided()) throw tactic_exception("undecided"); diff --git a/src/tactic/tactic.h b/src/tactic/tactic.h index 652bf8130..e62f93ecf 100644 --- a/src/tactic/tactic.h +++ b/src/tactic/tactic.h @@ -32,10 +32,8 @@ class progress_callback; typedef ptr_buffer goal_buffer; class tactic : public user_propagator::core { - unsigned m_ref_count; + unsigned m_ref_count = 0; public: - tactic():m_ref_count(0) {} - void inc_ref() { m_ref_count++; } void dec_ref() { SASSERT(m_ref_count > 0); m_ref_count--; if (m_ref_count == 0) dealloc(this); } diff --git a/src/util/chashtable.h b/src/util/chashtable.h index 394e5998c..da7cb5b31 100644 --- a/src/util/chashtable.h +++ b/src/util/chashtable.h @@ -609,7 +609,7 @@ public: struct key_value { Key m_key; Value m_value; - key_value() {} + key_value() = default; key_value(Key const & k):m_key(k) {} key_value(Key const & k, Value const & v):m_key(k), m_value(v) {} }; diff --git a/src/util/optional.h b/src/util/optional.h index 8e515f4be..c2a0fd3ef 100644 --- a/src/util/optional.h +++ b/src/util/optional.h @@ -30,7 +30,7 @@ class optional { } public: - optional() {} + optional() = default; explicit optional(const T & val) { m_obj = alloc(T, val); @@ -116,13 +116,13 @@ public: */ template class optional { - T * m_ptr; + T * m_ptr = nullptr; static optional m_undef; public: - optional():m_ptr(nullptr) {} + optional() = default; explicit optional(T * val):m_ptr(val) {} diff --git a/src/util/params.cpp b/src/util/params.cpp index 700a53109..3440673b7 100644 --- a/src/util/params.cpp +++ b/src/util/params.cpp @@ -366,12 +366,11 @@ class params { }; typedef std::pair entry; svector m_entries; - std::atomic m_ref_count; + std::atomic m_ref_count = 0; void del_value(entry & e); void del_values(); public: - params():m_ref_count(0) {} ~params() { reset(); } diff --git a/src/util/queue.h b/src/util/queue.h index 059dea573..771ebbcd4 100644 --- a/src/util/queue.h +++ b/src/util/queue.h @@ -23,13 +23,10 @@ Notes: template class queue { vector m_elems; - unsigned m_head; - unsigned m_capacity; + unsigned m_head = 0; + unsigned m_capacity = 0; public: - - queue(): m_head(0), m_capacity(0) {} - void push(T const& t) { m_elems.push_back(t); } bool empty() const { diff --git a/src/util/rational.h b/src/util/rational.h index e9924bca7..61569f40c 100644 --- a/src/util/rational.h +++ b/src/util/rational.h @@ -41,8 +41,8 @@ public: ADD_INITIALIZER('rational::initialize();') ADD_FINALIZER('rational::finalize();') */ - rational() {} - + rational() = default; + rational(rational const & r) { m().set(m_val, r.m_val); } rational(rational&&) = default; diff --git a/src/util/s_integer.h b/src/util/s_integer.h index 6ddd2bf67..b102d6d4b 100644 --- a/src/util/s_integer.h +++ b/src/util/s_integer.h @@ -21,7 +21,7 @@ Revision History: #include "util/rational.h" class s_integer { - int m_val; + int m_val = 0; static s_integer m_zero; static s_integer m_one; static s_integer m_minus_one; @@ -41,7 +41,7 @@ public: std::string to_string() const; public: - s_integer(): m_val(0) {} + s_integer() = default; explicit s_integer(int n):m_val(n) {} struct i64 {}; explicit s_integer(int64_t i, i64):m_val(static_cast(i)) {} diff --git a/src/util/small_object_allocator.h b/src/util/small_object_allocator.h index 05fe32ef0..646a203c1 100644 --- a/src/util/small_object_allocator.h +++ b/src/util/small_object_allocator.h @@ -29,9 +29,8 @@ class small_object_allocator { static const unsigned NUM_SLOTS = (SMALL_OBJ_SIZE >> PTR_ALIGNMENT); struct chunk { chunk* m_next{ nullptr }; - char* m_curr{ nullptr }; + char* m_curr = m_data; char m_data[CHUNK_SIZE]; - chunk():m_curr(m_data) {} }; chunk * m_chunks[NUM_SLOTS]; void * m_free_list[NUM_SLOTS]; diff --git a/src/util/vector.h b/src/util/vector.h index 31ced7f4b..79e51d545 100644 --- a/src/util/vector.h +++ b/src/util/vector.h @@ -1170,7 +1170,7 @@ public: template class ptr_vector : public vector { public: - ptr_vector():vector() {} + ptr_vector() = default; ptr_vector(unsigned s):vector(s) {} ptr_vector(unsigned s, T * elem):vector(s, elem) {} ptr_vector(unsigned s, T * const * data):vector(s, const_cast(data)) {} @@ -1190,7 +1190,7 @@ public: template class svector : public vector { public: - svector():vector() {} + svector() = default; svector(SZ s):vector(s) {} svector(SZ s, T const & elem):vector(s, elem) {} svector(SZ s, T const * data):vector(s, data) {} From 1ace3d0cf3f1a0f1c1c4a39a581674ebe7fa5306 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 12 Sep 2024 10:37:19 -0700 Subject: [PATCH 097/187] fix #7372 Signed-off-by: Nikolaj Bjorner --- src/sat/sat_config.cpp | 1 + src/util/gparams.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sat/sat_config.cpp b/src/sat/sat_config.cpp index 73516f66d..ac9a68878 100644 --- a/src/sat/sat_config.cpp +++ b/src/sat/sat_config.cpp @@ -158,6 +158,7 @@ namespace sat { m_lookahead_delta_fraction = p.lookahead_delta_fraction(); m_lookahead_use_learned = p.lookahead_use_learned(); if (m_lookahead_delta_fraction < 0 || m_lookahead_delta_fraction > 1.0) { + verbose_stream() << m_lookahead_delta_fraction << "\n"; throw sat_param_exception("invalid value for delta fraction. It should be a number in the interval 0 to 1"); } diff --git a/src/util/gparams.cpp b/src/util/gparams.cpp index 839d02ab0..171cae604 100644 --- a/src/util/gparams.cpp +++ b/src/util/gparams.cpp @@ -22,6 +22,7 @@ Notes: #include "util/mutex.h" #include "util/region.h" #include "util/map.h" +#include "util/rational.h" static DECLARE_MUTEX(gparams_mux); @@ -351,8 +352,8 @@ public: ps.set_uint(param_name, static_cast(val)); } else if (k == CPK_DOUBLE) { - char * aux; - double val = strtod(value, &aux); + rational r(value); + double val = r.get_double(); ps.set_double(param_name, val); } else if (k == CPK_BOOL) { From 99a9a4af03ed34fd4bd13b9881ca5910646d4c54 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 12 Sep 2024 10:37:50 -0700 Subject: [PATCH 098/187] fix #7372 Signed-off-by: Nikolaj Bjorner --- src/sat/sat_config.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sat/sat_config.cpp b/src/sat/sat_config.cpp index ac9a68878..73516f66d 100644 --- a/src/sat/sat_config.cpp +++ b/src/sat/sat_config.cpp @@ -158,7 +158,6 @@ namespace sat { m_lookahead_delta_fraction = p.lookahead_delta_fraction(); m_lookahead_use_learned = p.lookahead_use_learned(); if (m_lookahead_delta_fraction < 0 || m_lookahead_delta_fraction > 1.0) { - verbose_stream() << m_lookahead_delta_fraction << "\n"; throw sat_param_exception("invalid value for delta fraction. It should be a number in the interval 0 to 1"); } From 0ba306e7b320901540162bfd7cf70c7b7399be17 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 17 Sep 2024 12:27:13 +0300 Subject: [PATCH 099/187] y --- src/api/python/z3/z3.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/api/python/z3/z3.py b/src/api/python/z3/z3.py index bd38d5baa..25dc341b8 100644 --- a/src/api/python/z3/z3.py +++ b/src/api/python/z3/z3.py @@ -7926,9 +7926,12 @@ _on_model_eh = on_model_eh_type(_global_on_model) class Optimize(Z3PPObject): """Optimize API provides methods for solving using objective functions and weighted soft constraints""" - def __init__(self, ctx=None): + def __init__(self, optimize=None, ctx=None): self.ctx = _get_ctx(ctx) - self.optimize = Z3_mk_optimize(self.ctx.ref()) + if optimize is None: + self.optimize = Z3_mk_optimize(self.ctx.ref()) + else: + self.optimize = optimize self._on_models_id = None Z3_optimize_inc_ref(self.ctx.ref(), self.optimize) From 48712b4f60e090b3e95bb71063cbfe37c1c1d353 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 18 Sep 2024 16:13:15 +0300 Subject: [PATCH 100/187] Add initial value setting for variables in Z3 API, solver, and optimize modules --- src/api/api_opt.cpp | 17 ++++++++++- src/api/api_solver.cpp | 18 ++++++++++++ src/api/c++/z3++.h | 22 ++++++++++++++ src/api/python/z3/z3.py | 14 +++++++++ src/api/z3_api.h | 12 ++++++++ src/api/z3_optimization.h | 12 ++++++++ src/math/lp/lar_solver.cpp | 18 ++++++++++++ src/math/lp/lar_solver.h | 1 + src/opt/opt_context.cpp | 19 ++++++++----- src/opt/opt_context.h | 4 +++ src/opt/opt_solver.h | 1 + src/sat/sat_solver/inc_sat_solver.cpp | 4 +++ src/sat/sat_solver/sat_smt_solver.cpp | 5 ++++ src/sat/smt/euf_solver.cpp | 25 ++++++++++++++++ src/sat/smt/euf_solver.h | 2 ++ src/smt/smt_context.cpp | 41 +++++++++++++++++++++++++++ src/smt/smt_context.h | 13 +++++++++ src/smt/smt_kernel.cpp | 4 +++ src/smt/smt_kernel.h | 2 ++ src/smt/smt_solver.cpp | 4 +++ src/smt/smt_theory.h | 4 +++ src/smt/tactic/smt_tactic_core.cpp | 7 +++++ src/smt/theory_arith.h | 1 + src/smt/theory_arith_aux.h | 15 ++++++++++ src/smt/theory_lra.cpp | 19 ++++++++++++- src/smt/theory_lra.h | 2 ++ src/solver/combined_solver.cpp | 5 ++++ src/solver/simplifier_solver.cpp | 2 ++ src/solver/tactic2solver.cpp | 4 +++ src/tactic/tactical.cpp | 5 ++++ src/tactic/user_propagator_base.h | 4 +++ 31 files changed, 297 insertions(+), 9 deletions(-) diff --git a/src/api/api_opt.cpp b/src/api/api_opt.cpp index 5854bdaca..a9a0b3230 100644 --- a/src/api/api_opt.cpp +++ b/src/api/api_opt.cpp @@ -459,6 +459,21 @@ extern "C" { Z3_CATCH; } - + void Z3_API Z3_optimize_set_initial_value(Z3_context c, Z3_optimize o, Z3_ast var, Z3_ast value) { + Z3_TRY; + LOG_Z3_optimize_set_initial_value(c, o, var, value); + RESET_ERROR_CODE(); + if (to_expr(var)->get_sort() != to_expr(value)->get_sort()) { + SET_ERROR_CODE(Z3_INVALID_USAGE, "variable and value should have same sort"); + return; + } + ast_manager& m = mk_c(c)->m(); + if (!m.is_value(to_expr(value))) { + SET_ERROR_CODE(Z3_INVALID_USAGE, "a proper value was not supplied"); + return; + } + to_optimize_ptr(o)->initialize_value(to_expr(var), to_expr(value)); + Z3_CATCH; + } }; diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index f18edd96b..f226529de 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -1143,5 +1143,23 @@ extern "C" { Z3_CATCH_RETURN(nullptr); } + void Z3_API Z3_solver_set_initial_value(Z3_context c, Z3_solver s, Z3_ast var, Z3_ast value) { + Z3_TRY; + LOG_Z3_solver_set_initial_value(c, s, var, value); + RESET_ERROR_CODE(); + if (to_expr(var)->get_sort() != to_expr(value)->get_sort()) { + SET_ERROR_CODE(Z3_INVALID_USAGE, "variable and value should have same sort"); + return; + } + ast_manager& m = mk_c(c)->m(); + if (!m.is_value(to_expr(value))) { + SET_ERROR_CODE(Z3_INVALID_USAGE, "a proper value was not supplied"); + return; + } + to_solver_ref(s)->user_propagate_initialize_value(to_expr(var), to_expr(value)); + Z3_CATCH; + } + + }; diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index 81d5bcaa9..bb148d712 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -2865,6 +2865,17 @@ namespace z3 { check_error(); return result; } + void set_initial_value(expr const& var, expr const& value) { + Z3_solver_set_initial_value(ctx(), m_solver, var, value); + check_error(); + } + void set_initial_value(expr const& var, int i) { + set_initial_value(var, ctx().num_val(i, var.get_sort())); + } + void set_initial_value(expr const& var, bool b) { + set_initial_value(var, ctx().bool_val(b)); + } + expr proof() const { Z3_ast r = Z3_solver_get_proof(ctx(), m_solver); check_error(); return expr(ctx(), r); } friend std::ostream & operator<<(std::ostream & out, solver const & s); @@ -3330,6 +3341,17 @@ namespace z3 { handle add(expr const& e, unsigned weight) { return add_soft(e, weight); } + void set_initial_value(expr const& var, expr const& value) { + Z3_optimize_set_initial_value(ctx(), m_opt, var, value); + check_error(); + } + void set_initial_value(expr const& var, int i) { + set_initial_value(var, ctx().num_val(i, var.get_sort())); + } + void set_initial_value(expr const& var, bool b) { + set_initial_value(var, ctx().bool_val(b)); + } + handle maximize(expr const& e) { return handle(Z3_optimize_maximize(ctx(), m_opt, e)); } diff --git a/src/api/python/z3/z3.py b/src/api/python/z3/z3.py index 25dc341b8..5c2a35995 100644 --- a/src/api/python/z3/z3.py +++ b/src/api/python/z3/z3.py @@ -7353,6 +7353,13 @@ class Solver(Z3PPObject): Z3_solver_get_levels(self.ctx.ref(), self.solver, trail.vector, len(trail), levels) return trail, levels + def set_initial_value(self, var, value): + """initialize the solver's state by setting the initial value of var to value + """ + s = var.sort() + value = s.cast(value) + Z3_solver_set_initial_value(self.ctx.ref(), self.solver, var.ast, value.ast) + def trail(self): """Return trail of the solver state after a check() call. """ @@ -8032,6 +8039,13 @@ class Optimize(Z3PPObject): return [asoft(a) for a in arg] return asoft(arg) + def set_initial_value(self, var, value): + """initialize the solver's state by setting the initial value of var to value + """ + s = var.sort() + value = s.cast(value) + Z3_optimize_set_initial_value(self.ctx.ref(), self.optimize, var.ast, value.ast) + def maximize(self, arg): """Add objective function to maximize.""" return OptimizeObjective( diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 1f0daf8b5..fdc25ef46 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -7241,6 +7241,18 @@ extern "C" { bool Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback cb, unsigned num_fixed, Z3_ast const* fixed, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq); + + /** + \brief provide an initialization hint to the solver. The initialization hint is used to calibrate an initial value of the expression that + represents a variable. If the variable is Boolean, the initial phase is set according to \c value. If the variable is an integer or real, + the initial Simplex tableau is recalibrated to attempt to follow the value assignment. + + def_API('Z3_solver_set_initial_value', VOID, (_in(CONTEXT), _in(SOLVER), _in(AST), _in(AST))) + */ + + void Z3_API Z3_solver_set_initial_value(Z3_context c, Z3_solver s, Z3_ast var, Z3_ast value); + + /** \brief Check whether the assertions in a given solver are consistent or not. diff --git a/src/api/z3_optimization.h b/src/api/z3_optimization.h index 8bf0e9da5..ad55cab1d 100644 --- a/src/api/z3_optimization.h +++ b/src/api/z3_optimization.h @@ -139,6 +139,18 @@ extern "C" { */ void Z3_API Z3_optimize_pop(Z3_context c, Z3_optimize d); + /** + \brief provide an initialization hint to the solver. + The initialization hint is used to calibrate an initial value of the expression that + represents a variable. If the variable is Boolean, the initial phase is set + according to \c value. If the variable is an integer or real, + the initial Simplex tableau is recalibrated to attempt to follow the value assignment. + + def_API('Z3_optimize_set_initial_value', VOID, (_in(CONTEXT), _in(OPTIMIZE), _in(AST), _in(AST))) + */ + + void Z3_API Z3_optimize_set_initial_value(Z3_context c, Z3_optimize o, Z3_ast var, Z3_ast value); + /** \brief Check consistency and produce optimal values. \param c - context diff --git a/src/math/lp/lar_solver.cpp b/src/math/lp/lar_solver.cpp index 9272e0298..b0f153e46 100644 --- a/src/math/lp/lar_solver.cpp +++ b/src/math/lp/lar_solver.cpp @@ -2081,6 +2081,24 @@ namespace lp { lpvar lar_solver::to_column(unsigned ext_j) const { return m_var_register.external_to_local(ext_j); } + + bool lar_solver::move_lpvar_to_value(lpvar j, mpq const& value) { + if (is_base(j)) + return false; + + impq ivalue(value); + auto& lcs = m_mpq_lar_core_solver; + auto& slv = m_mpq_lar_core_solver.m_r_solver; + + if (slv.column_has_upper_bound(j) && lcs.m_r_upper_bounds()[j] < ivalue) + return false; + if (slv.column_has_lower_bound(j) && lcs.m_r_lower_bounds()[j] > ivalue) + return false; + + set_value_for_nbasic_column(j, ivalue); + return true; + } + bool lar_solver::tighten_term_bounds_by_delta(lpvar j, const impq& delta) { SASSERT(column_has_term(j)); diff --git a/src/math/lp/lar_solver.h b/src/math/lp/lar_solver.h index f223b5cc5..c58fe7917 100644 --- a/src/math/lp/lar_solver.h +++ b/src/math/lp/lar_solver.h @@ -623,6 +623,7 @@ public: lp_status find_feasible_solution(); void move_non_basic_columns_to_bounds(); bool move_non_basic_column_to_bounds(unsigned j); + bool move_lpvar_to_value(lpvar j, mpq const& value); inline bool r_basis_has_inf_int() const { for (unsigned j : r_basis()) { if (column_is_int(j) && !column_value_is_int(j)) diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp index 1b57a7200..90bc0ddd6 100644 --- a/src/opt/opt_context.cpp +++ b/src/opt/opt_context.cpp @@ -58,8 +58,9 @@ namespace opt { } void context::scoped_state::pop() { - m_hard.resize(m_hard_lim.back()); - m_asms.resize(m_asms_lim.back()); + m_hard.shrink(m_hard_lim.back()); + m_asms.shrink(m_asms_lim.back()); + m_values.shrink(m_values_lim.back()); unsigned k = m_objectives_term_trail_lim.back(); while (m_objectives_term_trail.size() > k) { unsigned idx = m_objectives_term_trail.back(); @@ -79,6 +80,7 @@ namespace opt { m_objectives_lim.pop_back(); m_hard_lim.pop_back(); m_asms_lim.pop_back(); + m_values_lim.pop_back(); } void context::scoped_state::add(expr* hard) { @@ -306,13 +308,11 @@ namespace opt { if (contains_quantifiers()) { warning_msg("optimization with quantified constraints is not supported"); } -#if 0 - if (is_qsat_opt()) { - return run_qsat_opt(); - } -#endif solver& s = get_solver(); s.assert_expr(m_hard_constraints); + for (auto const& [var, value] : m_scoped_state.m_values) { + s.user_propagate_initialize_value(var, value); + } opt_params optp(m_params); symbol pri = optp.priority(); @@ -697,6 +697,11 @@ namespace opt { } } + void context::initialize_value(expr* var, expr* value) { + m_scoped_state.m_values.push_back({expr_ref(var, m), expr_ref(value, m)}); + } + + /** * Set the solver to the SAT core. * It requres: diff --git a/src/opt/opt_context.h b/src/opt/opt_context.h index 4e791531e..845fd3968 100644 --- a/src/opt/opt_context.h +++ b/src/opt/opt_context.h @@ -140,12 +140,14 @@ namespace opt { unsigned_vector m_objectives_lim; unsigned_vector m_objectives_term_trail; unsigned_vector m_objectives_term_trail_lim; + unsigned_vector m_values_lim; map_id m_indices; public: expr_ref_vector m_hard; expr_ref_vector m_asms; vector m_objectives; + vector> m_values; scoped_state(ast_manager& m): m(m), @@ -275,6 +277,8 @@ namespace opt { void add_offset(unsigned id, rational const& o) override; + void initialize_value(expr* var, expr* value); + void register_on_model(on_model_t& ctx, std::function& on_model) { m_on_model_ctx = ctx; m_on_model_eh = on_model; diff --git a/src/opt/opt_solver.h b/src/opt/opt_solver.h index 2682fca09..66835df48 100644 --- a/src/opt/opt_solver.h +++ b/src/opt/opt_solver.h @@ -116,6 +116,7 @@ namespace opt { phase* get_phase() override { return m_context.get_phase(); } void set_phase(phase* p) override { m_context.set_phase(p); } void move_to_front(expr* e) override { m_context.move_to_front(e); } + void user_propagate_initialize_value(expr* var, expr* value) override { m_context.user_propagate_initialize_value(var, value); } void set_logic(symbol const& logic); diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index 4574d3da3..0129a026e 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -702,6 +702,10 @@ public: ensure_euf()->user_propagate_register_decide(r); } + void user_propagate_initialize_value(expr* var, expr* value) override { + ensure_euf()->user_propagate_initialize_value(var, value); + } + private: diff --git a/src/sat/sat_solver/sat_smt_solver.cpp b/src/sat/sat_solver/sat_smt_solver.cpp index 19b10eb3e..1c141a801 100644 --- a/src/sat/sat_solver/sat_smt_solver.cpp +++ b/src/sat/sat_solver/sat_smt_solver.cpp @@ -577,6 +577,11 @@ public: ensure_euf()->user_propagate_register_decide(r); } + void user_propagate_initialize_value(expr* var, expr* value) override { + ensure_euf()->user_propagate_initialize_value(var, value); + } + + private: void add_assumption(expr* a) { diff --git a/src/sat/smt/euf_solver.cpp b/src/sat/smt/euf_solver.cpp index b866990af..0a58d7d1d 100644 --- a/src/sat/smt/euf_solver.cpp +++ b/src/sat/smt/euf_solver.cpp @@ -1256,6 +1256,31 @@ namespace euf { add_solver(m_user_propagator); } + void solver::user_propagate_initialize_value(expr* var, expr* value) { + if (m.is_bool(var)) { + auto lit = expr2literal(var); + if (lit == sat::null_literal) { + IF_VERBOSE(5, verbose_stream() << "no literal associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + return; + } + if (m.is_true(value)) + s().set_phase(lit); + else if (m.is_false(value)) + s().set_phase(~lit); + else + IF_VERBOSE(5, verbose_stream() << "malformed value " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + return; + } + auto* th = m_id2solver.get(var->get_sort()->get_family_id(), nullptr); + if (!th) { + IF_VERBOSE(5, verbose_stream() << "no default initialization associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + return; + } + // th->initialize_value(var, value); + IF_VERBOSE(5, verbose_stream() << "no default initialization associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + } + + bool solver::watches_fixed(enode* n) const { return m_user_propagator && m_user_propagator->has_fixed() && n->get_th_var(m_user_propagator->get_id()) != null_theory_var; } diff --git a/src/sat/smt/euf_solver.h b/src/sat/smt/euf_solver.h index 1b13d5137..8c436b942 100644 --- a/src/sat/smt/euf_solver.h +++ b/src/sat/smt/euf_solver.h @@ -564,6 +564,8 @@ namespace euf { m_user_propagator->add_expr(e); } + void user_propagate_initialize_value(expr* var, expr* value); + // solver factory ::solver* mk_solver() { return m_mk_solver(); } void set_mk_solver(std::function<::solver*(void)>& mk) { m_mk_solver = mk; } diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index c11084e56..163da9b16 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -2914,6 +2914,44 @@ namespace smt { register_plugin(m_user_propagator); } + void context::user_propagate_initialize_value(expr* var, expr* value) { + m_values.push_back({expr_ref(var, m), expr_ref(value, m)}); + push_trail(push_back_vector(m_values)); + } + + void context::initialize_value(expr* var, expr* value) { + IF_VERBOSE(10, verbose_stream() << "context initialize " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + sort* s = var->get_sort(); + ensure_internalized(var); + + if (m.is_bool(s)) { + auto v = get_bool_var_of_id_option(var->get_id()); + if (v == null_bool_var) { + IF_VERBOSE(5, verbose_stream() << "Boolean variable has no literal " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + return; + } + m_bdata[v].m_phase_available = true; + if (m.is_true(value)) + m_bdata[v].m_phase = true; + else if (m.is_false(value)) + m_bdata[v].m_phase = false; + else + IF_VERBOSE(5, verbose_stream() << "Boolean value is not constant " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + return; + } + + if (!e_internalized(var)) + return; + enode* n = get_enode(var); + theory* th = m_theories.get_plugin(s->get_family_id()); + if (!th) { + IF_VERBOSE(5, verbose_stream() << "No theory is attached to variable " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + return; + } + th->initialize_value(var, value); + + } + bool context::watches_fixed(enode* n) const { return m_user_propagator && m_user_propagator->has_fixed() && n->get_th_var(m_user_propagator->get_family_id()) != null_theory_var; } @@ -3756,6 +3794,9 @@ namespace smt { TRACE("search", display(tout); display_enodes_lbls(tout);); TRACE("search_detail", m_asserted_formulas.display(tout);); init_search(); + for (auto const& [var, value] : m_values) + initialize_value(var, value); + flet l(m_searching, true); TRACE("after_init_search", display(tout);); IF_VERBOSE(2, verbose_stream() << "(smt.searching)\n";); diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index da7cde7e7..afbfd0e85 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -123,6 +123,7 @@ namespace smt { unsigned m_par_index = 0; bool m_internalizing_assertions = false; + // ----------------------------------- // // Equality & Uninterpreted functions @@ -246,6 +247,16 @@ namespace smt { vector m_th_case_split_sets; u_map< vector > m_literal2casesplitsets; // returns the case split literal sets that a literal participates in + + // ---------------------------------- + // + // Value initialization + // + // ---------------------------------- + vector> m_values; + void initialize_value(expr* var, expr* value); + + // ----------------------------------- // // Accessors @@ -1777,6 +1788,8 @@ namespace smt { m_user_propagator->register_decide(r); } + void user_propagate_initialize_value(expr* var, expr* value); + bool watches_fixed(enode* n) const; bool has_split_candidate(bool_var& var, bool& is_pos); diff --git a/src/smt/smt_kernel.cpp b/src/smt/smt_kernel.cpp index 74f0bded6..2d6c29532 100644 --- a/src/smt/smt_kernel.cpp +++ b/src/smt/smt_kernel.cpp @@ -305,5 +305,9 @@ namespace smt { void kernel::user_propagate_register_decide(user_propagator::decide_eh_t& r) { m_imp->m_kernel.user_propagate_register_decide(r); } + + void kernel::user_propagate_initialize_value(expr* var, expr* value) { + m_imp->m_kernel.user_propagate_initialize_value(var, value); + } }; diff --git a/src/smt/smt_kernel.h b/src/smt/smt_kernel.h index eec74f8b1..539a32750 100644 --- a/src/smt/smt_kernel.h +++ b/src/smt/smt_kernel.h @@ -322,6 +322,8 @@ namespace smt { void user_propagate_register_decide(user_propagator::decide_eh_t& r); + void user_propagate_initialize_value(expr* var, expr* value); + /** \brief Return a reference to smt::context. This breaks abstractions. diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp index f91a31111..7b9d416f3 100644 --- a/src/smt/smt_solver.cpp +++ b/src/smt/smt_solver.cpp @@ -252,6 +252,10 @@ namespace { m_context.user_propagate_register_decide(c); } + void user_propagate_initialize_value(expr* var, expr* value) override { + m_context.user_propagate_initialize_value(var, value); + } + struct scoped_minimize_core { smt_solver& s; expr_ref_vector m_assumptions; diff --git a/src/smt/smt_theory.h b/src/smt/smt_theory.h index d0e73cc92..416d626f7 100644 --- a/src/smt/smt_theory.h +++ b/src/smt/smt_theory.h @@ -549,6 +549,10 @@ namespace smt { return get_manager().mk_eq(lhs, rhs); } + virtual void initialize_value(expr* var, expr* value) { + IF_VERBOSE(5, verbose_stream() << "no default initialization associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + } + literal mk_eq(expr * a, expr * b, bool gate_ctx); literal mk_preferred_eq(expr* a, expr* b); diff --git a/src/smt/tactic/smt_tactic_core.cpp b/src/smt/tactic/smt_tactic_core.cpp index 2be2ace58..89b2b7135 100644 --- a/src/smt/tactic/smt_tactic_core.cpp +++ b/src/smt/tactic/smt_tactic_core.cpp @@ -41,6 +41,7 @@ class smt_tactic : public tactic { smt_params m_params; params_ref m_params_ref; expr_ref_vector m_vars; + vector> m_values; statistics m_stats; smt::kernel* m_ctx = nullptr; symbol m_logic; @@ -344,6 +345,8 @@ public: for (expr* v : m_vars) m_ctx->user_propagate_register_expr(v); + for (auto& [var, value] : m_values) + m_ctx->user_propagate_initialize_value(var, value); } void user_propagate_clear() override { @@ -403,6 +406,10 @@ public: void user_propagate_register_decide(user_propagator::decide_eh_t& decide_eh) override { m_decide_eh = decide_eh; } + + void user_propagate_initialize_value(expr* var, expr* value) override { + m_values.push_back({expr_ref(var, m), expr_ref(value, m)}); + } }; static tactic * mk_seq_smt_tactic(ast_manager& m, params_ref const & p) { diff --git a/src/smt/theory_arith.h b/src/smt/theory_arith.h index 86c05aec6..e68f0f53f 100644 --- a/src/smt/theory_arith.h +++ b/src/smt/theory_arith.h @@ -662,6 +662,7 @@ namespace smt { void restart_eh() override; void init_search_eh() override; + void initialize_value(expr* var, expr* value) override; /** \brief True if the assignment may be changed during final check. assume_eqs, check_int_feasibility, diff --git a/src/smt/theory_arith_aux.h b/src/smt/theory_arith_aux.h index 8141377c4..acb036d2a 100644 --- a/src/smt/theory_arith_aux.h +++ b/src/smt/theory_arith_aux.h @@ -2249,6 +2249,21 @@ namespace smt { return false; } + template + void theory_arith::initialize_value(expr* var, expr* value) { + theory_var v = expr2var(var); + rational r; + if (!m_util.is_numeral(value, r)) { + IF_VERBOSE(5, verbose_stream() << "numeric constant expected in initialization " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + return; + } + if (v == null_theory_var) + return; + if (is_base(v)) + return; + update_value(v, inf_numeral(r)); + } + #if 0 /** diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index f0a96ddd1..8f334276d 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -154,6 +154,7 @@ class theory_lra::imp { svector m_asserted_atoms; ptr_vector m_not_handled; ptr_vector m_underspecified; + vector> m_values; vector > m_use_list; // bounds where variables are used. // attributes for incremental version: @@ -991,6 +992,16 @@ public: return lp().compare_values(vi, k, b->get_value()) ? l_true : l_false; } + void initialize_value(expr* var, expr* value) { + rational r; + if (!a.is_numeral(value, r)) { + IF_VERBOSE(5, verbose_stream() << "numeric constant expected in initialization " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + return; + } + ctx().push_trail(push_back_vector(m_values)); + m_values.push_back({get_lpvar(var), r}); + } + void new_eq_eh(theory_var v1, theory_var v2) { TRACE("arith", tout << "eq " << v1 << " == " << v2 << "\n";); if (!is_int(v1) && !is_real(v1)) @@ -1409,6 +1420,9 @@ public: void init_search_eh() { m_arith_eq_adapter.init_search_eh(); m_num_conflicts = 0; + for (auto const& [v, r] : m_values) + lp().move_lpvar_to_value(v, r); + display(verbose_stream() << "init search\n"); } bool can_get_value(theory_var v) const { @@ -3878,6 +3892,9 @@ void theory_lra::assign_eh(bool_var v, bool is_true) { lbool theory_lra::get_phase(bool_var v) { return m_imp->get_phase(v); } +void theory_lra::initialize_value(expr* var, expr* value) { + m_imp->initialize_value(var, value); +} void theory_lra::new_eq_eh(theory_var v1, theory_var v2) { m_imp->new_eq_eh(v1, v2); } @@ -3912,7 +3929,7 @@ final_check_status theory_lra::final_check_eh() { } bool theory_lra::is_shared(theory_var v) const { return m_imp->is_shared(v); -} +} bool theory_lra::can_propagate() { return m_imp->can_propagate(); } diff --git a/src/smt/theory_lra.h b/src/smt/theory_lra.h index 4c2351c85..96988f957 100644 --- a/src/smt/theory_lra.h +++ b/src/smt/theory_lra.h @@ -80,6 +80,8 @@ namespace smt { void apply_sort_cnstr(enode * n, sort * s) override; void init_model(model_generator & m) override; + + void initialize_value(expr* var, expr* value) override; model_value_proc * mk_value(enode * n, model_generator & mg) override; void validate_model(proto_model& mdl) override; diff --git a/src/solver/combined_solver.cpp b/src/solver/combined_solver.cpp index 53aa56753..051dfd4eb 100644 --- a/src/solver/combined_solver.cpp +++ b/src/solver/combined_solver.cpp @@ -394,6 +394,11 @@ public: void user_propagate_clear() override { m_solver2->user_propagate_clear(); } + + void user_propagate_initialize_value(expr* var, expr* value) override { + m_solver2->user_propagate_initialize_value(var, value); + } + }; diff --git a/src/solver/simplifier_solver.cpp b/src/solver/simplifier_solver.cpp index 8995049f0..ae1d6b8a2 100644 --- a/src/solver/simplifier_solver.cpp +++ b/src/solver/simplifier_solver.cpp @@ -390,6 +390,8 @@ public: void user_propagate_register_expr(expr* e) override { m_preprocess_state.freeze(e); s->user_propagate_register_expr(e); } void user_propagate_register_created(user_propagator::created_eh_t& r) override { s->user_propagate_register_created(r); } void user_propagate_register_decide(user_propagator::decide_eh_t& r) override { s->user_propagate_register_decide(r); } + void user_propagate_initialize_value(expr* var, expr* value) override { m_preprocess_state.freeze(var); s->user_propagate_initialize_value(var, value); } + }; diff --git a/src/solver/tactic2solver.cpp b/src/solver/tactic2solver.cpp index 861a83185..cdabecb27 100644 --- a/src/solver/tactic2solver.cpp +++ b/src/solver/tactic2solver.cpp @@ -119,6 +119,10 @@ public: void user_propagate_register_expr(expr* e) override { m_tactic->user_propagate_register_expr(e); } + + void user_propagate_initialize_value(expr* var, expr* value) override { + m_tactic->user_propagate_initialize_value(var, value); + } void user_propagate_register_created(user_propagator::created_eh_t& created_eh) override { m_tactic->user_propagate_register_created(created_eh); diff --git a/src/tactic/tactical.cpp b/src/tactic/tactical.cpp index 0b8189e8d..626380913 100644 --- a/src/tactic/tactical.cpp +++ b/src/tactic/tactical.cpp @@ -213,6 +213,10 @@ public: m_t2->user_propagate_register_decide(decide_eh); } + void user_propagate_initialize_value(expr* var, expr* value) override { + m_t2->user_propagate_initialize_value(var, value); + } + }; tactic * and_then(tactic * t1, tactic * t2) { @@ -884,6 +888,7 @@ public: void set_progress_callback(progress_callback * callback) override { m_t->set_progress_callback(callback); } void user_propagate_register_expr(expr* e) override { m_t->user_propagate_register_expr(e); } void user_propagate_clear() override { m_t->user_propagate_clear(); } + void user_propagate_initialize_value(expr* var, expr* value) override { m_t->user_propagate_initialize_value(var, value); } protected: diff --git a/src/tactic/user_propagator_base.h b/src/tactic/user_propagator_base.h index 58904a12d..968196f63 100644 --- a/src/tactic/user_propagator_base.h +++ b/src/tactic/user_propagator_base.h @@ -99,6 +99,10 @@ namespace user_propagator { throw default_exception("clause logging is only supported on the SMT solver"); } + virtual void user_propagate_initialize_value(expr* var, expr* value) { + throw default_exception("value initialization is only supported on the SMT solver"); + } + }; From 0f896503a9ffe875936ec4f80094ea0e587e833a Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 18 Sep 2024 16:18:47 +0300 Subject: [PATCH 101/187] Add initial value setting API for solver and optimize contexts and update related function signatures --- RELEASE_NOTES.md | 5 ++++- src/api/z3_api.h | 2 +- src/api/z3_optimization.h | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b69772dcd..cc961a760 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -15,7 +15,10 @@ Version 4.13.1 - single-sample cell projection in nlsat was designed by Haokun Li and Bican Xia. - using simple-checker together with and variable ordering supported by qfnra_tactic was developed by Mengyu Zhao (Linxi) and Shaowei Cai. - The projection is described in paper by Haokun Li and Bican Xia, [Solving Satisfiability of Polynomial Formulas By Sample - Cell Projection](https://arxiv.org/abs/2003.00409). The code ported from https://github.com/hybridSMT/hybridSMT.git + The projection is described in paper by Haokun Li and Bican Xia, [Solving Satisfiability of Polynomial Formulas By Sample - Cell Projection](https://arxiv.org/abs/2003.00409). The code ported from https://github.com/hybridSMT/hybridSMT.git + +- Add API for providing hints for the solver/optimize contexts for which initial values to attempt to use for variables. + The new API function are Z3_solver_set_initial_value and Z3_optimize_set_initial_value, respectively. Supply these functions with a Boolean or numeric variable, and a value. The solver will then attempt to use these values in the initial phase of search. The feature is aimed at resolving nearly similar problems, or problems with a predicted model and the intent is that restarting the solver based on a near solution can avoid prune the space of constraints that are initially infeasible. Version 4.13.0 ============== diff --git a/src/api/z3_api.h b/src/api/z3_api.h index fdc25ef46..6c3efe7fc 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -7250,7 +7250,7 @@ extern "C" { def_API('Z3_solver_set_initial_value', VOID, (_in(CONTEXT), _in(SOLVER), _in(AST), _in(AST))) */ - void Z3_API Z3_solver_set_initial_value(Z3_context c, Z3_solver s, Z3_ast var, Z3_ast value); + void Z3_API Z3_solver_set_initial_value(Z3_context c, Z3_solver s, Z3_ast v, Z3_ast val); /** diff --git a/src/api/z3_optimization.h b/src/api/z3_optimization.h index ad55cab1d..4e585efb2 100644 --- a/src/api/z3_optimization.h +++ b/src/api/z3_optimization.h @@ -149,7 +149,7 @@ extern "C" { def_API('Z3_optimize_set_initial_value', VOID, (_in(CONTEXT), _in(OPTIMIZE), _in(AST), _in(AST))) */ - void Z3_API Z3_optimize_set_initial_value(Z3_context c, Z3_optimize o, Z3_ast var, Z3_ast value); + void Z3_API Z3_optimize_set_initial_value(Z3_context c, Z3_optimize o, Z3_ast v, Z3_ast val); /** \brief Check consistency and produce optimal values. From 1c163dbad2d2d9716a6a9eb7654a6a4387104ee3 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 18 Sep 2024 16:41:00 +0300 Subject: [PATCH 102/187] remove output Signed-off-by: Nikolaj Bjorner --- src/sat/smt/arith_internalize.cpp | 10 +++++++ src/sat/smt/arith_solver.h | 3 ++ src/sat/smt/euf_solver.cpp | 49 ++++++++++++++++++------------- src/sat/smt/euf_solver.h | 2 ++ src/sat/smt/sat_th.h | 2 ++ src/smt/theory_lra.cpp | 1 - 6 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/sat/smt/arith_internalize.cpp b/src/sat/smt/arith_internalize.cpp index a389d13b8..9c4e5c9be 100644 --- a/src/sat/smt/arith_internalize.cpp +++ b/src/sat/smt/arith_internalize.cpp @@ -51,6 +51,16 @@ namespace arith { } } + void solver::initialize_value(expr* var, expr* value) { + rational r; + if (!a.is_numeral(value, r)) { + IF_VERBOSE(5, verbose_stream() << "numeric constant expected in initialization " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + return; + } + lp().move_lpvar_to_value(get_lpvar(mk_evar(var)), r); + } + + lpvar solver::get_one(bool is_int) { return add_const(1, is_int ? m_one_var : m_rone_var, is_int); } diff --git a/src/sat/smt/arith_solver.h b/src/sat/smt/arith_solver.h index 755611474..f940af8b4 100644 --- a/src/sat/smt/arith_solver.h +++ b/src/sat/smt/arith_solver.h @@ -485,6 +485,8 @@ namespace arith { bool validate_conflict(); + + public: solver(euf::solver& ctx, theory_id id); ~solver() override; @@ -512,6 +514,7 @@ namespace arith { void internalize(expr* e) override; void eq_internalized(euf::enode* n) override; void apply_sort_cnstr(euf::enode* n, sort* s) override {} + void initialize_value(expr* var, expr* value) override; bool is_shared(theory_var v) const override; lbool get_phase(bool_var v) override; bool include_func_interp(func_decl* f) const override; diff --git a/src/sat/smt/euf_solver.cpp b/src/sat/smt/euf_solver.cpp index 0a58d7d1d..b443d836e 100644 --- a/src/sat/smt/euf_solver.cpp +++ b/src/sat/smt/euf_solver.cpp @@ -195,6 +195,30 @@ namespace euf { m_reason_unknown.clear(); for (auto* s : m_solvers) s->init_search(); + + for (auto const& [var, value] : m_initial_values) { + if (m.is_bool(var)) { + auto lit = expr2literal(var); + if (lit == sat::null_literal) { + IF_VERBOSE(5, verbose_stream() << "no literal associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + continue; + } + if (m.is_true(value)) + s().set_phase(lit); + else if (m.is_false(value)) + s().set_phase(~lit); + else + IF_VERBOSE(5, verbose_stream() << "malformed value " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + continue; + } + auto* th = m_id2solver.get(var->get_sort()->get_family_id(), nullptr); + if (!th) { + IF_VERBOSE(5, verbose_stream() << "no default initialization associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + continue; + } + th->initialize_value(var, value); + } + } bool solver::is_external(bool_var v) { @@ -1257,27 +1281,10 @@ namespace euf { } void solver::user_propagate_initialize_value(expr* var, expr* value) { - if (m.is_bool(var)) { - auto lit = expr2literal(var); - if (lit == sat::null_literal) { - IF_VERBOSE(5, verbose_stream() << "no literal associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); - return; - } - if (m.is_true(value)) - s().set_phase(lit); - else if (m.is_false(value)) - s().set_phase(~lit); - else - IF_VERBOSE(5, verbose_stream() << "malformed value " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); - return; - } - auto* th = m_id2solver.get(var->get_sort()->get_family_id(), nullptr); - if (!th) { - IF_VERBOSE(5, verbose_stream() << "no default initialization associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); - return; - } - // th->initialize_value(var, value); - IF_VERBOSE(5, verbose_stream() << "no default initialization associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + + m_initial_values.push_back({expr_ref(var, m), expr_ref(value, m)}); + push(push_back_vector(m_initial_values)); + } diff --git a/src/sat/smt/euf_solver.h b/src/sat/smt/euf_solver.h index 8c436b942..650208183 100644 --- a/src/sat/smt/euf_solver.h +++ b/src/sat/smt/euf_solver.h @@ -189,6 +189,8 @@ namespace euf { euf::enode* mk_true(); euf::enode* mk_false(); + vector> m_initial_values; + // replay typedef std::tuple reinit_t; vector m_reinit; diff --git a/src/sat/smt/sat_th.h b/src/sat/smt/sat_th.h index 373948014..24226eede 100644 --- a/src/sat/smt/sat_th.h +++ b/src/sat/smt/sat_th.h @@ -152,6 +152,8 @@ namespace euf { virtual void finalize() {} + virtual void initialize_value(expr* v, expr* value) { IF_VERBOSE(5, verbose_stream() << "value initialzation is not supported for theory\n"); } + }; class th_proof_hint : public sat::proof_hint { diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 8f334276d..38291237d 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -1422,7 +1422,6 @@ public: m_num_conflicts = 0; for (auto const& [v, r] : m_values) lp().move_lpvar_to_value(v, r); - display(verbose_stream() << "init search\n"); } bool can_get_value(theory_var v) const { From a3f35b6830fb9639a3e1d0dc23250e91973cb244 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 18 Sep 2024 17:48:03 +0300 Subject: [PATCH 103/187] Add command to set initial value hints for solver in various components --- src/cmd_context/basic_cmds.cpp | 20 +++++++++++++++++++ src/cmd_context/cmd_context.h | 2 ++ src/nlsat/tactic/nlsat_tactic.cpp | 3 +++ src/opt/opt_context.h | 4 ++-- src/qe/nlqsat.cpp | 2 ++ src/qe/qsat.cpp | 4 +++- src/sat/tactic/sat_tactic.cpp | 5 +++++ src/smt/theory_bv.cpp | 20 +++++++++++++++++++ src/smt/theory_bv.h | 1 + src/smt/theory_lra.cpp | 6 +----- src/solver/combined_solver.cpp | 1 + src/solver/solver2tactic.cpp | 5 +++++ src/tactic/.#tactic.cpp | 1 + .../fd_solver/bounded_int2bv_solver.cpp | 3 +++ src/tactic/tactic.cpp | 1 + src/tactic/tactic.h | 1 + src/tactic/tactical.cpp | 11 ++++++++++ 17 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 src/tactic/.#tactic.cpp diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index c93e4432f..cf661df49 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -318,6 +318,25 @@ UNARY_CMD(echo_cmd, "echo", "", "display the given string", CPK_STRING, else ctx.regular_stream() << arg << std::endl;); +class set_initial_value_cmd : public cmd { + expr* m_var = nullptr, *m_value = nullptr; +public: + set_initial_value_cmd(): cmd("set-initial-value") {} + char const* get_usage() const override { return " "; } + char const* get_descr(cmd_context& ctx) const { return "set an initial value for search as a hint to the solver"; } + unsigned get_arity() const { return 2; } + void prepare(cmd_context& ctx) { m_var = m_value = nullptr; } + cmd_arg_kind next_arg_kind(cmd_context& ctx) const { return CPK_EXPR; } + void set_next_arg(cmd_context& ctx, expr* e) { if (m_var) m_value = e; else m_var = e; } + void execute(cmd_context& ctx) { + SASSERT(m_var && m_value); + if (ctx.get_opt()) + ctx.get_opt()->initialize_value(m_var, m_value); + else if (ctx.get_solver()) + ctx.get_solver()->user_propagate_initialize_value(m_var, m_value); + } +}; + class set_get_option_cmd : public cmd { protected: symbol m_true; @@ -893,6 +912,7 @@ void install_basic_cmds(cmd_context & ctx) { ctx.insert(alloc(get_option_cmd)); ctx.insert(alloc(get_info_cmd)); ctx.insert(alloc(set_info_cmd)); + ctx.insert(alloc(set_initial_value_cmd)); ctx.insert(alloc(get_consequences_cmd)); ctx.insert(alloc(builtin_cmd, "assert", "", "assert term.")); ctx.insert(alloc(builtin_cmd, "check-sat", "*", "check if the current context is satisfiable. If a list of boolean constants B is provided, then check if the current context is consistent with assigning every constant in B to true.")); diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index c07d888c7..fc3c9f310 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -173,6 +173,8 @@ public: virtual void set_logic(symbol const& s) = 0; virtual void get_box_model(model_ref& mdl, unsigned index) = 0; virtual void updt_params(params_ref const& p) = 0; + virtual void initialize_value(expr* var, expr* value) = 0; + }; class ast_context_params : public context_params { diff --git a/src/nlsat/tactic/nlsat_tactic.cpp b/src/nlsat/tactic/nlsat_tactic.cpp index 9426de78e..11c80de2a 100644 --- a/src/nlsat/tactic/nlsat_tactic.cpp +++ b/src/nlsat/tactic/nlsat_tactic.cpp @@ -262,6 +262,9 @@ public: void reset_statistics() override { m_stats.reset(); } + + void user_propagate_initialize_value(expr* var, expr* value) override { } + }; tactic * mk_nlsat_tactic(ast_manager & m, params_ref const & p) { diff --git a/src/opt/opt_context.h b/src/opt/opt_context.h index 845fd3968..991fe16e6 100644 --- a/src/opt/opt_context.h +++ b/src/opt/opt_context.h @@ -277,8 +277,8 @@ namespace opt { void add_offset(unsigned id, rational const& o) override; - void initialize_value(expr* var, expr* value); - + void initialize_value(expr* var, expr* value) override; + void register_on_model(on_model_t& ctx, std::function& on_model) { m_on_model_ctx = ctx; m_on_model_eh = on_model; diff --git a/src/qe/nlqsat.cpp b/src/qe/nlqsat.cpp index 37cf62c61..9fd1d4e0e 100644 --- a/src/qe/nlqsat.cpp +++ b/src/qe/nlqsat.cpp @@ -848,6 +848,8 @@ namespace qe { void collect_param_descrs(param_descrs & r) override { } + void user_propagate_initialize_value(expr* var, expr* value) override { } + void operator()(/* in */ goal_ref const & in, /* out */ goal_ref_buffer & result) override { diff --git a/src/qe/qsat.cpp b/src/qe/qsat.cpp index dc0613c59..0ff054a89 100644 --- a/src/qe/qsat.cpp +++ b/src/qe/qsat.cpp @@ -1377,7 +1377,9 @@ namespace qe { tactic * translate(ast_manager & m) override { return alloc(qsat, m, m_params, m_mode); - } + } + + void user_propagate_initialize_value(expr* var, expr* value) override { } lbool maximize(expr_ref_vector const& fmls, app* t, model_ref& mdl, opt::inf_eps& value) { expr_ref_vector defs(m); diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp index 562fa431e..223222f9a 100644 --- a/src/sat/tactic/sat_tactic.cpp +++ b/src/sat/tactic/sat_tactic.cpp @@ -246,6 +246,11 @@ public: m_stats.reset(); } + void user_propagate_initialize_value(expr* var, expr* value) override { + + } + + protected: }; diff --git a/src/smt/theory_bv.cpp b/src/smt/theory_bv.cpp index 55d3a1d62..cf110298f 100644 --- a/src/smt/theory_bv.cpp +++ b/src/smt/theory_bv.cpp @@ -1789,6 +1789,26 @@ namespace smt { return false; } + void theory_bv::initialize_value(expr* var, expr* value) { + rational val; + unsigned sz; + if (!m_util.is_numeral(value, val, sz)) { + IF_VERBOSE(5, verbose_stream() << "value should be a bit-vector " << mk_pp(value, m) << "\n"); + return; + } + if (!is_app(var)) + return; + enode* n = mk_enode(to_app(var)); + auto v = get_var(n); + unsigned idx = 0; + for (auto lit : m_bits[v]) { + auto & b = ctx.get_bdata(lit.var()); + b.m_phase_available = true; + b.m_phase = val.get_bit(idx); + ++idx; + } + } + void theory_bv::init_model(model_generator & mg) { m_factory = alloc(bv_factory, m); mg.register_factory(m_factory); diff --git a/src/smt/theory_bv.h b/src/smt/theory_bv.h index 10cf005e3..72775c1d3 100644 --- a/src/smt/theory_bv.h +++ b/src/smt/theory_bv.h @@ -251,6 +251,7 @@ namespace smt { bool merge_zero_one_bits(theory_var r1, theory_var r2); bool can_propagate() override { return m_prop_diseqs_qhead < m_prop_diseqs.size(); } void propagate() override; + void initialize_value(expr* var, expr* value) override; // ----------------------------------- // diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 38291237d..6de623bb7 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -154,7 +154,6 @@ class theory_lra::imp { svector m_asserted_atoms; ptr_vector m_not_handled; ptr_vector m_underspecified; - vector> m_values; vector > m_use_list; // bounds where variables are used. // attributes for incremental version: @@ -998,8 +997,7 @@ public: IF_VERBOSE(5, verbose_stream() << "numeric constant expected in initialization " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); return; } - ctx().push_trail(push_back_vector(m_values)); - m_values.push_back({get_lpvar(var), r}); + lp().move_lpvar_to_value(get_lpvar(var), r); } void new_eq_eh(theory_var v1, theory_var v2) { @@ -1420,8 +1418,6 @@ public: void init_search_eh() { m_arith_eq_adapter.init_search_eh(); m_num_conflicts = 0; - for (auto const& [v, r] : m_values) - lp().move_lpvar_to_value(v, r); } bool can_get_value(theory_var v) const { diff --git a/src/solver/combined_solver.cpp b/src/solver/combined_solver.cpp index 051dfd4eb..34d31ec84 100644 --- a/src/solver/combined_solver.cpp +++ b/src/solver/combined_solver.cpp @@ -396,6 +396,7 @@ public: } void user_propagate_initialize_value(expr* var, expr* value) override { + m_solver1->user_propagate_initialize_value(var, value); m_solver2->user_propagate_initialize_value(var, value); } diff --git a/src/solver/solver2tactic.cpp b/src/solver/solver2tactic.cpp index b8e3dd37a..add55c628 100644 --- a/src/solver/solver2tactic.cpp +++ b/src/solver/solver2tactic.cpp @@ -189,6 +189,11 @@ public: } char const* name() const override { return "solver2tactic"; } + + + void user_propagate_initialize_value(expr* var, expr* value) override { + m_solver->user_propagate_initialize_value(var, value); + } }; tactic* mk_solver2tactic(solver* s) { return alloc(solver2tactic, s); } diff --git a/src/tactic/.#tactic.cpp b/src/tactic/.#tactic.cpp new file mode 100644 index 000000000..12fd8329b --- /dev/null +++ b/src/tactic/.#tactic.cpp @@ -0,0 +1 @@ +nbjorner@LAPTOP-04AEAFKH.32880:1726092166 \ No newline at end of file diff --git a/src/tactic/fd_solver/bounded_int2bv_solver.cpp b/src/tactic/fd_solver/bounded_int2bv_solver.cpp index 317286e1e..45b444fe9 100644 --- a/src/tactic/fd_solver/bounded_int2bv_solver.cpp +++ b/src/tactic/fd_solver/bounded_int2bv_solver.cpp @@ -375,6 +375,9 @@ private: return m_assertions.get(idx); } } + + void user_propagate_initialize_value(expr* var, expr* value) override { + } }; solver * mk_bounded_int2bv_solver(ast_manager & m, params_ref const & p, solver* s) { diff --git a/src/tactic/tactic.cpp b/src/tactic/tactic.cpp index f7dcfb3ea..e4e7b246a 100644 --- a/src/tactic/tactic.cpp +++ b/src/tactic/tactic.cpp @@ -151,6 +151,7 @@ public: throw tactic_exception("undecided"); skip_tactic::operator()(in, result); } + void user_propagate_initialize_value(expr* var, expr* value) override { } }; tactic * mk_fail_if_undecided_tactic() { diff --git a/src/tactic/tactic.h b/src/tactic/tactic.h index e62f93ecf..c69276424 100644 --- a/src/tactic/tactic.h +++ b/src/tactic/tactic.h @@ -129,6 +129,7 @@ public: tactic * translate(ast_manager & m) override { return this; } char const* name() const override { return "skip"; } void collect_statistics(statistics& st) const override {} + void user_propagate_initialize_value(expr* var, expr* value) override { } }; tactic * mk_skip_tactic(); diff --git a/src/tactic/tactical.cpp b/src/tactic/tactical.cpp index 626380913..db0a6d44d 100644 --- a/src/tactic/tactical.cpp +++ b/src/tactic/tactical.cpp @@ -382,6 +382,12 @@ public: } tactic * translate(ast_manager & m) override { return translate_core(m); } + + void user_propagate_initialize_value(expr* var, expr* value) override { + for (auto t : m_ts) + t->user_propagate_initialize_value(var, value); + } + }; tactic * or_else(unsigned num, tactic * const * ts) { @@ -1163,6 +1169,11 @@ public: tactic * new_t2 = m_t2->translate(m); return alloc(cond_tactical, m_p.get(), new_t1, new_t2); } + + void user_propagate_initialize_value(expr* var, expr* value) override { + m_t1->user_propagate_initialize_value(var, value); + m_t2->user_propagate_initialize_value(var, value); + } }; tactic * cond(probe * p, tactic * t1, tactic * t2) { From 4896edfb042a44c05b57770d4f77298723071c28 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 19 Sep 2024 11:27:17 +0300 Subject: [PATCH 104/187] Add tracking of values size in scoped_state push method in opt_context --- src/opt/opt_context.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp index 90bc0ddd6..0c18580e5 100644 --- a/src/opt/opt_context.cpp +++ b/src/opt/opt_context.cpp @@ -53,6 +53,7 @@ namespace opt { void context::scoped_state::push() { m_asms_lim.push_back(m_asms.size()); m_hard_lim.push_back(m_hard.size()); + m_values_lim.push_back(m_values.size()); m_objectives_lim.push_back(m_objectives.size()); m_objectives_term_trail_lim.push_back(m_objectives_term_trail.size()); } From 8349ee006936f8088e2cbba66504bd2c8fc458a4 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 19 Sep 2024 11:44:18 +0300 Subject: [PATCH 105/187] Add support for const array in all logics as per issue #7383 --- src/ast/array_decl_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/array_decl_plugin.cpp b/src/ast/array_decl_plugin.cpp index bd9d954c7..c013036f4 100644 --- a/src/ast/array_decl_plugin.cpp +++ b/src/ast/array_decl_plugin.cpp @@ -577,9 +577,9 @@ void array_decl_plugin::get_sort_names(svector& sort_names, symbol void array_decl_plugin::get_op_names(svector& op_names, symbol const & logic) { op_names.push_back(builtin_name("store",OP_STORE)); op_names.push_back(builtin_name("select",OP_SELECT)); + op_names.push_back(builtin_name("const",OP_CONST_ARRAY)); // github issue #7383 if (logic == symbol::null || logic == symbol("HORN") || logic == symbol("ALL")) { // none of the SMT2 logics support these extensions - op_names.push_back(builtin_name("const",OP_CONST_ARRAY)); op_names.push_back(builtin_name("map",OP_ARRAY_MAP)); op_names.push_back(builtin_name("default",OP_ARRAY_DEFAULT)); op_names.push_back(builtin_name("union",OP_SET_UNION)); From b99c4a47a4097cc6a671808f1e8abafcfd54bd06 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 19 Sep 2024 15:11:59 +0300 Subject: [PATCH 106/187] Add override specifiers to methods in set_initial_value_cmd class for clarity and consistency --- src/cmd_context/basic_cmds.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index cf661df49..402799e84 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -323,12 +323,12 @@ class set_initial_value_cmd : public cmd { public: set_initial_value_cmd(): cmd("set-initial-value") {} char const* get_usage() const override { return " "; } - char const* get_descr(cmd_context& ctx) const { return "set an initial value for search as a hint to the solver"; } - unsigned get_arity() const { return 2; } - void prepare(cmd_context& ctx) { m_var = m_value = nullptr; } - cmd_arg_kind next_arg_kind(cmd_context& ctx) const { return CPK_EXPR; } - void set_next_arg(cmd_context& ctx, expr* e) { if (m_var) m_value = e; else m_var = e; } - void execute(cmd_context& ctx) { + char const* get_descr(cmd_context& ctx) const override { return "set an initial value for search as a hint to the solver"; } + unsigned get_arity() const override { return 2; } + void prepare(cmd_context& ctx) override { m_var = m_value = nullptr; } + cmd_arg_kind next_arg_kind(cmd_context& ctx) const override { return CPK_EXPR; } + void set_next_arg(cmd_context& ctx, expr* e) override { if (m_var) m_value = e; else m_var = e; } + void execute(cmd_context& ctx) override { SASSERT(m_var && m_value); if (ctx.get_opt()) ctx.get_opt()->initialize_value(m_var, m_value); From 342dccdc0223b10f03369b037d529b396f70843b Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 19 Sep 2024 14:11:27 -0700 Subject: [PATCH 107/187] correctly process cancellation in gomory cuts Signed-off-by: Lev Nachmanson --- src/math/lp/gomory.cpp | 5 ++++- src/math/lp/lia_move.h | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/math/lp/gomory.cpp b/src/math/lp/gomory.cpp index 7b4347af5..6b7817769 100644 --- a/src/math/lp/gomory.cpp +++ b/src/math/lp/gomory.cpp @@ -527,7 +527,7 @@ public: has_small_cut = true; add_cut(cc.m_t, cc.m_k, cc.m_dep); if (lia.settings().get_cancel_flag()) - return lia_move::undef; + return lia_move::cancelled; } if (big_cuts.size()) { @@ -544,6 +544,9 @@ public: if (!_check_feasible()) return lia_move::conflict; + + if (lra.get_status() == lp_status::CANCELLED) + return lia_move::cancelled; if (!lia.has_inf_int()) return lia_move::sat; diff --git a/src/math/lp/lia_move.h b/src/math/lp/lia_move.h index 12e3d8e35..75ff67dcd 100644 --- a/src/math/lp/lia_move.h +++ b/src/math/lp/lia_move.h @@ -26,7 +26,8 @@ namespace lp { conflict, continue_with_check, undef, - unsat + unsat, + cancelled }; inline std::string lia_move_to_string(lia_move m) { switch (m) { From 0c48a50d59f207e3f1dee38a02391fd21f038d5b Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 19 Sep 2024 22:44:16 +0300 Subject: [PATCH 108/187] Add support for initializing variable values in solver and optimize contexts in Z3 --- RELEASE_NOTES.md | 13 +++++- src/ast/ast.cpp | 7 +++- .../converters/generic_model_converter.cpp | 41 +++++++++++++++++++ src/ast/converters/generic_model_converter.h | 3 ++ src/ast/converters/model_converter.cpp | 6 +++ src/ast/converters/model_converter.h | 2 + src/cmd_context/basic_cmds.cpp | 5 +-- src/cmd_context/cmd_context.cpp | 14 +++++++ src/cmd_context/cmd_context.h | 2 + src/opt/opt_context.cpp | 4 +- src/sat/sat_solver/inc_sat_solver.cpp | 9 +++- src/tactic/.#tactic.cpp | 1 - 12 files changed, 98 insertions(+), 9 deletions(-) delete mode 100644 src/tactic/.#tactic.cpp diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index cc961a760..50e181aeb 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -18,7 +18,18 @@ Version 4.13.1 The projection is described in paper by Haokun Li and Bican Xia, [Solving Satisfiability of Polynomial Formulas By Sample - Cell Projection](https://arxiv.org/abs/2003.00409). The code ported from https://github.com/hybridSMT/hybridSMT.git - Add API for providing hints for the solver/optimize contexts for which initial values to attempt to use for variables. - The new API function are Z3_solver_set_initial_value and Z3_optimize_set_initial_value, respectively. Supply these functions with a Boolean or numeric variable, and a value. The solver will then attempt to use these values in the initial phase of search. The feature is aimed at resolving nearly similar problems, or problems with a predicted model and the intent is that restarting the solver based on a near solution can avoid prune the space of constraints that are initially infeasible. + The new API function are Z3_solver_set_initial_value and Z3_optimize_set_initial_value, respectively. Supply these functions with a Boolean or numeric variable, and a value. The solver will then attempt to use these values in the initial phase of search. The feature is aimed at resolving nearly similar problems, or problems with a predicted model and the intent is that restarting the solver based on a near solution can avoid prune the space of constraints that are initially infeasible. + The SMTLIB front-end contains the new command (set-initial-value var value). For example, + (declare-const x Int) + (set-initial-value x 10) + (push) + (assert (> x 0)) + (check-sat) + (get-model) + produces a model where x = 10. We use (push) to ensure that z3 doesn't run a + specialized pre-processor that eliminates x, which renders the initialization + without effect. + Version 4.13.0 ============== diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index e1e3efe99..5194154f0 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -1008,7 +1008,8 @@ sort* basic_decl_plugin::join(unsigned n, expr* const* es) { } sort* basic_decl_plugin::join(sort* s1, sort* s2) { - if (s1 == s2) return s1; + if (s1 == s2) + return s1; if (s1->get_family_id() == arith_family_id && s2->get_family_id() == arith_family_id) { if (s1->get_decl_kind() == REAL_SORT) { @@ -1016,6 +1017,10 @@ sort* basic_decl_plugin::join(sort* s1, sort* s2) { } return s2; } + if (s1 == m_bool_sort && s2->get_family_id() == arith_family_id) + return s2; + if (s2 == m_bool_sort && s1->get_family_id() == arith_family_id) + return s1; std::ostringstream buffer; buffer << "Sorts " << mk_pp(s1, *m_manager) << " and " << mk_pp(s2, *m_manager) << " are incompatible"; throw ast_exception(buffer.str()); diff --git a/src/ast/converters/generic_model_converter.cpp b/src/ast/converters/generic_model_converter.cpp index c50d86cae..81f24ed8a 100644 --- a/src/ast/converters/generic_model_converter.cpp +++ b/src/ast/converters/generic_model_converter.cpp @@ -130,6 +130,47 @@ generic_model_converter * generic_model_converter::copy(ast_translation & transl return res; } +void generic_model_converter::convert_initialize_value(expr_ref& var, expr_ref& value) { + for (auto const& e : m_entries) { + switch (e.m_instruction) { + case HIDE: + break; + case ADD: + if (is_uninterp_const(var) && e.m_f == to_app(var)->get_decl()) + convert_initialize_value(e.m_def, var, value); + break; + } + } +} + +void generic_model_converter::convert_initialize_value(expr* def, expr_ref& var, expr_ref& value) { + + // var = if(c, th, el) = value + // th = value => c = true + // el = value => c = false + expr* c = nullptr, *th = nullptr, *el = nullptr; + if (m.is_ite(def, c, th, el)) { + if (value == th) { + var = c; + value = m.mk_true(); + return; + } + if (value == el) { + var = c; + value = m.mk_false(); + return; + } + } + + // var = def = value + // => def = value + if (is_uninterp(def)) + var = def; + + +} + + void generic_model_converter::set_env(ast_pp_util* visitor) { if (!visitor) { diff --git a/src/ast/converters/generic_model_converter.h b/src/ast/converters/generic_model_converter.h index 0bc6b21b4..e778828cd 100644 --- a/src/ast/converters/generic_model_converter.h +++ b/src/ast/converters/generic_model_converter.h @@ -37,6 +37,7 @@ private: vector m_entries; expr_ref simplify_def(entry const& e); + void convert_initialize_value(expr* def, expr_ref& var, expr_ref& value); public: generic_model_converter(ast_manager & m, char const* orig) : m(m), m_orig(orig) {} @@ -61,6 +62,8 @@ public: model_converter * translate(ast_translation & translator) override { return copy(translator); } + void convert_initialize_value(expr_ref& var, expr_ref& value) override; + generic_model_converter* copy(ast_translation & translator); void set_env(ast_pp_util* visitor) override; diff --git a/src/ast/converters/model_converter.cpp b/src/ast/converters/model_converter.cpp index d053394ca..f03ef5327 100644 --- a/src/ast/converters/model_converter.cpp +++ b/src/ast/converters/model_converter.cpp @@ -107,6 +107,12 @@ public: m_c2->get_units(fmls); m_c1->get_units(fmls); } + + void convert_initialize_value(expr_ref& var, expr_ref& value) override { + m_c2->convert_initialize_value(var, value); + m_c1->convert_initialize_value(var, value); + } + char const * get_name() const override { return "concat-model-converter"; } diff --git a/src/ast/converters/model_converter.h b/src/ast/converters/model_converter.h index 720324919..0165cfbfc 100644 --- a/src/ast/converters/model_converter.h +++ b/src/ast/converters/model_converter.h @@ -86,6 +86,8 @@ public: virtual void set_env(ast_pp_util* visitor); + virtual void convert_initialize_value(expr_ref& var, expr_ref& value) { } + /** \brief we are adding a formula to the context of the model converter. The operator has as side effect of adding definitions as assertions to the diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 402799e84..beb3aa0bb 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -330,10 +330,7 @@ public: void set_next_arg(cmd_context& ctx, expr* e) override { if (m_var) m_value = e; else m_var = e; } void execute(cmd_context& ctx) override { SASSERT(m_var && m_value); - if (ctx.get_opt()) - ctx.get_opt()->initialize_value(m_var, m_value); - else if (ctx.get_solver()) - ctx.get_solver()->user_propagate_initialize_value(m_var, m_value); + ctx.set_initial_value(m_var, m_value); } }; diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 231c78bc2..e9ca5595f 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -629,6 +629,7 @@ cmd_context::~cmd_context() { finalize_cmds(); finalize_tactic_manager(); m_proof_cmds = nullptr; + m_var2values.reset(); reset(true); m_mcs.reset(); m_solver = nullptr; @@ -654,6 +655,8 @@ void cmd_context::set_opt(opt_wrapper* opt) { m_opt = opt; for (unsigned i = 0; i < m_scopes.size(); ++i) m_opt->push(); + for (auto const& [var, value] : m_var2values) + m_opt->initialize_value(var, value); m_opt->set_logic(m_logic); } @@ -1874,6 +1877,17 @@ void cmd_context::display_dimacs() { } } +void cmd_context::set_initial_value(expr* var, expr* value) { + if (get_opt()) { + get_opt()->initialize_value(var, value); + return; + } + if (get_solver()) + get_solver()->user_propagate_initialize_value(var, value); + m_var2values.push_back({expr_ref(var, m()), expr_ref(value, m())}); +} + + void cmd_context::display_model(model_ref& mdl) { if (mdl) { if (mc0()) (*mc0())(mdl); diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index fc3c9f310..d113eb881 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -262,6 +262,7 @@ protected: scoped_ptr_vector m_extra_builtin_decls; // make sure that dynamically allocated builtin_decls are deleted dictionary m_object_refs; // anything that can be named. dictionary m_user_tactic_decls; + vector> m_var2values; dictionary m_func_decls; obj_map m_func_decl2alias; @@ -421,6 +422,7 @@ public: solver* get_solver() { return m_solver.get(); } void set_solver(solver* s) { m_solver = s; } void set_proof_cmds(proof_cmds* pc) { m_proof_cmds = pc; } + void set_initial_value(expr* var, expr* value); void set_solver_factory(solver_factory * s); void set_check_sat_result(check_sat_result * r) { m_check_sat_result = r; } diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp index 0c18580e5..6eb1de598 100644 --- a/src/opt/opt_context.cpp +++ b/src/opt/opt_context.cpp @@ -311,7 +311,9 @@ namespace opt { } solver& s = get_solver(); s.assert_expr(m_hard_constraints); - for (auto const& [var, value] : m_scoped_state.m_values) { + for (auto & [var, value] : m_scoped_state.m_values) { + if (m_model_converter) + m_model_converter->convert_initialize_value(var, value); s.user_propagate_initialize_value(var, value); } diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index 0129a026e..8c4a79b76 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -703,7 +703,14 @@ public: } void user_propagate_initialize_value(expr* var, expr* value) override { - ensure_euf()->user_propagate_initialize_value(var, value); + expr_ref _var(var, m), _value(value, m); + if (m_mcs.back()) + m_mcs.back()->convert_initialize_value(_var, _value); + sat::bool_var b = m_map.to_bool_var(_var); + if (b != sat::null_bool_var) + m_solver.set_phase(sat::literal(b, m.is_false(_value))); + else if (get_euf()) + ensure_euf()->user_propagate_initialize_value(_var, _value); } diff --git a/src/tactic/.#tactic.cpp b/src/tactic/.#tactic.cpp deleted file mode 100644 index 12fd8329b..000000000 --- a/src/tactic/.#tactic.cpp +++ /dev/null @@ -1 +0,0 @@ -nbjorner@LAPTOP-04AEAFKH.32880:1726092166 \ No newline at end of file From d66609ea14e8d329bb1ab730c93c98f3f67250be Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 22 Sep 2024 02:41:11 +0300 Subject: [PATCH 109/187] fix #7389 Signed-off-by: Nikolaj Bjorner --- src/ast/rewriter/bv_rewriter.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/ast/rewriter/bv_rewriter.cpp b/src/ast/rewriter/bv_rewriter.cpp index db87cd008..96fb1f856 100644 --- a/src/ast/rewriter/bv_rewriter.cpp +++ b/src/ast/rewriter/bv_rewriter.cpp @@ -618,6 +618,31 @@ br_status bv_rewriter::mk_leq_core(bool is_signed, expr * a, expr * b, expr_ref return BR_REWRITE3; } + // #x000f <=_u a <=> not (a <=_u #x000f) or a = #x000f + i = bv_sz; + first_non_zero = UINT_MAX; + while (i > 0) { + --i; + if (!is_zero_bit(a, i)) { + first_non_zero = i; + break; + } + } + + if (first_non_zero == UINT_MAX) { + // all bits are zero + result = m.mk_eq(b, mk_zero(bv_sz)); + return BR_REWRITE1; + } + else if (first_non_zero < bv_sz - 1 && m_le2extract) { + result = m.mk_and(m.mk_eq(m_mk_extract(bv_sz - 1, first_non_zero + 1, b), mk_zero(bv_sz - first_non_zero - 1)), + m_util.mk_ule(m_mk_extract(first_non_zero, 0, b), m_mk_extract(first_non_zero, 0, a))); + result = m.mk_or(m.mk_not(result), m.mk_eq(a, b)); + return BR_REWRITE_FULL; + } + + + } #endif From fa7fc8ef5ed98849f1a1408130f61a1b98bf58ca Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 22 Sep 2024 13:04:49 +0300 Subject: [PATCH 110/187] Refactor bv_rewriter functions using unified variable assignment and early break logic --- src/ast/rewriter/bv_rewriter.cpp | 82 ++++++++++++++++---------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/src/ast/rewriter/bv_rewriter.cpp b/src/ast/rewriter/bv_rewriter.cpp index 96fb1f856..018587afc 100644 --- a/src/ast/rewriter/bv_rewriter.cpp +++ b/src/ast/rewriter/bv_rewriter.cpp @@ -109,17 +109,20 @@ br_status bv_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons break; case OP_BNEG_OVFL: SASSERT(num_args == 1); - return mk_bvneg_overflow(args[0], result); - + st = mk_bvneg_overflow(args[0], result); + break; case OP_BSHL: SASSERT(num_args == 2); - return mk_bv_shl(args[0], args[1], result); + st = mk_bv_shl(args[0], args[1], result); + break; case OP_BLSHR: SASSERT(num_args == 2); - return mk_bv_lshr(args[0], args[1], result); + st = mk_bv_lshr(args[0], args[1], result); + break; case OP_BASHR: SASSERT(num_args == 2); - return mk_bv_ashr(args[0], args[1], result); + st = mk_bv_ashr(args[0], args[1], result); + break; case OP_BSDIV: SASSERT(num_args == 2); return mk_bv_sdiv(args[0], args[1], result); @@ -151,13 +154,16 @@ br_status bv_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons SASSERT(num_args == 2); return mk_bv_smod_i(args[0], args[1], result); case OP_CONCAT: - return mk_concat(num_args, args, result); + st = mk_concat(num_args, args, result); + break; case OP_EXTRACT: SASSERT(num_args == 1); - return mk_extract(m_util.get_extract_high(f), m_util.get_extract_low(f), args[0], result); + st = mk_extract(m_util.get_extract_high(f), m_util.get_extract_low(f), args[0], result); + break; case OP_REPEAT: SASSERT(num_args == 1); - return mk_repeat(f->get_parameter(0).get_int(), args[0], result); + st = mk_repeat(f->get_parameter(0).get_int(), args[0], result); + break; case OP_ZERO_EXT: SASSERT(num_args == 1); return mk_zero_extend(f->get_parameter(0).get_int(), args[0], result); @@ -596,53 +602,45 @@ br_status bv_rewriter::mk_leq_core(bool is_signed, expr * a, expr * b, expr_ref // // a <=_u #x000f // - unsigned bv_sz = m_util.get_bv_size(b); - unsigned i = bv_sz; - unsigned first_non_zero = UINT_MAX; - while (i > 0) { - --i; - if (!is_zero_bit(b, i)) { - first_non_zero = i; - break; - } - } + unsigned bv_sz = m_util.get_bv_size(a); + auto last_non_zero = [&](expr* x) { + for (unsigned i = bv_sz; i-- > 0; ) + if (!is_zero_bit(x, i)) + return i; + return UINT_MAX; + }; + + unsigned lnz = last_non_zero(b); - if (first_non_zero == UINT_MAX) { + if (lnz == UINT_MAX) { // all bits are zero result = m.mk_eq(a, mk_zero(bv_sz)); return BR_REWRITE1; } - else if (first_non_zero < bv_sz - 1 && m_le2extract) { - result = m.mk_and(m.mk_eq(m_mk_extract(bv_sz - 1, first_non_zero + 1, a), mk_zero(bv_sz - first_non_zero - 1)), - m_util.mk_ule(m_mk_extract(first_non_zero, 0, a), m_mk_extract(first_non_zero, 0, b))); + else if (lnz < bv_sz - 1 && m_le2extract) { + // a[sz-1:lnz+1] = 0 & a[lnz:0] <= b[lnz:0] + result = m.mk_and(m.mk_eq(m_mk_extract(bv_sz - 1, lnz + 1, a), mk_zero(bv_sz - lnz - 1)), + m_util.mk_ule(m_mk_extract(lnz, 0, a), m_mk_extract(lnz, 0, b))); + return BR_REWRITE3; } - // #x000f <=_u a <=> not (a <=_u #x000f) or a = #x000f - i = bv_sz; - first_non_zero = UINT_MAX; - while (i > 0) { - --i; - if (!is_zero_bit(a, i)) { - first_non_zero = i; - break; - } - } - if (first_non_zero == UINT_MAX) { + lnz = last_non_zero(a); + + if (lnz == UINT_MAX) { // all bits are zero - result = m.mk_eq(b, mk_zero(bv_sz)); - return BR_REWRITE1; + result = m.mk_true(); + return BR_DONE; } - else if (first_non_zero < bv_sz - 1 && m_le2extract) { - result = m.mk_and(m.mk_eq(m_mk_extract(bv_sz - 1, first_non_zero + 1, b), mk_zero(bv_sz - first_non_zero - 1)), - m_util.mk_ule(m_mk_extract(first_non_zero, 0, b), m_mk_extract(first_non_zero, 0, a))); - result = m.mk_or(m.mk_not(result), m.mk_eq(a, b)); + else if (lnz < bv_sz - 1 && m_le2extract) { + // use the equivalence to simplify: + // #x000f <=_u b <=> b[sz-1:lnz+1] != 0 or #xf <= b[lnz:0]) + + result = m.mk_implies(m.mk_eq(m_mk_extract(bv_sz - 1, lnz + 1, b), mk_zero(bv_sz - lnz - 1)), + m_util.mk_ule(m_mk_extract(lnz, 0, a), m_mk_extract(lnz, 0, b))); return BR_REWRITE_FULL; } - - - } #endif From ba5cec77045720d9cb81edbf102e473762762f37 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 22 Sep 2024 21:29:12 +0300 Subject: [PATCH 111/187] additional rewrites for bv2int --- src/ast/rewriter/bv_rewriter.cpp | 61 +++++++++++++++++++++++++++++--- src/ast/rewriter/bv_rewriter.h | 1 + src/ast/rewriter/th_rewriter.cpp | 9 +++++ 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/ast/rewriter/bv_rewriter.cpp b/src/ast/rewriter/bv_rewriter.cpp index 018587afc..7b54f76a1 100644 --- a/src/ast/rewriter/bv_rewriter.cpp +++ b/src/ast/rewriter/bv_rewriter.cpp @@ -1445,19 +1445,50 @@ br_status bv_rewriter::mk_bv_smod_core(expr * arg1, expr * arg2, bool hi_div0, e br_status bv_rewriter::mk_int2bv(unsigned bv_size, expr * arg, expr_ref & result) { numeral val; bool is_int; - + expr* x; if (m_autil.is_numeral(arg, val, is_int)) { val = m_util.norm(val, bv_size); result = mk_numeral(val, bv_size); return BR_DONE; } - // (int2bv (bv2int x)) --> x - if (m_util.is_bv2int(arg) && bv_size == get_bv_size(to_app(arg)->get_arg(0))) { - result = to_app(arg)->get_arg(0); + // int2bv (bv2int x) --> x + if (m_util.is_bv2int(arg, x) && bv_size == get_bv_size(x)) { + result = x; return BR_DONE; } + // int2bv (bv2int x) --> 0000x + if (m_util.is_bv2int(arg, x) && bv_size > get_bv_size(x)) { + mk_zero_extend(bv_size - get_bv_size(x), x, result); + return BR_REWRITE1; + } + + // int2bv (bv2int x) --> x[sz-1:0] + if (m_util.is_bv2int(arg, x) && bv_size < get_bv_size(x)) { + result = m_mk_extract(bv_size - 1, 0, x); + return BR_REWRITE1; + } + +#if 0 + // int2bv (a + b) --> int2bv(a) + int2bv(b) + if (m_autil.is_add(arg)) { + expr_ref_vector args(m); + for (expr* e : *to_app(arg)) + args.push_back(m_util.mk_int2bv(bv_size, e)); + result = m_util.mk_bv_add(args); + return BR_REWRITE3; + } + // int2bv (a * b) --> int2bv(a) * int2bv(b) + if (m_autil.is_mul(arg)) { + expr_ref_vector args(m); + for (expr* e : *to_app(arg)) + args.push_back(m_util.mk_int2bv(bv_size, e)); + result = m_util.mk_bv_mul(args); + return BR_REWRITE3; + } +#endif + return BR_FAILED; } @@ -2740,6 +2771,27 @@ bool bv_rewriter::is_urem_any(expr * e, expr * & dividend, expr * & divisor) { return true; } +br_status bv_rewriter::mk_eq_bv2int(expr* lhs, expr* rhs, expr_ref& result) { + rational r; + expr* x, *y; + if (m_autil.is_numeral(lhs)) + std::swap(lhs, rhs); + + if (m_autil.is_numeral(rhs, r) && m_util.is_bv2int(lhs, x)) { + unsigned bv_size = m_util.get_bv_size(x); + if (0 <= r && r < rational::power_of_two(bv_size)) + result = m.mk_eq(m_util.mk_numeral(r, bv_size), x); + else + result = m.mk_false(); + return BR_REWRITE1; + } + if (m_util.is_bv2int(lhs, x) && m_util.is_bv2int(rhs, y)) { + result = m.mk_eq(x, y); + return BR_REWRITE1; + } + return BR_FAILED; +} + br_status bv_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) { if (lhs == rhs) { result = m.mk_true(); @@ -2783,6 +2835,7 @@ br_status bv_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) { return st; } + if (m_blast_eq_value) { st = mk_blast_eq_value(lhs, rhs, result); if (st != BR_FAILED) diff --git a/src/ast/rewriter/bv_rewriter.h b/src/ast/rewriter/bv_rewriter.h index 67ed1da87..73710f5c6 100644 --- a/src/ast/rewriter/bv_rewriter.h +++ b/src/ast/rewriter/bv_rewriter.h @@ -203,6 +203,7 @@ public: bool is_urem_any(expr * e, expr * & dividend, expr * & divisor); br_status mk_eq_core(expr * lhs, expr * rhs, expr_ref & result); + br_status mk_eq_bv2int(expr* lhs, expr* rhs, expr_ref& result); br_status mk_ite_core(expr * c, expr * t, expr * e, expr_ref & result); br_status mk_distinct(unsigned num_args, expr * const * args, expr_ref & result); diff --git a/src/ast/rewriter/th_rewriter.cpp b/src/ast/rewriter/th_rewriter.cpp index 844c51940..483e2d5fb 100644 --- a/src/ast/rewriter/th_rewriter.cpp +++ b/src/ast/rewriter/th_rewriter.cpp @@ -685,9 +685,18 @@ struct th_rewriter_cfg : public default_rewriter_cfg { st = m_seq_rw.mk_eq_core(a, b, result); if (st != BR_FAILED) return st; + st = extended_bv_eq(a, b, result); + if (st != BR_FAILED) + return st; return apply_tamagotchi(a, b, result); } + br_status extended_bv_eq(expr* a, expr* b, expr_ref& result) { + if (m_bv_util.is_bv2int(a) || m_bv_util.is_bv2int(b)) + return m_bv_rw.mk_eq_bv2int(a, b, result); + return BR_FAILED; + } + expr_ref mk_eq(expr* a, expr* b) { expr_ref result(m()); br_status st = reduce_eq(a, b, result); From a9f8ec1bcb997ab7d386e67ff4825450b110728a Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 22 Sep 2024 21:30:11 +0300 Subject: [PATCH 112/187] updated handling of value initialization for bit-vectors --- .../converters/generic_model_converter.cpp | 39 +++++++++++++------ src/ast/converters/generic_model_converter.h | 4 +- src/ast/converters/model_converter.cpp | 6 +-- src/ast/converters/model_converter.h | 2 +- src/opt/opt_context.cpp | 7 ++-- src/sat/sat_solver/inc_sat_solver.cpp | 30 ++++++++++---- src/sat/tactic/sat_tactic.cpp | 29 +++++++++++--- src/smt/smt_context.cpp | 2 +- src/smt/theory_bv.cpp | 1 + src/tactic/bv/bit_blaster_model_converter.cpp | 28 +++++++++++++ 10 files changed, 112 insertions(+), 36 deletions(-) diff --git a/src/ast/converters/generic_model_converter.cpp b/src/ast/converters/generic_model_converter.cpp index 81f24ed8a..f64e798b5 100644 --- a/src/ast/converters/generic_model_converter.cpp +++ b/src/ast/converters/generic_model_converter.cpp @@ -22,6 +22,7 @@ Notes: #include "ast/for_each_expr.h" #include "ast/ast_util.h" #include "ast/occurs.h" +#include "ast/bv_decl_plugin.h" #include "ast/rewriter/expr_safe_replace.h" #include "ast/rewriter/th_rewriter.h" #include "ast/converters/generic_model_converter.h" @@ -130,25 +131,32 @@ generic_model_converter * generic_model_converter::copy(ast_translation & transl return res; } -void generic_model_converter::convert_initialize_value(expr_ref& var, expr_ref& value) { - for (auto const& e : m_entries) { - switch (e.m_instruction) { - case HIDE: - break; - case ADD: - if (is_uninterp_const(var) && e.m_f == to_app(var)->get_decl()) - convert_initialize_value(e.m_def, var, value); - break; +void generic_model_converter::convert_initialize_value(vector> & var2value) { + if (var2value.empty() || m_entries.empty()) + return; + for (unsigned i = 0; i < var2value.size(); ++i) { + auto& [var, value] = var2value[i]; + for (auto const& e : m_entries) { + switch (e.m_instruction) { + case HIDE: + break; + case ADD: + if (is_uninterp_const(var) && e.m_f == to_app(var)->get_decl()) + convert_initialize_value(e.m_def, i, var2value); + break; + } } } } -void generic_model_converter::convert_initialize_value(expr* def, expr_ref& var, expr_ref& value) { +void generic_model_converter::convert_initialize_value(expr* def, unsigned i, vector>& var2value) { // var = if(c, th, el) = value // th = value => c = true // el = value => c = false expr* c = nullptr, *th = nullptr, *el = nullptr; + auto& [var, value] = var2value[i]; + verbose_stream() << "def " << mk_pp(def, m) << "\n"; if (m.is_ite(def, c, th, el)) { if (value == th) { var = c; @@ -164,8 +172,15 @@ void generic_model_converter::convert_initialize_value(expr* def, expr_ref& var, // var = def = value // => def = value - if (is_uninterp(def)) - var = def; + if (is_uninterp(def)) { + var = def; + return; + } + + bv_util bv(m); + if (bv.is_mkbv(def)) { + verbose_stream() << "def\n"; + } } diff --git a/src/ast/converters/generic_model_converter.h b/src/ast/converters/generic_model_converter.h index e778828cd..18ec16fe0 100644 --- a/src/ast/converters/generic_model_converter.h +++ b/src/ast/converters/generic_model_converter.h @@ -37,7 +37,7 @@ private: vector m_entries; expr_ref simplify_def(entry const& e); - void convert_initialize_value(expr* def, expr_ref& var, expr_ref& value); + void convert_initialize_value(expr* def, unsigned i, vector>& var2value); public: generic_model_converter(ast_manager & m, char const* orig) : m(m), m_orig(orig) {} @@ -62,7 +62,7 @@ public: model_converter * translate(ast_translation & translator) override { return copy(translator); } - void convert_initialize_value(expr_ref& var, expr_ref& value) override; + void convert_initialize_value(vector>& var2value) override; generic_model_converter* copy(ast_translation & translator); diff --git a/src/ast/converters/model_converter.cpp b/src/ast/converters/model_converter.cpp index f03ef5327..c309bbb79 100644 --- a/src/ast/converters/model_converter.cpp +++ b/src/ast/converters/model_converter.cpp @@ -108,9 +108,9 @@ public: m_c1->get_units(fmls); } - void convert_initialize_value(expr_ref& var, expr_ref& value) override { - m_c2->convert_initialize_value(var, value); - m_c1->convert_initialize_value(var, value); + void convert_initialize_value(vector>& var2value) override { + m_c2->convert_initialize_value(var2value); + m_c1->convert_initialize_value(var2value); } diff --git a/src/ast/converters/model_converter.h b/src/ast/converters/model_converter.h index 0165cfbfc..354b51854 100644 --- a/src/ast/converters/model_converter.h +++ b/src/ast/converters/model_converter.h @@ -86,7 +86,7 @@ public: virtual void set_env(ast_pp_util* visitor); - virtual void convert_initialize_value(expr_ref& var, expr_ref& value) { } + virtual void convert_initialize_value(vector> & var2value) { } /** \brief we are adding a formula to the context of the model converter. diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp index 6eb1de598..c571753e9 100644 --- a/src/opt/opt_context.cpp +++ b/src/opt/opt_context.cpp @@ -311,11 +311,10 @@ namespace opt { } solver& s = get_solver(); s.assert_expr(m_hard_constraints); - for (auto & [var, value] : m_scoped_state.m_values) { - if (m_model_converter) - m_model_converter->convert_initialize_value(var, value); + if (m_model_converter) + m_model_converter->convert_initialize_value(m_scoped_state.m_values); + for (auto & [var, value] : m_scoped_state.m_values) s.user_propagate_initialize_value(var, value); - } opt_params optp(m_params); symbol pri = optp.priority(); diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index 8c4a79b76..19482c286 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -78,6 +78,7 @@ class inc_sat_solver : public solver { // this allows to access the internal state of the SAT solver and carry on partial results. bool m_internalized_converted; // have internalized formulas been converted back expr_ref_vector m_internalized_fmls; // formulas in internalized format + vector> m_var2value; typedef obj_map dep2asm_t; @@ -175,9 +176,27 @@ public: (m.is_not(e, e) && is_uninterp_const(e)); } + void initialize_values() { + if (m_mcs.back()) + m_mcs.back()->convert_initialize_value(m_var2value); + if (m_mcs.back()) + m_mcs.back()->display(verbose_stream()); + + for (auto & [var, value] : m_var2value) { + sat::bool_var b = m_map.to_bool_var(var); + if (b != sat::null_bool_var) + m_solver.set_phase(sat::literal(b, m.is_false(value))); + else if (get_euf()) + ensure_euf()->user_propagate_initialize_value(var, value); + } + } + lbool check_sat_core(unsigned sz, expr * const * assumptions) override { m_solver.pop_to_base_level(); m_core.reset(); + + + if (m_solver.inconsistent()) return l_false; expr_ref_vector _assumptions(m); obj_map asm2fml; @@ -202,6 +221,8 @@ public: r = internalize_assumptions(sz, _assumptions.data()); if (r != l_true) return r; + initialize_values(); + init_reason_unknown(); m_internalized_converted = false; bool reason_set = false; @@ -703,14 +724,7 @@ public: } void user_propagate_initialize_value(expr* var, expr* value) override { - expr_ref _var(var, m), _value(value, m); - if (m_mcs.back()) - m_mcs.back()->convert_initialize_value(_var, _value); - sat::bool_var b = m_map.to_bool_var(_var); - if (b != sat::null_bool_var) - m_solver.set_phase(sat::literal(b, m.is_false(_value))); - else if (get_euf()) - ensure_euf()->user_propagate_initialize_value(_var, _value); + m_var2value.push_back({expr_ref(var, m), expr_ref(value, m) }); } diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp index 223222f9a..e997cbc2c 100644 --- a/src/sat/tactic/sat_tactic.cpp +++ b/src/sat/tactic/sat_tactic.cpp @@ -32,13 +32,26 @@ class sat_tactic : public tactic { sat2goal m_sat2goal; scoped_ptr m_solver; params_ref m_params; + vector>& m_var2value; - imp(ast_manager & _m, params_ref const & p): + imp(ast_manager & _m, params_ref const & p, vector>& var2value): m(_m), m_solver(alloc(sat::solver, p, m.limit())), - m_params(p) { + m_params(p), + m_var2value(var2value) { updt_params(p); } + + void initialize_values(goal_ref const& g, atom2bool_var& map) { + g->mc()->convert_initialize_value(m_var2value); + for (auto & [var, value] : m_var2value) { + if (!m.is_bool(var)) + continue; + sat::bool_var b = map.to_bool_var(var); + if (b != sat::null_bool_var) + m_solver->set_phase(sat::literal(b, m.is_false(value))); + } + } void operator()(goal_ref const & g, goal_ref_buffer & result) { @@ -66,6 +79,8 @@ class sat_tactic : public tactic { g->reset(); g->m().compact_memory(); + initialize_values(g, map); + CASSERT("sat_solver", m_solver->check_invariant()); IF_VERBOSE(TACTIC_VERBOSITY_LVL, m_solver->display_status(verbose_stream());); TRACE("sat_dimacs", m_solver->display_dimacs(tout);); @@ -184,11 +199,14 @@ class sat_tactic : public tactic { imp * m_imp; params_ref m_params; statistics m_stats; + ast_manager& m; + vector> m_var2value; public: sat_tactic(ast_manager & m, params_ref const & p): m_imp(nullptr), - m_params(p) { + m_params(p), + m(m) { sat_params p1(p); } @@ -215,7 +233,7 @@ public: void operator()(goal_ref const & g, goal_ref_buffer & result) override { - imp proc(g->m(), m_params); + imp proc(g->m(), m_params, m_var2value); scoped_set_imp set(this, &proc); try { proc(g, result); @@ -247,7 +265,8 @@ public: } void user_propagate_initialize_value(expr* var, expr* value) override { - + verbose_stream() << "initialize-value\n"; + m_var2value.push_back({ expr_ref(var, m), expr_ref(value, m) }); } diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 163da9b16..deee05f6d 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -2920,7 +2920,7 @@ namespace smt { } void context::initialize_value(expr* var, expr* value) { - IF_VERBOSE(10, verbose_stream() << "context initialize " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); + IF_VERBOSE(10, verbose_stream() << "initialize " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); sort* s = var->get_sort(); ensure_internalized(var); diff --git a/src/smt/theory_bv.cpp b/src/smt/theory_bv.cpp index cf110298f..ca327891c 100644 --- a/src/smt/theory_bv.cpp +++ b/src/smt/theory_bv.cpp @@ -1792,6 +1792,7 @@ namespace smt { void theory_bv::initialize_value(expr* var, expr* value) { rational val; unsigned sz; + TRACE("bv", tout << "initializing " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); if (!m_util.is_numeral(value, val, sz)) { IF_VERBOSE(5, verbose_stream() << "value should be a bit-vector " << mk_pp(value, m) << "\n"); return; diff --git a/src/tactic/bv/bit_blaster_model_converter.cpp b/src/tactic/bv/bit_blaster_model_converter.cpp index 5958a9d38..5bc874abb 100644 --- a/src/tactic/bv/bit_blaster_model_converter.cpp +++ b/src/tactic/bv/bit_blaster_model_converter.cpp @@ -222,6 +222,34 @@ struct bit_blaster_model_converter : public model_converter { // no-op } + void convert_initialize_value(vector>& var2value) { + if (m_vars.empty() || var2value.empty()) + return; + rational r; + bv_util util(m()); + for (unsigned j = 0; j < var2value.size(); ++j) { + auto& [var, value] = var2value[j]; + if (!is_uninterp_const(var)) + continue; + if (!util.is_numeral(value, r)) + continue; + unsigned sz = m_vars.size(); + for (unsigned i = 0; i < sz; i++) { + if (m_vars.get(i) != to_app(var)->get_decl()) + continue; + unsigned k = 0; + expr_ref bit_k(m()); + for (auto arg : *to_app(m_bits.get(i))) { + bit_k = m().mk_bool_val(r.get_bit(k)); + var2value.push_back({ expr_ref(arg, m()), bit_k }); + ++k; + } + var2value[i] = var2value.back(); + var2value.pop_back(); + } + } + } + protected: bit_blaster_model_converter(ast_manager & m):m_vars(m), m_bits(m), m_newbits(m) { } public: From 96c13757864c3fb5ec91e811fb4b4186fcd4ce91 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 22 Sep 2024 19:35:03 +0100 Subject: [PATCH 113/187] #7391 Signed-off-by: Nikolaj Bjorner --- src/ast/rewriter/seq_rewriter.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ast/rewriter/seq_rewriter.cpp b/src/ast/rewriter/seq_rewriter.cpp index 50f0bc05a..7e39931f4 100644 --- a/src/ast/rewriter/seq_rewriter.cpp +++ b/src/ast/rewriter/seq_rewriter.cpp @@ -2060,6 +2060,10 @@ br_status seq_rewriter::mk_seq_replace_all(expr* a, expr* b, expr* c, expr_ref& result = m().mk_ite(str().mk_is_empty(b), str().mk_empty(a->get_sort()), c); return BR_REWRITE2; } + if (str().is_empty(a) && str().is_empty(c)) { + result = a; + return BR_DONE; + } zstring s1, s2; expr_ref_vector strs(m()); if (str().is_string(a, s1) && str().is_string(b, s2)) { From 1e580a7f12cb1cbba6aed4d3484bae4988e06806 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 22 Sep 2024 21:30:44 +0100 Subject: [PATCH 114/187] update to c++20, remove debug output Signed-off-by: Nikolaj Bjorner --- CMakeLists.txt | 2 +- scripts/mk_util.py | 10 +++++----- src/ast/converters/generic_model_converter.cpp | 9 +-------- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cdccb8e4b..4603ae1de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,7 +178,7 @@ include(${PROJECT_SOURCE_DIR}/cmake/z3_add_cxx_flag.cmake) ################################################################################ # C++ language version ################################################################################ -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) ################################################################################ diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 3e6da0b22..e0f029a3b 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2007,11 +2007,11 @@ class MLComponent(Component): src_dir = self.to_src_dir mk_dir(os.path.join(BUILD_DIR, self.sub_dir)) api_src = get_component(API_COMPONENT).to_src_dir - # remove /GL and -std=c++17; the ocaml tools don't like them. + # remove /GL and -std=c++20; the ocaml tools don't like them. if IS_WINDOWS: out.write('CXXFLAGS_OCAML=$(CXXFLAGS:/GL=)\n') else: - out.write('CXXFLAGS_OCAML=$(subst -std=c++17,,$(CXXFLAGS))\n') + out.write('CXXFLAGS_OCAML=$(subst -std=c++20,,$(CXXFLAGS))\n') substitutions = { 'VERSION': "{}.{}.{}.{}".format(VER_MAJOR, VER_MINOR, VER_BUILD, VER_TWEAK) } @@ -2500,7 +2500,7 @@ def mk_config(): config = open(os.path.join(BUILD_DIR, 'config.mk'), 'w') global CXX, CC, GMP, GUARD_CF, STATIC_BIN, GIT_HASH, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG, FPMATH_FLAGS, LOG_SYNC, SINGLE_THREADED, IS_ARCH_ARM64 if IS_WINDOWS: - CXXFLAGS = '/nologo /Zi /D WIN32 /D _WINDOWS /EHsc /GS /Gd /std:c++17' + CXXFLAGS = '/nologo /Zi /D WIN32 /D _WINDOWS /EHsc /GS /Gd /std:C++20' config.write( 'CC=cl\n' 'CXX=cl\n' @@ -2616,7 +2616,7 @@ def mk_config(): CPPFLAGS = '%s -D_MP_INTERNAL' % CPPFLAGS if GIT_HASH: CPPFLAGS = '%s -DZ3GITHASH=%s' % (CPPFLAGS, GIT_HASH) - CXXFLAGS = '%s -std=c++17' % CXXFLAGS + CXXFLAGS = '%s -std=C++20' % CXXFLAGS CXXFLAGS = '%s -fvisibility=hidden -fvisibility-inlines-hidden -c' % CXXFLAGS FPMATH = test_fpmath(CXX) CXXFLAGS = '%s %s' % (CXXFLAGS, FPMATH_FLAGS) @@ -2699,7 +2699,7 @@ def mk_config(): config.write('CC=%s\n' % CC) config.write('CXX=%s\n' % CXX) config.write('CXXFLAGS=%s %s\n' % (CPPFLAGS, CXXFLAGS)) - config.write('CFLAGS=%s %s\n' % (CPPFLAGS, CXXFLAGS.replace('-std=c++17', ''))) + config.write('CFLAGS=%s %s\n' % (CPPFLAGS, CXXFLAGS.replace('-std=C++20', ''))) config.write('EXAMP_DEBUG_FLAG=%s\n' % EXAMP_DEBUG_FLAG) config.write('CXX_OUT_FLAG=-o \n') config.write('C_OUT_FLAG=-o \n') diff --git a/src/ast/converters/generic_model_converter.cpp b/src/ast/converters/generic_model_converter.cpp index f64e798b5..03624c9de 100644 --- a/src/ast/converters/generic_model_converter.cpp +++ b/src/ast/converters/generic_model_converter.cpp @@ -156,7 +156,6 @@ void generic_model_converter::convert_initialize_value(expr* def, unsigned i, ve // el = value => c = false expr* c = nullptr, *th = nullptr, *el = nullptr; auto& [var, value] = var2value[i]; - verbose_stream() << "def " << mk_pp(def, m) << "\n"; if (m.is_ite(def, c, th, el)) { if (value == th) { var = c; @@ -175,13 +174,7 @@ void generic_model_converter::convert_initialize_value(expr* def, unsigned i, ve if (is_uninterp(def)) { var = def; return; - } - - bv_util bv(m); - if (bv.is_mkbv(def)) { - verbose_stream() << "def\n"; - } - + } } From 11218154391d5137ab35a3281fb6283587c08ba0 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 22 Sep 2024 21:45:10 +0100 Subject: [PATCH 115/187] Standardize C++20 flag across different platforms in build script --- scripts/mk_util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index e0f029a3b..0177dc564 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2500,7 +2500,7 @@ def mk_config(): config = open(os.path.join(BUILD_DIR, 'config.mk'), 'w') global CXX, CC, GMP, GUARD_CF, STATIC_BIN, GIT_HASH, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG, FPMATH_FLAGS, LOG_SYNC, SINGLE_THREADED, IS_ARCH_ARM64 if IS_WINDOWS: - CXXFLAGS = '/nologo /Zi /D WIN32 /D _WINDOWS /EHsc /GS /Gd /std:C++20' + CXXFLAGS = '/nologo /Zi /D WIN32 /D _WINDOWS /EHsc /GS /Gd /std:c++20' config.write( 'CC=cl\n' 'CXX=cl\n' @@ -2616,7 +2616,7 @@ def mk_config(): CPPFLAGS = '%s -D_MP_INTERNAL' % CPPFLAGS if GIT_HASH: CPPFLAGS = '%s -DZ3GITHASH=%s' % (CPPFLAGS, GIT_HASH) - CXXFLAGS = '%s -std=C++20' % CXXFLAGS + CXXFLAGS = '%s -std=c++20' % CXXFLAGS CXXFLAGS = '%s -fvisibility=hidden -fvisibility-inlines-hidden -c' % CXXFLAGS FPMATH = test_fpmath(CXX) CXXFLAGS = '%s %s' % (CXXFLAGS, FPMATH_FLAGS) @@ -2699,7 +2699,7 @@ def mk_config(): config.write('CC=%s\n' % CC) config.write('CXX=%s\n' % CXX) config.write('CXXFLAGS=%s %s\n' % (CPPFLAGS, CXXFLAGS)) - config.write('CFLAGS=%s %s\n' % (CPPFLAGS, CXXFLAGS.replace('-std=C++20', ''))) + config.write('CFLAGS=%s %s\n' % (CPPFLAGS, CXXFLAGS.replace('-std=c++20', ''))) config.write('EXAMP_DEBUG_FLAG=%s\n' % EXAMP_DEBUG_FLAG) config.write('CXX_OUT_FLAG=-o \n') config.write('C_OUT_FLAG=-o \n') From 22d9bfad358eefaa2f7aa490983463f6b0dd022f Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Mon, 23 Sep 2024 08:10:56 +0100 Subject: [PATCH 116/187] fix warning with iterators due to non-const comparator --- src/ast/rewriter/factor_equivs.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ast/rewriter/factor_equivs.h b/src/ast/rewriter/factor_equivs.h index 7c58f4abd..d4d566ed6 100644 --- a/src/ast/rewriter/factor_equivs.h +++ b/src/ast/rewriter/factor_equivs.h @@ -103,11 +103,10 @@ public: m_first = false; return *this; } - bool operator==(const iterator& o) { + bool operator!=(const iterator& o) const { SASSERT(&m_ouf == &o.m_ouf); - return m_first == o.m_first && m_curr_id == o.m_curr_id; + return m_first != o.m_first || m_curr_id != o.m_curr_id; } - bool operator!=(const iterator& o) {return !(*this == o);} }; iterator begin(OBJ*o) { @@ -152,11 +151,10 @@ public: m_ouf.m_uf.is_root(m_rootnb) != true); return *this; } - bool operator==(const equiv_iterator& o) { + bool operator!=(const equiv_iterator& o) const { SASSERT(&m_ouf == &o.m_ouf); - return m_rootnb == o.m_rootnb; + return m_rootnb != o.m_rootnb; } - bool operator!=(const equiv_iterator& o) {return !(*this == o);} }; equiv_iterator begin() {return equiv_iterator(*this, 0);} From a62fede64ba641cb6158f3bfdd22fd86f87d55f9 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Mon, 23 Sep 2024 08:17:58 +0100 Subject: [PATCH 117/187] remove a few default constructors --- src/ast/recfun_decl_plugin.cpp | 2 -- src/ast/seq_decl_plugin.h | 2 +- src/ast/sls/sls_valuation.h | 2 +- src/math/grobner/grobner.h | 4 ++-- src/math/lp/explanation.h | 2 +- src/math/lp/general_matrix.h | 2 +- src/math/lp/hnf_cutter.cpp | 3 +-- src/math/lp/implied_bound.h | 2 +- src/math/lp/indexed_vector.h | 2 +- src/math/lp/lar_term.h | 2 +- src/math/lp/nla_tangent_lemmas.h | 2 +- src/muz/base/dl_util.h | 1 - src/muz/spacer/spacer_unsat_core_plugin.h | 2 +- src/smt/fingerprints.h | 2 +- src/tactic/aig/aig.cpp | 1 - src/util/mpq.h | 6 +++--- 16 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/ast/recfun_decl_plugin.cpp b/src/ast/recfun_decl_plugin.cpp index 37e5d359e..a976ee3c9 100644 --- a/src/ast/recfun_decl_plugin.cpp +++ b/src/ast/recfun_decl_plugin.cpp @@ -170,8 +170,6 @@ namespace recfun { vector m_branches; public: - case_state() : m_reg(), m_branches() {} - bool empty() const { return m_branches.empty(); } branch pop_branch() { diff --git a/src/ast/seq_decl_plugin.h b/src/ast/seq_decl_plugin.h index c6550d33a..c08ed6f7a 100644 --- a/src/ast/seq_decl_plugin.h +++ b/src/ast/seq_decl_plugin.h @@ -446,7 +446,7 @@ public: /* Default constructor of invalid info. */ - info() {} + info() = default; /* Used for constructing either an invalid info that is only used to indicate uninitialized entry, or valid but unknown info value. diff --git a/src/ast/sls/sls_valuation.h b/src/ast/sls/sls_valuation.h index 66d7e0281..f10fd8f0b 100644 --- a/src/ast/sls/sls_valuation.h +++ b/src/ast/sls/sls_valuation.h @@ -33,7 +33,7 @@ namespace bv { unsigned nw = 0; unsigned mask = 0; - bvect() {} + bvect() = default; bvect(unsigned sz) : svector(sz, (unsigned)0) {} void set_bw(unsigned bw); diff --git a/src/math/grobner/grobner.h b/src/math/grobner/grobner.h index 6adffea7c..83c0d8a5e 100644 --- a/src/math/grobner/grobner.h +++ b/src/math/grobner/grobner.h @@ -48,7 +48,7 @@ public: friend class grobner; friend struct monomial_lt; - monomial() {} + monomial() = default; public: rational const & get_coeff() const { return m_coeff; } unsigned get_degree() const { return m_vars.size(); } @@ -63,7 +63,7 @@ public: ptr_vector m_monomials; //!< sorted monomials v_dependency * m_dep; //!< justification for the equality friend class grobner; - equation() {} + equation() = default; public: unsigned get_num_monomials() const { return m_monomials.size(); } monomial const * get_monomial(unsigned idx) const { return m_monomials[idx]; } diff --git a/src/math/lp/explanation.h b/src/math/lp/explanation.h index 960c5fb4a..9d8099c1e 100644 --- a/src/math/lp/explanation.h +++ b/src/math/lp/explanation.h @@ -29,7 +29,7 @@ class explanation { vector> m_vector; ci_set m_set; public: - explanation() {} + explanation() = default; template explanation(const T& t) { diff --git a/src/math/lp/general_matrix.h b/src/math/lp/general_matrix.h index fb1030e6b..e42f01ad7 100644 --- a/src/math/lp/general_matrix.h +++ b/src/math/lp/general_matrix.h @@ -180,7 +180,7 @@ public: m_column_permutation.transpose_from_left(j, k); } - general_matrix(){} + general_matrix() = default; general_matrix(unsigned n) : m_row_permutation(n), m_column_permutation(n), diff --git a/src/math/lp/hnf_cutter.cpp b/src/math/lp/hnf_cutter.cpp index b120b7aac..7f1af2aaa 100644 --- a/src/math/lp/hnf_cutter.cpp +++ b/src/math/lp/hnf_cutter.cpp @@ -19,8 +19,7 @@ namespace lp { lia(lia), lra(lia.lra), m_settings(lia.settings()), - m_abs_max(zero_of_type()), - m_var_register() {} + m_abs_max(zero_of_type()) {} bool hnf_cutter::is_full() const { return diff --git a/src/math/lp/implied_bound.h b/src/math/lp/implied_bound.h index 195ec0359..6d7fc54b9 100644 --- a/src/math/lp/implied_bound.h +++ b/src/math/lp/implied_bound.h @@ -44,7 +44,7 @@ class implied_bound { k = static_cast(k / 2); return k; } - implied_bound(){} + implied_bound() = default; implied_bound(const mpq & a, unsigned j, bool is_lower_bound, diff --git a/src/math/lp/indexed_vector.h b/src/math/lp/indexed_vector.h index 9f3119e9a..5740fdc21 100644 --- a/src/math/lp/indexed_vector.h +++ b/src/math/lp/indexed_vector.h @@ -76,7 +76,7 @@ public: } - indexed_vector() {} + indexed_vector() = default; void resize(unsigned data_size); unsigned data_size() const { diff --git a/src/math/lp/lar_term.h b/src/math/lp/lar_term.h index 6547377d3..87a0c282a 100644 --- a/src/math/lp/lar_term.h +++ b/src/math/lp/lar_term.h @@ -70,7 +70,7 @@ public: } } // constructors - lar_term() {} + lar_term() = default; lar_term(const vector>& coeffs) { for (auto const& p : coeffs) { add_monomial(p.first, p.second); diff --git a/src/math/lp/nla_tangent_lemmas.h b/src/math/lp/nla_tangent_lemmas.h index 1895b3fcb..daa45a41a 100644 --- a/src/math/lp/nla_tangent_lemmas.h +++ b/src/math/lp/nla_tangent_lemmas.h @@ -17,7 +17,7 @@ struct point { rational x; rational y; point(const rational& a, const rational& b): x(a), y(b) {} - point() {} + point() = default; inline point& operator*=(rational a) { x *= a; y *= a; diff --git a/src/muz/base/dl_util.h b/src/muz/base/dl_util.h index 401d8e816..ac1bed51e 100644 --- a/src/muz/base/dl_util.h +++ b/src/muz/base/dl_util.h @@ -347,7 +347,6 @@ namespace datalog { class rule_counter : public var_counter { public: - rule_counter(){} void count_rule_vars(const rule * r, int coef = 1); unsigned get_max_rule_var(const rule& r); }; diff --git a/src/muz/spacer/spacer_unsat_core_plugin.h b/src/muz/spacer/spacer_unsat_core_plugin.h index a7ea4c89b..b844cdd46 100644 --- a/src/muz/spacer/spacer_unsat_core_plugin.h +++ b/src/muz/spacer/spacer_unsat_core_plugin.h @@ -33,7 +33,7 @@ namespace spacer { unsat_core_plugin(unsat_core_learner& learner); virtual ~unsat_core_plugin() = default; virtual void compute_partial_core(proof* step) = 0; - virtual void finalize(){}; + virtual void finalize(){} unsat_core_learner& m_ctx; }; diff --git a/src/smt/fingerprints.h b/src/smt/fingerprints.h index a602f25cd..6a0bc1ccd 100644 --- a/src/smt/fingerprints.h +++ b/src/smt/fingerprints.h @@ -32,7 +32,7 @@ namespace smt { enode** m_args = nullptr; friend class fingerprint_set; - fingerprint() {} + fingerprint() = default; public: fingerprint(region & r, void * d, unsigned d_hash, expr* def, unsigned n, enode * const * args); void * get_data() const { return m_data; } diff --git a/src/tactic/aig/aig.cpp b/src/tactic/aig/aig.cpp index 433120b48..e59982969 100644 --- a/src/tactic/aig/aig.cpp +++ b/src/tactic/aig/aig.cpp @@ -50,7 +50,6 @@ struct aig { unsigned m_ref_count; aig_lit m_children[2]; unsigned m_mark:1; - aig() {} }; #if Z3DEBUG diff --git a/src/util/mpq.h b/src/util/mpq.h index 286c2758d..87ee5e17d 100644 --- a/src/util/mpq.h +++ b/src/util/mpq.h @@ -23,12 +23,12 @@ Revision History: class mpq { mpz m_num; - mpz m_den; + mpz m_den = 1; friend class mpq_manager; friend class mpq_manager; public: - mpq(int v):m_num(v), m_den(1) {} - mpq():m_den(1) {} + mpq(int v) : m_num(v) {} + mpq() = default; mpq(mpq &&) noexcept = default; mpq & operator=(mpq&&) = default; mpq & operator=(mpq const&) = delete; From 4b4a28239f9a06e9e10049f73f65e9859268b0a6 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 23 Sep 2024 11:45:11 +0100 Subject: [PATCH 118/187] Add const qualifiers to comparison operators and update iterator equality checks in various classes --- src/api/c++/z3++.h | 26 +++++++++++++------------- src/muz/rel/dl_base.h | 16 ++++++---------- src/sat/sat_solver/inc_sat_solver.cpp | 2 -- src/sat/tactic/sat_tactic.cpp | 1 - 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index bb148d712..85d5fce62 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -1603,10 +1603,10 @@ namespace z3 { unsigned i; public: iterator(expr& e, unsigned i): e(e), i(i) {} - bool operator==(iterator const& other) noexcept { + bool operator==(iterator const& other) const noexcept { return i == other.i; } - bool operator!=(iterator const& other) noexcept { + bool operator!=(iterator const& other) const noexcept { return i != other.i; } expr operator*() const { return e.arg(i); } @@ -1703,28 +1703,28 @@ namespace z3 { inline expr operator||(bool a, expr const & b) { return b.ctx().bool_val(a) || b; } - inline expr operator==(expr const & a, expr const & b) { + inline expr operator==(expr const & a, expr const & b) const { check_context(a, b); Z3_ast r = Z3_mk_eq(a.ctx(), a, b); a.check_error(); return expr(a.ctx(), r); } - inline expr operator==(expr const & a, int b) { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a == a.ctx().num_val(b, a.get_sort()); } + inline expr operator==(expr const & a, int b) const { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a == a.ctx().num_val(b, a.get_sort()); } inline expr operator==(int a, expr const & b) { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) == b; } - inline expr operator==(expr const & a, double b) { assert(a.is_fpa()); return a == a.ctx().fpa_val(b); } - inline expr operator==(double a, expr const & b) { assert(b.is_fpa()); return b.ctx().fpa_val(a) == b; } + inline expr operator==(expr const & a, double b) const { assert(a.is_fpa()); return a == a.ctx().fpa_val(b); } + inline expr operator==(double a, expr const & b) const { assert(b.is_fpa()); return b.ctx().fpa_val(a) == b; } - inline expr operator!=(expr const & a, expr const & b) { + inline expr operator!=(expr const & a, expr const & b) const { check_context(a, b); Z3_ast args[2] = { a, b }; Z3_ast r = Z3_mk_distinct(a.ctx(), 2, args); a.check_error(); return expr(a.ctx(), r); } - inline expr operator!=(expr const & a, int b) { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a != a.ctx().num_val(b, a.get_sort()); } - inline expr operator!=(int a, expr const & b) { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) != b; } - inline expr operator!=(expr const & a, double b) { assert(a.is_fpa()); return a != a.ctx().fpa_val(b); } - inline expr operator!=(double a, expr const & b) { assert(b.is_fpa()); return b.ctx().fpa_val(a) != b; } + inline expr operator!=(expr const & a, int b) const { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a != a.ctx().num_val(b, a.get_sort()); } + inline expr operator!=(int a, expr const & b) const { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) != b; } + inline expr operator!=(expr const & a, double b) const { assert(a.is_fpa()); return a != a.ctx().fpa_val(b); } + inline expr operator!=(double a, expr const & b) const { assert(b.is_fpa()); return b.ctx().fpa_val(a) != b; } inline expr operator+(expr const & a, expr const & b) { check_context(a, b); @@ -2957,10 +2957,10 @@ namespace z3 { expr_vector const * operator->() const { return &(operator*()); } expr_vector const& operator*() const noexcept { return m_cube; } - bool operator==(cube_iterator const& other) noexcept { + bool operator==(cube_iterator const& other) const noexcept { return other.m_end == m_end; }; - bool operator!=(cube_iterator const& other) noexcept { + bool operator!=(cube_iterator const& other) const noexcept { return other.m_end != m_end; }; diff --git a/src/muz/rel/dl_base.h b/src/muz/rel/dl_base.h index 158df4906..d1d946d10 100644 --- a/src/muz/rel/dl_base.h +++ b/src/muz/rel/dl_base.h @@ -1113,7 +1113,7 @@ namespace datalog { virtual row_interface & operator*() = 0; virtual void operator++() = 0; - virtual bool operator==(const iterator_core & it) { + virtual bool operator==(const iterator_core & it) const { //we worry about the equality operator only because of checking //the equality with the end() iterator return is_finished() && it.is_finished(); @@ -1142,7 +1142,7 @@ namespace datalog { virtual table_element operator*() = 0; virtual void operator++() = 0; - virtual bool operator==(const row_iterator_core & it) { + virtual bool operator==(const row_iterator_core & it) const { //we worry about the equality operator only because of checking //the equality with the end() iterator return is_finished() && it.is_finished(); @@ -1169,10 +1169,8 @@ namespace datalog { { return &(*(*m_core)); } iterator & operator++() { ++(*m_core); return *this; } - bool operator==(const iterator & it) - { return (*m_core)==(*it.m_core); } - bool operator!=(const iterator & it) - { return !operator==(it); } + bool operator==(const iterator & it) const { return (*m_core)==(*it.m_core); } + bool operator!=(const iterator & it) const { return !operator==(it); } }; class row_iterator { @@ -1187,10 +1185,8 @@ namespace datalog { { return *(*m_core); } row_iterator & operator++() { ++(*m_core); return *this; } - bool operator==(const row_iterator & it) - { return (*m_core)==(*it.m_core); } - bool operator!=(const row_iterator & it) - { return !operator==(it); } + bool operator==(const row_iterator & it) const { return (*m_core)==(*it.m_core); } + bool operator!=(const row_iterator & it) const { return !operator==(it); } }; virtual iterator begin() const = 0; diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index 19482c286..5e0d10918 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -179,8 +179,6 @@ public: void initialize_values() { if (m_mcs.back()) m_mcs.back()->convert_initialize_value(m_var2value); - if (m_mcs.back()) - m_mcs.back()->display(verbose_stream()); for (auto & [var, value] : m_var2value) { sat::bool_var b = m_map.to_bool_var(var); diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp index e997cbc2c..6a48bc8ed 100644 --- a/src/sat/tactic/sat_tactic.cpp +++ b/src/sat/tactic/sat_tactic.cpp @@ -265,7 +265,6 @@ public: } void user_propagate_initialize_value(expr* var, expr* value) override { - verbose_stream() << "initialize-value\n"; m_var2value.push_back({ expr_ref(var, m), expr_ref(value, m) }); } From 737c2208fad6c006a391897663adba71215f066f Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Mon, 23 Sep 2024 12:13:52 +0100 Subject: [PATCH 119/187] delete more default constructors reduces code size by 0.1% --- src/ackermannization/ackr_bound_probe.cpp | 2 -- src/ast/converters/model_converter.h | 3 --- src/ast/recfun_decl_plugin.cpp | 1 - src/ast/recfun_decl_plugin.h | 1 - src/ast/rewriter/var_subst.h | 2 +- src/ast/simplifiers/linear_equation.h | 2 +- src/cmd_context/cmd_context.h | 2 +- src/math/interval/mod_interval.h | 4 ++-- src/math/lp/factorization.h | 2 +- src/math/lp/indexed_value.h | 2 +- src/math/lp/nex.h | 2 +- src/math/lp/numeric_pair.h | 5 +---- src/math/lp/permutation_matrix.h | 2 +- src/math/lp/stacked_vector.h | 3 --- src/math/lp/static_matrix.h | 2 +- src/math/lp/var_eqs.h | 2 +- src/math/lp/var_register.h | 2 +- src/math/polynomial/polynomial.cpp | 14 ++++---------- .../polynomial/upolynomial_factorization_int.h | 2 +- src/math/simplex/model_based_opt.h | 6 +++--- src/muz/base/dl_util.cpp | 2 -- src/muz/fp/dl_cmds.cpp | 3 +-- src/muz/rel/dl_mk_simple_joins.cpp | 2 -- src/muz/rel/dl_relation_manager.cpp | 1 - src/muz/rel/dl_sieve_relation.h | 2 +- src/muz/rel/karr_relation.cpp | 2 -- src/muz/rel/udoc_relation.cpp | 4 ---- src/muz/spacer/spacer_arith_kernel.cpp | 2 -- src/muz/transforms/dl_mk_magic_sets.h | 2 +- src/opt/maxcore.cpp | 2 +- src/sat/sat_ddfw.h | 1 - src/sat/smt/arith_solver.h | 8 -------- src/sat/smt/q_mam.h | 2 +- src/smt/params/theory_array_params.h | 2 -- src/smt/theory_lra.cpp | 11 ----------- src/tactic/core/pb_preprocess_tactic.cpp | 2 +- src/util/array.h | 8 ++++---- src/util/buffer.h | 2 +- src/util/inf_rational.h | 2 +- src/util/sat_literal.h | 3 +-- src/util/stacked_value.h | 2 +- 41 files changed, 35 insertions(+), 91 deletions(-) diff --git a/src/ackermannization/ackr_bound_probe.cpp b/src/ackermannization/ackr_bound_probe.cpp index b518adccc..48a54543f 100644 --- a/src/ackermannization/ackr_bound_probe.cpp +++ b/src/ackermannization/ackr_bound_probe.cpp @@ -60,8 +60,6 @@ class ackr_bound_probe : public probe { }; public: - ackr_bound_probe() {} - result operator()(goal const & g) override { proc p(g.m()); unsigned sz = g.size(); diff --git a/src/ast/converters/model_converter.h b/src/ast/converters/model_converter.h index 354b51854..baf5e422d 100644 --- a/src/ast/converters/model_converter.h +++ b/src/ast/converters/model_converter.h @@ -71,9 +71,6 @@ protected: void display_del(std::ostream& out, func_decl* f) const; void display_add(std::ostream& out, ast_manager& m); public: - - model_converter() {} - void set_completion(bool f) { m_completion = f; } virtual void operator()(model_ref & m) = 0; diff --git a/src/ast/recfun_decl_plugin.cpp b/src/ast/recfun_decl_plugin.cpp index a976ee3c9..5f2534a51 100644 --- a/src/ast/recfun_decl_plugin.cpp +++ b/src/ast/recfun_decl_plugin.cpp @@ -417,7 +417,6 @@ namespace recfun { } namespace decl { - plugin::plugin() : decl_plugin(), m_defs(), m_case_defs() {} plugin::~plugin() { finalize(); } void plugin::finalize() { diff --git a/src/ast/recfun_decl_plugin.h b/src/ast/recfun_decl_plugin.h index e078c7ef9..73e2b5244 100644 --- a/src/ast/recfun_decl_plugin.h +++ b/src/ast/recfun_decl_plugin.h @@ -173,7 +173,6 @@ namespace recfun { void compute_scores(expr* e, obj_map& scores); public: - plugin(); ~plugin() override; void finalize() override; diff --git a/src/ast/rewriter/var_subst.h b/src/ast/rewriter/var_subst.h index e9d39740d..aa905cb0e 100644 --- a/src/ast/rewriter/var_subst.h +++ b/src/ast/rewriter/var_subst.h @@ -94,7 +94,7 @@ class expr_free_vars { ptr_vector m_sorts; ptr_vector m_todo; public: - expr_free_vars() {} + expr_free_vars() = default; expr_free_vars(expr* e) { (*this)(e); } void reset(); void operator()(expr* e); diff --git a/src/ast/simplifiers/linear_equation.h b/src/ast/simplifiers/linear_equation.h index 5220a1e46..662c8c9fc 100644 --- a/src/ast/simplifiers/linear_equation.h +++ b/src/ast/simplifiers/linear_equation.h @@ -35,7 +35,7 @@ private: mpz * m_as; // precise coefficients double * m_approx_as; // approximated coefficients var * m_xs; // var ids - linear_equation() {} + linear_equation() = default; public: unsigned size() const { return m_size; } mpz const & a(unsigned idx) const { SASSERT(idx < m_size); return m_as[idx]; } diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index d113eb881..6dc60c9dd 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -47,7 +47,7 @@ class func_decls { bool signatures_collide(func_decl* f, func_decl* g) const; bool signatures_collide(unsigned n, sort*const* domain, sort* range, func_decl* g) const; public: - func_decls() {} + func_decls() = default; func_decls(ast_manager & m, func_decl * f); void finalize(ast_manager & m); bool contains(func_decl * f) const; diff --git a/src/math/interval/mod_interval.h b/src/math/interval/mod_interval.h index ed189fe7b..28b69b003 100644 --- a/src/math/interval/mod_interval.h +++ b/src/math/interval/mod_interval.h @@ -26,7 +26,7 @@ namespace bv { bool tight = true; interval_tpl(T const& l, T const& h, unsigned sz, bool tight = false): l(l), h(h), sz(sz), tight(tight) {} - interval_tpl() {} + interval_tpl() = default; bool invariant() const { return @@ -167,7 +167,7 @@ namespace bv { iinterval i; rinterval r; - interval() {} + interval() = default; interval(rational const& l, rational const& h, unsigned sz, bool tight = false) { if (sz <= 64) { diff --git a/src/math/lp/factorization.h b/src/math/lp/factorization.h index e1096a75f..be3a024e3 100644 --- a/src/math/lp/factorization.h +++ b/src/math/lp/factorization.h @@ -24,7 +24,7 @@ class factor { factor_type m_type = factor_type::VAR; bool m_sign = false; public: - factor() { } + factor() = default; explicit factor(lpvar v, factor_type t) : m_var(v), m_type(t) {} unsigned var() const { return m_var; } factor_type type() const { return m_type; } diff --git a/src/math/lp/indexed_value.h b/src/math/lp/indexed_value.h index 92d8f2adf..c0194670d 100644 --- a/src/math/lp/indexed_value.h +++ b/src/math/lp/indexed_value.h @@ -29,7 +29,7 @@ public: // m_other is the offset of the corresponding element in its vector : for a row element it points to the column element offset, // for a column element it points to the row element offset unsigned m_other; - indexed_value() {} + indexed_value() = default; indexed_value(T v, unsigned i, unsigned other) : m_value(v), m_index(i), m_other(other) { diff --git a/src/math/lp/nex.h b/src/math/lp/nex.h index e4087a407..7217374d5 100644 --- a/src/math/lp/nex.h +++ b/src/math/lp/nex.h @@ -92,7 +92,7 @@ public: virtual const rational& coeff() const { return rational::one(); } #ifdef Z3DEBUG - virtual void sort() {}; + virtual void sort() {} #endif bool virtual is_linear() const = 0; }; diff --git a/src/math/lp/numeric_pair.h b/src/math/lp/numeric_pair.h index 93780f7be..dbebbf998 100644 --- a/src/math/lp/numeric_pair.h +++ b/src/math/lp/numeric_pair.h @@ -116,10 +116,7 @@ template struct numeric_pair { T x; T y; - // empty constructor - numeric_pair() {} - // another constructor - + numeric_pair() = default; numeric_pair(T xp, T yp) : x(xp), y(yp) {} template diff --git a/src/math/lp/permutation_matrix.h b/src/math/lp/permutation_matrix.h index a3fff4f7f..df0897dbe 100644 --- a/src/math/lp/permutation_matrix.h +++ b/src/math/lp/permutation_matrix.h @@ -52,7 +52,7 @@ class permutation_matrix }; public: - permutation_matrix() {} + permutation_matrix() = default; permutation_matrix(unsigned length); permutation_matrix(unsigned length, vector const & values); diff --git a/src/math/lp/stacked_vector.h b/src/math/lp/stacked_vector.h index ecd61eb10..69ff99263 100644 --- a/src/math/lp/stacked_vector.h +++ b/src/math/lp/stacked_vector.h @@ -98,9 +98,6 @@ private: } } public: - - stacked_vector() { } - ref operator[] (unsigned a) { return ref(*this, a); } diff --git a/src/math/lp/static_matrix.h b/src/math/lp/static_matrix.h index 42dd476b5..5bbd000ca 100644 --- a/src/math/lp/static_matrix.h +++ b/src/math/lp/static_matrix.h @@ -105,7 +105,7 @@ public: void init_row_columns(unsigned m, unsigned n); // constructor with no parameters - static_matrix() {} + static_matrix() = default; // constructor static_matrix(unsigned m, unsigned n): m_vector_of_row_offsets(n, -1) { diff --git a/src/math/lp/var_eqs.h b/src/math/lp/var_eqs.h index a639a9a5e..56c39c460 100644 --- a/src/math/lp/var_eqs.h +++ b/src/math/lp/var_eqs.h @@ -81,7 +81,7 @@ class var_eqs { mutable stats m_stats; public: - var_eqs(): m_merge_handler(nullptr), m_uf(*this), m_stack() {} + var_eqs(): m_merge_handler(nullptr), m_uf(*this) {} /** \brief push a scope */ void push() { diff --git a/src/math/lp/var_register.h b/src/math/lp/var_register.h index bd7e6efe8..84ac8236d 100644 --- a/src/math/lp/var_register.h +++ b/src/math/lp/var_register.h @@ -27,7 +27,7 @@ class ext_var_info { bool m_is_integer; std::string m_name; public: - ext_var_info() {} + ext_var_info() = default; ext_var_info(unsigned j): ext_var_info(j, true) {} ext_var_info(unsigned j , bool is_int) : m_external_j(j), m_is_integer(is_int) {} ext_var_info(unsigned j , bool is_int, std::string name) : m_external_j(j), m_is_integer(is_int), m_name(name) {} diff --git a/src/math/polynomial/polynomial.cpp b/src/math/polynomial/polynomial.cpp index 74c5e05d7..76f717da0 100644 --- a/src/math/polynomial/polynomial.cpp +++ b/src/math/polynomial/polynomial.cpp @@ -91,7 +91,7 @@ namespace polynomial { */ class power : public std::pair { public: - power():std::pair() {} + power() = default; power(var v, unsigned d):std::pair(v, d) {} var get_var() const { return first; } unsigned degree() const { return second; } @@ -1895,7 +1895,7 @@ namespace polynomial { Invoke add(...), addmul(...) several times, and then invoke mk() to obtain the final polynomial. */ class som_buffer { - imp * m_owner; + imp * m_owner = nullptr; monomial2pos m_m2pos; numeral_vector m_tmp_as; monomial_vector m_tmp_ms; @@ -1939,8 +1939,6 @@ namespace polynomial { } public: - som_buffer():m_owner(nullptr) {} - void reset() { if (empty()) return; @@ -2236,12 +2234,10 @@ namespace polynomial { In this buffer, each monomial can be added at most once. */ class cheap_som_buffer { - imp * m_owner; + imp * m_owner = nullptr; numeral_vector m_tmp_as; monomial_vector m_tmp_ms; public: - cheap_som_buffer():m_owner(nullptr) {} - void set_owner(imp * o) { m_owner = o; } bool empty() const { return m_tmp_ms.empty(); } @@ -3072,11 +3068,9 @@ namespace polynomial { } class newton_interpolator_vector { - imp * m_imp; + imp * m_imp = nullptr; ptr_vector m_data; public: - newton_interpolator_vector():m_imp(nullptr) {} - ~newton_interpolator_vector() { flush(); } diff --git a/src/math/polynomial/upolynomial_factorization_int.h b/src/math/polynomial/upolynomial_factorization_int.h index a65e5ee62..f47610b65 100644 --- a/src/math/polynomial/upolynomial_factorization_int.h +++ b/src/math/polynomial/upolynomial_factorization_int.h @@ -64,7 +64,7 @@ namespace upolynomial { public: - factorization_degree_set() { } + factorization_degree_set() = default; factorization_degree_set(zp_factors const & factors) { diff --git a/src/math/simplex/model_based_opt.h b/src/math/simplex/model_based_opt.h index 35516283d..891df598b 100644 --- a/src/math/simplex/model_based_opt.h +++ b/src/math/simplex/model_based_opt.h @@ -43,7 +43,7 @@ namespace opt { struct var { unsigned m_id { 0 }; rational m_coeff; - var() {} + var() = default; var(unsigned id, rational const& c): m_id(id), m_coeff(c) {} struct compare { bool operator()(var x, var y) { @@ -76,11 +76,11 @@ namespace opt { // A definition is a linear term of the form (vars + coeff) / div struct def { - def(): m_div(1) {} + def() = default; def(row const& r, unsigned x); vector m_vars; rational m_coeff; - rational m_div; + rational m_div{1}; def operator+(def const& other) const; def operator/(unsigned n) const { return *this / rational(n); } def operator/(rational const& n) const; diff --git a/src/muz/base/dl_util.cpp b/src/muz/base/dl_util.cpp index 03a8f1c99..7b01c2b3f 100644 --- a/src/muz/base/dl_util.cpp +++ b/src/muz/base/dl_util.cpp @@ -393,8 +393,6 @@ namespace datalog { class skip_model_converter : public model_converter { public: - skip_model_converter() {} - model_converter * translate(ast_translation & translator) override { return alloc(skip_model_converter); } diff --git a/src/muz/fp/dl_cmds.cpp b/src/muz/fp/dl_cmds.cpp index f40400167..508b79ace 100644 --- a/src/muz/fp/dl_cmds.cpp +++ b/src/muz/fp/dl_cmds.cpp @@ -56,8 +56,7 @@ struct dl_context { m_cmd(ctx), m_collected_cmds(collected_cmds), m_ref_count(0), - m_decl_plugin(nullptr), - m_trail() {} + m_decl_plugin(nullptr) {} void inc_ref() { ++m_ref_count; diff --git a/src/muz/rel/dl_mk_simple_joins.cpp b/src/muz/rel/dl_mk_simple_joins.cpp index 37fd3ef36..f60760fab 100644 --- a/src/muz/rel/dl_mk_simple_joins.cpp +++ b/src/muz/rel/dl_mk_simple_joins.cpp @@ -54,8 +54,6 @@ namespace datalog { var_idx_set m_all_nonlocal_vars; rule_vector m_rules; - pair_info() {} - pair_info & operator=(const pair_info &) = delete; bool can_be_joined() const { return m_consumers > 0; diff --git a/src/muz/rel/dl_relation_manager.cpp b/src/muz/rel/dl_relation_manager.cpp index 8de25c8f3..5e96dc487 100644 --- a/src/muz/rel/dl_relation_manager.cpp +++ b/src/muz/rel/dl_relation_manager.cpp @@ -1043,7 +1043,6 @@ namespace datalog { class relation_manager::null_signature_table_project_fn : public table_transformer_fn { const table_signature m_empty_sig; public: - null_signature_table_project_fn() : m_empty_sig() {} table_base * operator()(const table_base & t) override { relation_manager & m = t.get_plugin().get_manager(); table_base * res = m.mk_empty_table(m_empty_sig); diff --git a/src/muz/rel/dl_sieve_relation.h b/src/muz/rel/dl_sieve_relation.h index 72c246e99..0166bec98 100644 --- a/src/muz/rel/dl_sieve_relation.h +++ b/src/muz/rel/dl_sieve_relation.h @@ -36,7 +36,7 @@ namespace datalog { /** Create uninitialized rel_spec. */ - rel_spec() {} + rel_spec() = default; /** \c inner_kind==null_family_id means we will not specify a relation kind when requesting the relation object from the relation_manager. diff --git a/src/muz/rel/karr_relation.cpp b/src/muz/rel/karr_relation.cpp index d01056960..7a2ba5179 100644 --- a/src/muz/rel/karr_relation.cpp +++ b/src/muz/rel/karr_relation.cpp @@ -674,8 +674,6 @@ namespace datalog { class karr_relation_plugin::union_fn : public relation_union_fn { public: - union_fn() {} - void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) override { karr_relation& r = get(_r); diff --git a/src/muz/rel/udoc_relation.cpp b/src/muz/rel/udoc_relation.cpp index 2b28a6c82..8240f7f9e 100644 --- a/src/muz/rel/udoc_relation.cpp +++ b/src/muz/rel/udoc_relation.cpp @@ -491,8 +491,6 @@ namespace datalog { } class udoc_plugin::union_fn : public relation_union_fn { public: - union_fn() {} - void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) override { TRACE("doc", _r.display(tout << "dst:\n"); _src.display(tout << "src:\n");); udoc_relation& r = get(_r); @@ -1040,8 +1038,6 @@ namespace datalog { class udoc_plugin::join_project_and_fn : public relation_join_fn { public: - join_project_and_fn() {} - relation_base* operator()(relation_base const& t1, relation_base const& t2) override { udoc_relation *result = get(t1.clone()); result->get_udoc().intersect(result->get_dm(), get(t2).get_udoc()); diff --git a/src/muz/spacer/spacer_arith_kernel.cpp b/src/muz/spacer/spacer_arith_kernel.cpp index fdcb6b0d6..25aff0273 100644 --- a/src/muz/spacer/spacer_arith_kernel.cpp +++ b/src/muz/spacer/spacer_arith_kernel.cpp @@ -45,8 +45,6 @@ bool spacer_arith_kernel::compute_kernel() { namespace { class simplex_arith_kernel_plugin : public spacer_arith_kernel::plugin { public: - simplex_arith_kernel_plugin() {} - bool compute_kernel(const spacer_matrix &in, spacer_matrix &out, vector &basics) override { using qmatrix = simplex::sparse_matrix; diff --git a/src/muz/transforms/dl_mk_magic_sets.h b/src/muz/transforms/dl_mk_magic_sets.h index aa4c30274..3a8a92580 100644 --- a/src/muz/transforms/dl_mk_magic_sets.h +++ b/src/muz/transforms/dl_mk_magic_sets.h @@ -65,7 +65,7 @@ namespace datalog { func_decl * m_pred; adornment m_adornment; - adornment_desc() {} + adornment_desc() = default; adornment_desc(func_decl * pred) : m_pred(pred) {} adornment_desc(func_decl * pred, const adornment & a) : m_pred(pred), m_adornment(a) {} diff --git a/src/opt/maxcore.cpp b/src/opt/maxcore.cpp index d29da86f7..84906cbaa 100644 --- a/src/opt/maxcore.cpp +++ b/src/opt/maxcore.cpp @@ -777,7 +777,7 @@ public: ptr_vector es; unsigned k = 0; rational weight; - bound_info() {} + bound_info() = default; bound_info(ptr_vector const& es, unsigned k, rational const& weight): es(es), k(k), weight(weight) {} bound_info(expr_ref_vector const& es, unsigned k, rational const& weight): diff --git a/src/sat/sat_ddfw.h b/src/sat/sat_ddfw.h index ff86e9b8c..3454d47da 100644 --- a/src/sat/sat_ddfw.h +++ b/src/sat/sat_ddfw.h @@ -95,7 +95,6 @@ namespace sat { }; struct var_info { - var_info() {} bool m_value = false; double m_reward = 0; double m_last_reward = 0; diff --git a/src/sat/smt/arith_solver.h b/src/sat/smt/arith_solver.h index f940af8b4..d4850e67d 100644 --- a/src/sat/smt/arith_solver.h +++ b/src/sat/smt/arith_solver.h @@ -428,19 +428,11 @@ namespace arith { * Facility to put a small box around integer variables used in branch and bounds. */ - struct bound_info { - rational m_offset; - unsigned m_range; - bound_info() {} - bound_info(rational const& o, unsigned r) :m_offset(o), m_range(r) {} - }; unsigned m_bounded_range_idx; // current size of bounded range. literal m_bounded_range_lit; // current bounded range literal expr_ref_vector m_bound_terms; // predicates used for bounds expr_ref m_bound_predicate; - obj_map m_predicate2term; - obj_map m_term2bound_info; bool m_model_is_initialized = false; unsigned small_lemma_size() const { return get_config().m_arith_small_lemma_size; } diff --git a/src/sat/smt/q_mam.h b/src/sat/smt/q_mam.h index 9fc6d18f1..e642f9e44 100644 --- a/src/sat/smt/q_mam.h +++ b/src/sat/smt/q_mam.h @@ -39,7 +39,7 @@ namespace q { class mam { friend class mam_impl; - mam() {} + mam() = default; public: diff --git a/src/smt/params/theory_array_params.h b/src/smt/params/theory_array_params.h index b6da32ba5..8c56093a8 100644 --- a/src/smt/params/theory_array_params.h +++ b/src/smt/params/theory_array_params.h @@ -41,8 +41,6 @@ struct theory_array_params { unsigned m_array_lazy_ieq_delay = 10; bool m_array_fake_support = false; // fake support for all array operations to pretend they are satisfiable. - theory_array_params() {} - void updt_params(params_ref const & _p); void display(std::ostream & out) const; diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 6de623bb7..135744f02 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -3806,19 +3806,10 @@ public: * Facility to put a small box around integer variables used in branch and bounds. */ - struct bound_info { - rational m_offset; - unsigned m_range; - bound_info() {} - bound_info(rational const& o, unsigned r):m_offset(o), m_range(r) {} - }; unsigned m_bounded_range_idx; // current size of bounded range. literal m_bounded_range_lit; // current bounded range literal expr_ref_vector m_bound_terms; // predicates used for bounds expr_ref m_bound_predicate; - - obj_map m_predicate2term; - obj_map m_term2bound_info; unsigned init_range() const { return 5; } unsigned max_range() const { return 20; } @@ -3828,8 +3819,6 @@ public: m_bounded_range_lit = null_literal; m_bound_terms.reset(); m_bound_predicate = nullptr; - m_predicate2term.reset(); - m_term2bound_info.reset(); } diff --git a/src/tactic/core/pb_preprocess_tactic.cpp b/src/tactic/core/pb_preprocess_tactic.cpp index 05ed6eee9..2d82a12a1 100644 --- a/src/tactic/core/pb_preprocess_tactic.cpp +++ b/src/tactic/core/pb_preprocess_tactic.cpp @@ -25,7 +25,7 @@ Author: #include "ast/ast_pp.h" class pb_preprocess_tactic : public tactic { - struct rec { unsigned_vector pos, neg; rec() { } }; + struct rec { unsigned_vector pos, neg; }; typedef obj_map var_map; ast_manager& m; expr_ref_vector m_trail; diff --git a/src/util/array.h b/src/util/array.h index 2954035f6..d844692ef 100644 --- a/src/util/array.h +++ b/src/util/array.h @@ -26,7 +26,7 @@ public: private: #define ARRAY_SIZE_IDX -1 - T * m_data; + T * m_data = nullptr; void destroy_elements() { iterator it = begin(); iterator e = end(); @@ -71,7 +71,7 @@ public: typedef T * iterator; typedef const T * const_iterator; - array():m_data(nullptr) {} + array() = default; /** \brief Store the array in the given chunk of memory (mem). @@ -193,7 +193,7 @@ public: template class ptr_array : public array { public: - ptr_array() {} + ptr_array() = default; ptr_array(void * mem, unsigned sz, T * const * vs):array(mem, sz, vs) {} template ptr_array(Allocator & a, unsigned sz, T * const * vs):array(a, sz, vs) {} @@ -205,7 +205,7 @@ public: template class sarray : public array { public: - sarray() {} + sarray() = default; sarray(void * mem, unsigned sz, T const * vs):array(mem, sz, vs) {} template sarray(Allocator & a, unsigned sz, T const * vs):array(a, sz, vs) {} diff --git a/src/util/buffer.h b/src/util/buffer.h index 3ca597af2..b71717fe6 100644 --- a/src/util/buffer.h +++ b/src/util/buffer.h @@ -275,6 +275,6 @@ public: template class sbuffer : public buffer { public: - sbuffer(): buffer() {} + sbuffer() = default; sbuffer(unsigned sz, const T& elem) : buffer(sz,elem) {} }; diff --git a/src/util/inf_rational.h b/src/util/inf_rational.h index 2d7963ff0..7e8487d9d 100644 --- a/src/util/inf_rational.h +++ b/src/util/inf_rational.h @@ -65,7 +65,7 @@ class inf_rational { return s; } - inf_rational() {} + inf_rational() = default; explicit inf_rational(int n): m_first(rational(n)), diff --git a/src/util/sat_literal.h b/src/util/sat_literal.h index 58088e628..61ee5f657 100644 --- a/src/util/sat_literal.h +++ b/src/util/sat_literal.h @@ -119,7 +119,7 @@ namespace sat { literal_set(literal_vector const& v) { for (unsigned i = 0; i < v.size(); ++i) insert(v[i]); } - literal_set() {} + literal_set() = default; literal_vector to_vector() const { literal_vector result; for (literal lit : *this) result.push_back(lit); @@ -146,7 +146,6 @@ namespace sat { literal operator*() const { return to_literal(*m_it); } iterator& operator++() { ++m_it; return *this; } iterator operator++(int) { iterator tmp = *this; ++m_it; return tmp; } - bool operator==(iterator const& it) const { return m_it == it.m_it; } bool operator!=(iterator const& it) const { return m_it != it.m_it; } }; iterator begin() const { return iterator(m_set.begin()); } diff --git a/src/util/stacked_value.h b/src/util/stacked_value.h index 89be6fa53..a3a0d933b 100644 --- a/src/util/stacked_value.h +++ b/src/util/stacked_value.h @@ -52,7 +52,7 @@ public: } } - stacked_value() {} + stacked_value() = default; stacked_value(const T& m) { m_value = m; } From 499ed5d8445607c03c4bd11e5cba27a91dfec578 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Mon, 23 Sep 2024 12:57:54 +0100 Subject: [PATCH 120/187] remove unneeded iterator functions --- src/ast/euf/euf_ac_plugin.h | 3 +-- src/ast/euf/euf_enode.h | 6 ++---- src/ast/for_each_expr.cpp | 24 ++++++++---------------- src/ast/for_each_expr.h | 2 -- src/math/dd/dd_pdd.h | 4 +--- src/math/hilbert/heap_trie.h | 1 - src/math/hilbert/hilbert_basis.cpp | 2 -- src/math/hilbert/hilbert_basis.h | 1 - src/math/lp/emonics.h | 7 ++----- src/math/lp/explanation.h | 5 ++--- src/math/lp/factorization.cpp | 12 +++++------- src/math/lp/factorization.h | 3 +-- src/math/lp/lar_constraints.h | 2 -- src/math/lp/lar_term.h | 3 +-- src/math/lp/var_eqs.h | 1 - src/math/simplex/bit_matrix.h | 2 -- src/math/simplex/sparse_matrix.h | 2 -- src/muz/rel/dl_table.cpp | 2 +- src/qe/qe.h | 1 - src/sat/dimacs.h | 1 - src/sat/sat_clause.h | 1 - src/sat/smt/pb_constraint.h | 1 - src/smt/smt_enode.h | 3 +-- src/util/approx_set.h | 4 ---- src/util/bit_vector.h | 1 - src/util/chashtable.h | 1 - src/util/distribution.h | 1 - src/util/dlist.h | 7 +------ src/util/list.h | 1 - src/util/scoped_vector.h | 3 +-- src/util/uint_set.h | 1 - src/util/vector.h | 6 ------ 32 files changed, 27 insertions(+), 87 deletions(-) diff --git a/src/ast/euf/euf_ac_plugin.h b/src/ast/euf/euf_ac_plugin.h index 2963c1f8b..d55d7dbb4 100644 --- a/src/ast/euf/euf_ac_plugin.h +++ b/src/ast/euf/euf_ac_plugin.h @@ -61,8 +61,7 @@ namespace euf { node* operator*() { return m_first; } iterator& operator++() { if (!m_last) m_last = m_first; m_first = m_first->next; return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } - bool operator==(iterator const& other) const { return m_last == other.m_last && m_first == other.m_first; } - bool operator!=(iterator const& other) const { return !(*this == other); } + bool operator!=(iterator const& other) const { return m_last != other.m_last || m_first != other.m_first; } }; equiv(node& _n) :n(_n) {} equiv(node* _n) :n(*_n) {} diff --git a/src/ast/euf/euf_enode.h b/src/ast/euf/euf_enode.h index 50a7ce479..af22a5b2c 100644 --- a/src/ast/euf/euf_enode.h +++ b/src/ast/euf/euf_enode.h @@ -280,8 +280,7 @@ namespace euf { enode* operator*() { return m_first; } iterator& operator++() { if (!m_last) m_last = m_first; m_first = m_first->m_next; return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } - bool operator==(iterator const& other) const { return m_last == other.m_last && m_first == other.m_first; } - bool operator!=(iterator const& other) const { return !(*this == other); } + bool operator!=(iterator const& other) const { return m_last != other.m_last || m_first != other.m_first; } }; enode_class(enode & _n):n(_n) {} enode_class(enode * _n):n(*_n) {} @@ -300,8 +299,7 @@ namespace euf { th_var_list const& operator*() { return *m_th_vars; } iterator& operator++() { m_th_vars = m_th_vars->get_next(); return *this; } iterator operator++(int) { iterator tmp = *this; ++* this; return tmp; } - bool operator==(iterator const& other) const { return m_th_vars == other.m_th_vars; } - bool operator!=(iterator const& other) const { return !(*this == other); } + bool operator!=(iterator const& other) const { return m_th_vars != other.m_th_vars; } }; enode_th_vars(enode& _n) :n(_n) {} enode_th_vars(enode* _n) :n(*_n) {} diff --git a/src/ast/for_each_expr.cpp b/src/ast/for_each_expr.cpp index 8feb217db..ebad5760c 100644 --- a/src/ast/for_each_expr.cpp +++ b/src/ast/for_each_expr.cpp @@ -146,20 +146,16 @@ subterms::iterator& subterms::iterator::operator++() { return *this; } -bool subterms::iterator::operator==(iterator const& other) const { +bool subterms::iterator::operator!=(iterator const& other) const { // ignore state of visited if (other.m_esp->size() != m_esp->size()) { - return false; + return true; } for (unsigned i = m_esp->size(); i-- > 0; ) { if (m_esp->get(i) != other.m_esp->get(i)) - return false; + return true; } - return true; -} - -bool subterms::iterator::operator!=(iterator const& other) const { - return !(*this == other); + return false; } @@ -216,18 +212,14 @@ subterms_postorder::iterator& subterms_postorder::iterator::operator++() { return *this; } -bool subterms_postorder::iterator::operator==(iterator const& other) const { +bool subterms_postorder::iterator::operator!=(iterator const& other) const { // ignore state of visited if (other.m_es.size() != m_es.size()) { - return false; + return true; } for (unsigned i = m_es.size(); i-- > 0; ) { if (m_es.get(i) != other.m_es.get(i)) - return false; + return true; } - return true; -} - -bool subterms_postorder::iterator::operator!=(iterator const& other) const { - return !(*this == other); + return false; } diff --git a/src/ast/for_each_expr.h b/src/ast/for_each_expr.h index 77b01e939..97a171755 100644 --- a/src/ast/for_each_expr.h +++ b/src/ast/for_each_expr.h @@ -190,7 +190,6 @@ public: expr* operator*(); iterator operator++(int); iterator& operator++(); - bool operator==(iterator const& other) const; bool operator!=(iterator const& other) const; }; @@ -220,7 +219,6 @@ public: expr* operator*(); iterator operator++(int); iterator& operator++(); - bool operator==(iterator const& other) const; bool operator!=(iterator const& other) const; }; static subterms_postorder all(expr_ref_vector const& es) { return subterms_postorder(es, true); } diff --git a/src/math/dd/dd_pdd.h b/src/math/dd/dd_pdd.h index fa545c06e..4fe208429 100644 --- a/src/math/dd/dd_pdd.h +++ b/src/math/dd/dd_pdd.h @@ -571,8 +571,7 @@ namespace dd { pdd_monomial const* operator->() const { return &m_mono; } pdd_iterator& operator++() { next(); return *this; } pdd_iterator operator++(int) { auto tmp = *this; next(); return tmp; } - bool operator==(pdd_iterator const& other) const { return m_nodes == other.m_nodes; } - bool operator!=(pdd_iterator const& other) const { return !operator==(other); } + bool operator!=(pdd_iterator const& other) const { return m_nodes != other.m_nodes; } }; class pdd_linear_iterator { @@ -591,7 +590,6 @@ namespace dd { pointer operator->() const { return &m_mono; } pdd_linear_iterator& operator++() { next(); return *this; } pdd_linear_iterator operator++(int) { auto tmp = *this; next(); return tmp; } - bool operator==(pdd_linear_iterator const& other) const { return m_next == other.m_next; } bool operator!=(pdd_linear_iterator const& other) const { return m_next != other.m_next; } }; diff --git a/src/math/hilbert/heap_trie.h b/src/math/hilbert/heap_trie.h index b492fb7ee..3feb68ba6 100644 --- a/src/math/hilbert/heap_trie.h +++ b/src/math/hilbert/heap_trie.h @@ -369,7 +369,6 @@ public: } iterator& operator++() { fwd(); return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } - bool operator==(iterator const& it) const {return m_count == it.m_count; } bool operator!=(iterator const& it) const {return m_count != it.m_count; } private: diff --git a/src/math/hilbert/hilbert_basis.cpp b/src/math/hilbert/hilbert_basis.cpp index 586027103..308adf54f 100644 --- a/src/math/hilbert/hilbert_basis.cpp +++ b/src/math/hilbert/hilbert_basis.cpp @@ -455,7 +455,6 @@ public: offset_t operator*() const { return p.m_passive[m_idx]; } iterator& operator++() { ++m_idx; fwd(); return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } - bool operator==(iterator const& it) const {return m_idx == it.m_idx; } bool operator!=(iterator const& it) const {return m_idx != it.m_idx; } }; @@ -614,7 +613,6 @@ public: offset_t sos() const { return (p.hb.vec(pas()).weight().is_pos()?p.m_neg_sos:p.m_pos_sos)[p.m_psos[m_idx]]; } iterator& operator++() { ++m_idx; fwd(); return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } - bool operator==(iterator const& it) const {return m_idx == it.m_idx; } bool operator!=(iterator const& it) const {return m_idx != it.m_idx; } }; diff --git a/src/math/hilbert/hilbert_basis.h b/src/math/hilbert/hilbert_basis.h index 1bd87d60c..f743f32ca 100644 --- a/src/math/hilbert/hilbert_basis.h +++ b/src/math/hilbert/hilbert_basis.h @@ -115,7 +115,6 @@ class hilbert_basis { offset_t operator*() const { return hb.m_basis[m_idx]; } iterator& operator++() { ++m_idx; return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } - bool operator==(iterator const& it) const {return m_idx == it.m_idx; } bool operator!=(iterator const& it) const {return m_idx != it.m_idx; } }; diff --git a/src/math/lp/emonics.h b/src/math/lp/emonics.h index 55086515d..f6326c044 100644 --- a/src/math/lp/emonics.h +++ b/src/math/lp/emonics.h @@ -51,9 +51,8 @@ class emonics { unsigned m_index; }; struct head_tail { - head_tail(): m_head(nullptr), m_tail(nullptr) {} - cell* m_head; - cell* m_tail; + cell* m_head = nullptr; + cell* m_tail = nullptr; }; struct hash_canonical { emonics& em; @@ -205,7 +204,6 @@ public: monic & operator*() { return m.m_monics[m_cell->m_index]; } iterator& operator++() { m_touched = true; m_cell = m_cell->m_next; return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } - bool operator==(iterator const& other) const { return m_cell == other.m_cell && m_touched == other.m_touched; } bool operator!=(iterator const& other) const { return m_cell != other.m_cell || m_touched != other.m_touched; } }; @@ -239,7 +237,6 @@ public: } pf_iterator& operator++() { ++m_it; fast_forward(); return *this; } pf_iterator operator++(int) { pf_iterator tmp = *this; ++*this; return tmp; } - bool operator==(pf_iterator const& other) const { return m_it == other.m_it; } bool operator!=(pf_iterator const& other) const { return m_it != other.m_it; } }; diff --git a/src/math/lp/explanation.h b/src/math/lp/explanation.h index 9d8099c1e..850e59cd4 100644 --- a/src/math/lp/explanation.h +++ b/src/math/lp/explanation.h @@ -106,11 +106,10 @@ public: iterator(bool run_on_vector, pair_vec::const_iterator vi, ci_set::iterator cii) : m_run_on_vector(run_on_vector), m_vi(vi), m_ci(cii) {} - bool operator==(const iterator &other) const { + bool operator!=(const iterator &other) const { SASSERT(m_run_on_vector == other.m_run_on_vector); - return m_run_on_vector? m_vi == other.m_vi : m_ci == other.m_ci; + return m_run_on_vector ? m_vi != other.m_vi : m_ci != other.m_ci; } - bool operator!=(const iterator &other) const { return !(*this == other); } }; iterator begin() const { diff --git a/src/math/lp/factorization.cpp b/src/math/lp/factorization.cpp index e1dcff626..89c16ec91 100644 --- a/src/math/lp/factorization.cpp +++ b/src/math/lp/factorization.cpp @@ -97,14 +97,12 @@ const_iterator_mon::const_iterator_mon(const bool_vector& mask, const factorizat m_ff(f) , m_full_factorization_returned(false) {} - -bool const_iterator_mon::operator==(const const_iterator_mon::self_type &other) const { - return - m_full_factorization_returned == other.m_full_factorization_returned && - m_mask == other.m_mask; -} -bool const_iterator_mon::operator!=(const const_iterator_mon::self_type &other) const { return !(*this == other); } +bool const_iterator_mon::operator!=(const const_iterator_mon::self_type &other) const { + return + m_full_factorization_returned != other.m_full_factorization_returned || + m_mask != other.m_mask; +} factorization const_iterator_mon::create_binary_factorization(factor j, factor k) const { factorization f(nullptr); diff --git a/src/math/lp/factorization.h b/src/math/lp/factorization.h index be3a024e3..128b269fa 100644 --- a/src/math/lp/factorization.h +++ b/src/math/lp/factorization.h @@ -88,8 +88,7 @@ struct const_iterator_mon { self_type operator++(int); const_iterator_mon(const bool_vector& mask, const factorization_factory *f); - - bool operator==(const self_type &other) const; + bool operator!=(const self_type &other) const; factorization create_binary_factorization(factor j, factor k) const; diff --git a/src/math/lp/lar_constraints.h b/src/math/lp/lar_constraints.h index b9069625f..1105382e7 100644 --- a/src/math/lp/lar_constraints.h +++ b/src/math/lp/lar_constraints.h @@ -203,7 +203,6 @@ public: lar_base_constraint const* operator->() const { return &cs[m_index]; } iterator& operator++() { next(); return *this; } iterator operator++(int) { auto tmp = *this; next(); return tmp; } - bool operator==(iterator const& other) const { return m_index == other.m_index; } bool operator!=(iterator const& other) const { return m_index != other.m_index; } }; iterator begin() const { return iterator(cs, 0); } @@ -229,7 +228,6 @@ public: constraint_index const* operator->() const { return &m_index; } iterator& operator++() { next(); return *this; } iterator operator++(int) { auto tmp = *this; next(); return tmp; } - bool operator==(iterator const& other) const { return m_index == other.m_index; } bool operator!=(iterator const& other) const { return m_index != other.m_index; } }; iterator begin() const { return iterator(cs, 0); } diff --git a/src/math/lp/lar_term.h b/src/math/lp/lar_term.h index 87a0c282a..8f8dd2f4a 100644 --- a/src/math/lp/lar_term.h +++ b/src/math/lp/lar_term.h @@ -170,8 +170,7 @@ public: const_iterator operator++() { const_iterator i = *this; m_it++; return i; } const_iterator operator++(int) { m_it++; return *this; } const_iterator(u_map::iterator it) : m_it(it) {} - bool operator==(const const_iterator &other) const { return m_it == other.m_it; } - bool operator!=(const const_iterator &other) const { return !(*this == other); } + bool operator!=(const const_iterator &other) const { return m_it != other.m_it; } }; bool is_normalized() const { diff --git a/src/math/lp/var_eqs.h b/src/math/lp/var_eqs.h index 56c39c460..b2b3f24cf 100644 --- a/src/math/lp/var_eqs.h +++ b/src/math/lp/var_eqs.h @@ -302,7 +302,6 @@ public: return signed_var(m_idx); } iterator& operator++() { m_idx = m_ve.m_uf.next(m_idx); m_touched = true; return *this; } - bool operator==(iterator const& other) const { return m_idx == other.m_idx && m_touched == other.m_touched; } bool operator!=(iterator const& other) const { return m_idx != other.m_idx || m_touched != other.m_touched; } }; diff --git a/src/math/simplex/bit_matrix.h b/src/math/simplex/bit_matrix.h index c827690ec..13ca2b7ba 100644 --- a/src/math/simplex/bit_matrix.h +++ b/src/math/simplex/bit_matrix.h @@ -71,7 +71,6 @@ public: unsigned const* operator->() const { return &m_column; } col_iterator& operator++() { next(); return *this; } col_iterator operator++(int) { auto tmp = *this; next(); return tmp; } - bool operator==(col_iterator const& other) const { return m_column == other.m_column; } bool operator!=(col_iterator const& other) const { return m_column != other.m_column; } }; @@ -88,7 +87,6 @@ public: row* operator->() { return &m_row; } row_iterator& operator++() { next(); return *this; } row_iterator operator++(int) { auto tmp = *this; next(); return tmp; } - bool operator==(row_iterator const& other) const { return m_index == other.m_index; } bool operator!=(row_iterator const& other) const { return m_index != other.m_index; } }; diff --git a/src/math/simplex/sparse_matrix.h b/src/math/simplex/sparse_matrix.h index 9333e9ddb..0dfd1a2ad 100644 --- a/src/math/simplex/sparse_matrix.h +++ b/src/math/simplex/sparse_matrix.h @@ -198,7 +198,6 @@ namespace simplex { row_entry * operator->() const { return &(operator*()); } row_iterator & operator++() { ++m_curr; move_to_used(); return *this; } row_iterator operator++(int) { row_iterator tmp = *this; ++*this; return tmp; } - bool operator==(row_iterator const & it) const { return m_curr == it.m_curr; } bool operator!=(row_iterator const & it) const { return m_curr != it.m_curr; } }; @@ -308,7 +307,6 @@ namespace simplex { row operator*() { return row(m_curr); } all_row_iterator & operator++() { m_curr++; move_to_next(); return *this; } all_row_iterator operator++(int) { all_row_iterator tmp = *this; ++*this; return tmp; } - bool operator==(all_row_iterator const& it) const { return m_curr == it.m_curr; } bool operator!=(all_row_iterator const& it) const { return m_curr != it.m_curr; } }; diff --git a/src/muz/rel/dl_table.cpp b/src/muz/rel/dl_table.cpp index e0ea17739..fec4e5c98 100644 --- a/src/muz/rel/dl_table.cpp +++ b/src/muz/rel/dl_table.cpp @@ -122,7 +122,7 @@ namespace datalog { m_end(t.m_data.end()), m_row_obj(*this) {} bool is_finished() const override { - return m_inner==m_end; + return !(m_inner != m_end); } row_interface & operator*() override { diff --git a/src/qe/qe.h b/src/qe/qe.h index 55729d0b5..05251a2e0 100644 --- a/src/qe/qe.h +++ b/src/qe/qe.h @@ -123,7 +123,6 @@ namespace qe { iterator(conj_enum& c, bool first) : m_super(&c), m_index(first?0:c.m_conjs.size()) {} expr* operator*() { return m_super->m_conjs[m_index].get(); } iterator& operator++() { m_index++; return *this; } - bool operator==(iterator const& it) const { return m_index == it.m_index; } bool operator!=(iterator const& it) const { return m_index != it.m_index; } }; diff --git a/src/sat/dimacs.h b/src/sat/dimacs.h index ca6aae07b..3ca8102ff 100644 --- a/src/sat/dimacs.h +++ b/src/sat/dimacs.h @@ -94,7 +94,6 @@ namespace dimacs { iterator(drat_parser& p, bool is_eof):p(p), m_eof(is_eof) { if (!m_eof) m_eof = !p.next(); } drat_record const& operator*() { return p.m_record; } iterator& operator++() { if (!p.next()) m_eof = true; return *this;} - bool operator==(iterator const& other) const { return m_eof == other.m_eof; } bool operator!=(iterator const& other) const { return m_eof != other.m_eof; } }; diff --git a/src/sat/sat_clause.h b/src/sat/sat_clause.h index f1a44296e..0129febbf 100644 --- a/src/sat/sat_clause.h +++ b/src/sat/sat_clause.h @@ -188,7 +188,6 @@ namespace sat { iterator(clause_wrapper const& c, unsigned idx): m_idx(idx), m_cw(c) {} iterator& operator++() { ++m_idx; return *this; } literal operator*() { return m_cw[m_idx]; } - bool operator==(iterator const& other) const { SASSERT(&m_cw == &other.m_cw); return m_idx == other.m_idx; } bool operator!=(iterator const& other) const { SASSERT(&m_cw == &other.m_cw); return m_idx != other.m_idx; } }; iterator begin() const { return iterator(*this, 0); } diff --git a/src/sat/smt/pb_constraint.h b/src/sat/smt/pb_constraint.h index 26c5f8b08..4c6f69e07 100644 --- a/src/sat/smt/pb_constraint.h +++ b/src/sat/smt/pb_constraint.h @@ -125,7 +125,6 @@ namespace pb { iterator(constraint const& c, unsigned idx) : c(c), idx(idx) {} literal operator*() { return c.get_lit(idx); } iterator& operator++() { ++idx; return *this; } - bool operator==(iterator const& other) const { SASSERT(&c == &other.c); return idx == other.idx; } bool operator!=(iterator const& other) const { SASSERT(&c == &other.c); return idx != other.idx; } }; diff --git a/src/smt/smt_enode.h b/src/smt/smt_enode.h index 92902ea0b..3f488a3b7 100644 --- a/src/smt/smt_enode.h +++ b/src/smt/smt_enode.h @@ -360,8 +360,7 @@ namespace smt { enode* operator*() { return m_first; } iterator& operator++() { if (!m_last) m_last = m_first; m_first = m_first->m_next; return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } - bool operator==(iterator const& other) const { return m_last == other.m_last && m_first == other.m_first; } - bool operator!=(iterator const& other) const { return !(*this == other); } + bool operator!=(iterator const& other) const { return m_last != other.m_last || m_first != other.m_first; } }; iterator begin() { return iterator(this, nullptr); } diff --git a/src/util/approx_set.h b/src/util/approx_set.h index a1835be6f..011a8017d 100644 --- a/src/util/approx_set.h +++ b/src/util/approx_set.h @@ -197,10 +197,6 @@ public: ++*this; return tmp; } - - bool operator==(iterator const & it) const { - return m_set == it.m_set; - } bool operator!=(iterator const & it) const { return m_set != it.m_set; diff --git a/src/util/bit_vector.h b/src/util/bit_vector.h index 12f86dd00..7b87e045a 100644 --- a/src/util/bit_vector.h +++ b/src/util/bit_vector.h @@ -220,7 +220,6 @@ public: bool operator*() const { return b.get(m_curr); } iterator& operator++() { ++m_curr; return *this; } iterator operator++(int) { iterator tmp = *this; ++* this; return tmp; } - bool operator==(iterator const& it) const { return m_curr == it.m_curr; } bool operator!=(iterator const& it) const { return m_curr != it.m_curr; } }; diff --git a/src/util/chashtable.h b/src/util/chashtable.h index da7cb5b31..f245a047c 100644 --- a/src/util/chashtable.h +++ b/src/util/chashtable.h @@ -551,7 +551,6 @@ public: return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } - bool operator==(iterator const & it) const { return m_list_it == it.m_list_it; } bool operator!=(iterator const & it) const { return m_list_it != it.m_list_it; } }; diff --git a/src/util/distribution.h b/src/util/distribution.h index 0ed63d510..92aa4d805 100644 --- a/src/util/distribution.h +++ b/src/util/distribution.h @@ -95,7 +95,6 @@ public: next_index(); return *this; } - bool operator==(iterator const& other) const { return m_sz == other.m_sz; } bool operator!=(iterator const& other) const { return m_sz != other.m_sz; } }; diff --git a/src/util/dlist.h b/src/util/dlist.h index 4c0e51e58..1ed183d3d 100644 --- a/src/util/dlist.h +++ b/src/util/dlist.h @@ -213,13 +213,8 @@ public: T const& operator*() const { return *m_elem; } - - bool operator==(dll_iterator const& other) const { - return m_elem == other.m_elem && m_first == other.m_first; - } - bool operator!=(dll_iterator const& other) const { - return !operator==(other); + return m_elem != other.m_elem || m_first != other.m_first; } }; diff --git a/src/util/list.h b/src/util/list.h index 208828ea0..a9c33fd33 100644 --- a/src/util/list.h +++ b/src/util/list.h @@ -44,7 +44,6 @@ public: T const & operator*() const { return m_curr->head(); } iterator & operator++() { m_curr = m_curr->tail(); return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } - bool operator==(iterator const & it) { return m_curr == it.m_curr; } bool operator!=(iterator const & it) { return m_curr != it.m_curr; } }; diff --git a/src/util/scoped_vector.h b/src/util/scoped_vector.h index 7d0cec472..6a5c1228d 100644 --- a/src/util/scoped_vector.h +++ b/src/util/scoped_vector.h @@ -106,8 +106,7 @@ public: unsigned m_index; public: iterator(scoped_vector const& v, unsigned idx): m_vec(v), m_index(idx) {} - - bool operator==(iterator const& other) const { return &other.m_vec == &m_vec && other.m_index == m_index; } + bool operator!=(iterator const& other) const { return &other.m_vec != &m_vec || other.m_index != m_index; } T const& operator*() { return m_vec[m_index]; } diff --git a/src/util/uint_set.h b/src/util/uint_set.h index 73c3bce1f..f936f1134 100644 --- a/src/util/uint_set.h +++ b/src/util/uint_set.h @@ -194,7 +194,6 @@ public: SASSERT(invariant()); } unsigned operator*() const { return m_index; } - bool operator==(iterator const& it) const { return m_index == it.m_index; } bool operator!=(iterator const& it) const { return m_index != it.m_index; } iterator & operator++() { ++m_index; scan(); return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } diff --git a/src/util/vector.h b/src/util/vector.h index 79e51d545..1f51ac775 100644 --- a/src/util/vector.h +++ b/src/util/vector.h @@ -311,9 +311,6 @@ public: return *this; } - bool operator==(reverse_iterator const& other) const { - return other.v == v; - } bool operator!=(reverse_iterator const& other) const { return other.v != v; } @@ -883,9 +880,6 @@ public: return *this; } - bool operator==(reverse_iterator const& other) const { - return other.v == v; - } bool operator!=(reverse_iterator const& other) const { return other.v != v; } From eb8c63080a9f37e023fce58caf76e82e4497c406 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 23 Sep 2024 13:33:44 +0100 Subject: [PATCH 121/187] Refactor and fix uninitialized variables and improve function consistency across multiple modules --- genaisrc/.#gcm.genai.mts | 1 + genaisrc/fw.genai.mts | 37 +++++++++++++++++++++++++++ src/ast/bv_decl_plugin.cpp | 4 +-- src/ast/euf/euf_ac_plugin.cpp | 1 - src/ast/euf/euf_ac_plugin.h | 2 +- src/qe/mbp/mbp_arith.cpp | 8 +++--- src/qe/mbp/mbp_arith.h | 2 +- src/qe/mbp/mbp_arrays.cpp | 2 +- src/qe/mbp/mbp_arrays.h | 2 +- src/qe/mbp/mbp_datatypes.cpp | 6 ++--- src/qe/mbp/mbp_datatypes.h | 2 +- src/qe/mbp/mbp_plugin.h | 2 +- src/qe/qe_mbp.cpp | 2 +- src/sat/sat_solver/inc_sat_solver.cpp | 2 -- src/sat/smt/arith_axioms.cpp | 2 +- src/sat/smt/array_internalize.cpp | 2 +- src/sat/smt/intblast_solver.cpp | 8 +++--- 17 files changed, 60 insertions(+), 25 deletions(-) create mode 100644 genaisrc/.#gcm.genai.mts create mode 100644 genaisrc/fw.genai.mts diff --git a/genaisrc/.#gcm.genai.mts b/genaisrc/.#gcm.genai.mts new file mode 100644 index 000000000..9102e16be --- /dev/null +++ b/genaisrc/.#gcm.genai.mts @@ -0,0 +1 @@ +nbjorner@LAPTOP-04AEAFKH.21956:1726928207 \ No newline at end of file diff --git a/genaisrc/fw.genai.mts b/genaisrc/fw.genai.mts new file mode 100644 index 000000000..11f4ed579 --- /dev/null +++ b/genaisrc/fw.genai.mts @@ -0,0 +1,37 @@ +// This script is used to invoke ninja and automatically suggest fixes to build warnings +import { select, input, confirm } from "@inquirer/prompts" + + +// TODO: invoke ninja in z3 build directory +// - pipe output of build to a string buffer +// - chunk up warning/error messages one by one +// - create AI query to have the warning/error fixed +// - stage the changes +// - recompile, rinse repeat until fixes +// - backtrack from failed fixes? + +// let ninjaout = await host.exec("ninja", []) +// console.log(ninjaout.stdout) +// await runPrompt( (_) => { _.def("BUILDMSG", ninjaout, { maxTokens: 20000}) +// _.$`BUILDMSG is the output of a ninja build. Please generate fixes for the warning messages, stage the changes. Repeat the build process for up to three iterations to fix error or warning messages` } + + + +defData("EXAMPLEMSG"," +/home/nbjorner/z3/src/smt/theory_str.cpp: In member function ‘void smt::theory_str::instantiate_axiom_CharAt(smt::enode*)’: +/home/nbjorner/z3/src/smt/theory_str.cpp:1092:15: warning: ‘arg0’ may be used uninitialized [-Wmaybe-uninitialized] + 1092 | expr* arg0, *arg1; + | ^~~~ +In file included from /home/nbjorner/z3/src/ast/ast_smt2_pp.h:26, + from /home/nbjorner/z3/src/smt/theory_str.cpp:17: +In member function ‘app* arith_util::mk_lt(expr*, expr*) const’, + inlined from ‘void smt::theory_str::instantiate_axiom_CharAt(smt::enode*)’ at /home/nbjorner/z3/src/smt/theory_str.cpp:1110:40: +") + +// TODO: script to extract file contents +// TODO: script what to update. + +$` +You are a helpful AI assistant who knows C++ and can fix build warnings. +You are given the following warning message ${EXAMPLEMSG}. Create a fix. +` diff --git a/src/ast/bv_decl_plugin.cpp b/src/ast/bv_decl_plugin.cpp index 5dd9f6080..8c9a5652f 100644 --- a/src/ast/bv_decl_plugin.cpp +++ b/src/ast/bv_decl_plugin.cpp @@ -927,7 +927,7 @@ sort * bv_util::mk_sort(unsigned bv_size) { } unsigned bv_util::get_int2bv_size(parameter const& p) { - int sz; + int sz = 0; VERIFY(m_plugin->get_int2bv_size(1, &p, sz)); return static_cast(sz); } @@ -951,4 +951,4 @@ app* bv_util::mk_bv_rotate_left(expr* arg, unsigned n) { app* bv_util::mk_bv_rotate_right(expr* arg, unsigned n) { parameter p(n); return m_manager.mk_app(get_fid(), OP_ROTATE_RIGHT, 1, &p, 1, &arg); -} \ No newline at end of file +} diff --git a/src/ast/euf/euf_ac_plugin.cpp b/src/ast/euf/euf_ac_plugin.cpp index 174ef363b..69d0e6572 100644 --- a/src/ast/euf/euf_ac_plugin.cpp +++ b/src/ast/euf/euf_ac_plugin.cpp @@ -907,7 +907,6 @@ namespace euf { m_dst_r.reset(); m_dst_r.append(monomial(dst.r).m_nodes); unsigned src_r_size = m_src_r.size(); - unsigned dst_r_size = m_dst_r.size(); SASSERT(src_r_size == monomial(src.r).size()); // dst_r contains C // src_r contains E diff --git a/src/ast/euf/euf_ac_plugin.h b/src/ast/euf/euf_ac_plugin.h index d55d7dbb4..809ac55cf 100644 --- a/src/ast/euf/euf_ac_plugin.h +++ b/src/ast/euf/euf_ac_plugin.h @@ -136,7 +136,7 @@ namespace euf { }; theory_id m_fid = 0; - unsigned m_op = null_decl_kind; + decl_kind m_op = null_decl_kind; func_decl* m_decl = nullptr; vector m_eqs; ptr_vector m_nodes; diff --git a/src/qe/mbp/mbp_arith.cpp b/src/qe/mbp/mbp_arith.cpp index ef4428fa7..8bbf3a002 100644 --- a/src/qe/mbp/mbp_arith.cpp +++ b/src/qe/mbp/mbp_arith.cpp @@ -304,7 +304,7 @@ namespace mbp { return rational(b.is_pos() ? -1 : 1); } - bool operator()(model& model, app* v, app_ref_vector& vars, expr_ref_vector& lits) { + bool project1(model& model, app* v, app_ref_vector& vars, expr_ref_vector& lits) { app_ref_vector vs(m); vs.push_back(v); vector defs; @@ -710,8 +710,8 @@ namespace mbp { dealloc(m_imp); } - bool arith_project_plugin::operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) { - return (*m_imp)(model, var, vars, lits); + bool arith_project_plugin::project1(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) { + return m_imp->project1(model, var, vars, lits); } bool arith_project_plugin::operator()(model& model, app_ref_vector& vars, expr_ref_vector& lits) { @@ -743,6 +743,6 @@ namespace mbp { ast_manager& m = lits.get_manager(); arith_project_plugin ap(m); app_ref_vector vars(m); - return ap(model, var, vars, lits); + return ap.project1(model, var, vars, lits); } } diff --git a/src/qe/mbp/mbp_arith.h b/src/qe/mbp/mbp_arith.h index ca4cccb74..666ffffc4 100644 --- a/src/qe/mbp/mbp_arith.h +++ b/src/qe/mbp/mbp_arith.h @@ -26,7 +26,7 @@ namespace mbp { arith_project_plugin(ast_manager& m); ~arith_project_plugin() override; - bool operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) override; + bool project1(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) override; bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) override { return false; } family_id get_family_id() override; bool operator()(model& model, app_ref_vector& vars, expr_ref_vector& lits) override; diff --git a/src/qe/mbp/mbp_arrays.cpp b/src/qe/mbp/mbp_arrays.cpp index fa7ec8cb5..6e036a714 100644 --- a/src/qe/mbp/mbp_arrays.cpp +++ b/src/qe/mbp/mbp_arrays.cpp @@ -1444,7 +1444,7 @@ namespace mbp { dealloc(m_imp); } - bool array_project_plugin::operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) { + bool array_project_plugin::project1(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) { ast_manager& m = vars.get_manager(); app_ref_vector vvars(m, 1, &var); expr_ref fml = mk_and(lits); diff --git a/src/qe/mbp/mbp_arrays.h b/src/qe/mbp/mbp_arrays.h index 7dd904108..ed06ba78b 100644 --- a/src/qe/mbp/mbp_arrays.h +++ b/src/qe/mbp/mbp_arrays.h @@ -31,7 +31,7 @@ namespace mbp { public: array_project_plugin(ast_manager& m); ~array_project_plugin() override; - bool operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) override; + bool project1(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) override; bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) override; void operator()(model& model, app_ref_vector& vars, expr_ref& fml, app_ref_vector& aux_vars, bool reduce_all_selects); family_id get_family_id() override; diff --git a/src/qe/mbp/mbp_datatypes.cpp b/src/qe/mbp/mbp_datatypes.cpp index 32e2b9f27..5a88016db 100644 --- a/src/qe/mbp/mbp_datatypes.cpp +++ b/src/qe/mbp/mbp_datatypes.cpp @@ -40,7 +40,7 @@ namespace mbp { return lift_foreign(vars, lits); } - bool operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) { + bool project1(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) { expr_ref val = model(var); SASSERT(is_app(val)); TRACE("qe", tout << mk_pp(var, m) << " := " << val << "\n";); @@ -292,8 +292,8 @@ namespace mbp { dealloc(m_imp); } - bool datatype_project_plugin::operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) { - return (*m_imp)(model, var, vars, lits); + bool datatype_project_plugin::project1(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) { + return m_imp->project1(model, var, vars, lits); } bool datatype_project_plugin::solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) { diff --git a/src/qe/mbp/mbp_datatypes.h b/src/qe/mbp/mbp_datatypes.h index f30aaaa9f..28f93089d 100644 --- a/src/qe/mbp/mbp_datatypes.h +++ b/src/qe/mbp/mbp_datatypes.h @@ -31,7 +31,7 @@ namespace mbp { public: datatype_project_plugin(ast_manager& m); ~datatype_project_plugin() override; - bool operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) override; + bool project1(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) override; bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) override; family_id get_family_id() override; bool project(model& model, app_ref_vector& vars, expr_ref_vector& lits, vector& defs) override; diff --git a/src/qe/mbp/mbp_plugin.h b/src/qe/mbp/mbp_plugin.h index 4f73b92e6..c270489e8 100644 --- a/src/qe/mbp/mbp_plugin.h +++ b/src/qe/mbp/mbp_plugin.h @@ -60,7 +60,7 @@ namespace mbp { public: project_plugin(ast_manager& m) :m(m), m_cache(m), m_args(m), m_pure_eqs(m) {} virtual ~project_plugin() = default; - virtual bool operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) { return false; } + virtual bool project1(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) { return false; } /** \brief partial solver. */ diff --git a/src/qe/qe_mbp.cpp b/src/qe/qe_mbp.cpp index 97f12238d..b5fafeeac 100644 --- a/src/qe/qe_mbp.cpp +++ b/src/qe/qe_mbp.cpp @@ -452,7 +452,7 @@ public: var = vars.back(); vars.pop_back(); mbp::project_plugin* p = get_plugin(var); - if (p && (*p)(model, var, vars, fmls)) { + if (p && p->project1(model, var, vars, fmls)) { progress = true; } else { diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index 5e0d10918..522638c1d 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -193,8 +193,6 @@ public: m_solver.pop_to_base_level(); m_core.reset(); - - if (m_solver.inconsistent()) return l_false; expr_ref_vector _assumptions(m); obj_map asm2fml; diff --git a/src/sat/smt/arith_axioms.cpp b/src/sat/smt/arith_axioms.cpp index 7270e7080..f35f3851a 100644 --- a/src/sat/smt/arith_axioms.cpp +++ b/src/sat/smt/arith_axioms.cpp @@ -325,7 +325,7 @@ namespace arith { void solver::mk_bv_axiom(app* n) { unsigned sz; - expr* _x, * _y; + expr* _x = nullptr, * _y = nullptr; VERIFY(a.is_band(n, sz, _x, _y) || a.is_shl(n, sz, _x, _y) || a.is_ashr(n, sz, _x, _y) || a.is_lshr(n, sz, _x, _y)); rational N = rational::power_of_two(sz); expr_ref x(a.mk_mod(_x, a.mk_int(N)), m); diff --git a/src/sat/smt/array_internalize.cpp b/src/sat/smt/array_internalize.cpp index d5a1dd2c5..9e41be3bb 100644 --- a/src/sat/smt/array_internalize.cpp +++ b/src/sat/smt/array_internalize.cpp @@ -128,7 +128,7 @@ namespace array { internalize_lambda_eh(n); break; case OP_SET_SUBSET: { - expr* x, *y; + expr* x = nullptr, *y = nullptr; VERIFY(a.is_subset(n->get_expr(), x, y)); expr_ref diff(a.mk_setminus(x, y), m); expr_ref emp(a.mk_empty_set(x->get_sort()), m); diff --git a/src/sat/smt/intblast_solver.cpp b/src/sat/smt/intblast_solver.cpp index f91113d59..d6dfe57d7 100644 --- a/src/sat/smt/intblast_solver.cpp +++ b/src/sat/smt/intblast_solver.cpp @@ -91,7 +91,7 @@ namespace intblast { void solver::eq_internalized(euf::enode* n) { expr* e = n->get_expr(); - expr* x, * y; + expr* x = nullptr, * y = nullptr; VERIFY(m.is_eq(n->get_expr(), x, y)); SASSERT(bv.is_bv(x)); if (!is_translated(e)) { @@ -482,7 +482,7 @@ namespace intblast { return r >= 0; if (is_bounded(e, N)) return true; - expr* x, * y; + expr* x = nullptr, * y = nullptr; if (a.is_mul(e, x, y)) return is_non_negative(bv_expr, x) && is_non_negative(bv_expr, y); if (a.is_add(e, x, y)) @@ -544,7 +544,7 @@ namespace intblast { */ expr* solver::amod(expr* bv_expr, expr* x, rational const& N) { rational v; - expr* r, *c, * t, * e; + expr* r = nullptr, *c = nullptr, * t = nullptr, * e = nullptr; if (m.is_ite(x, c, t, e)) r = m.mk_ite(c, amod(bv_expr, t, N), amod(bv_expr, e, N)); else if (a.is_idiv(x, t, e) && a.is_numeral(t, v) && 0 <= v && v < N && is_non_negative(bv_expr, e)) @@ -880,7 +880,7 @@ namespace intblast { r = umod(bv_expr, 0); SASSERT(bv.get_bv_size(e) >= bv.get_bv_size(bv_expr)); unsigned arg_sz = bv.get_bv_size(bv_expr); - unsigned sz = bv.get_bv_size(e); + //unsigned sz = bv.get_bv_size(e); // rational N = rational::power_of_two(sz); rational M = rational::power_of_two(arg_sz); expr* signbit = a.mk_ge(r, a.mk_int(M / 2)); From ee347735be8246d7150fa90b1e35cfc5f02bb835 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 23 Sep 2024 13:34:26 +0100 Subject: [PATCH 122/187] remove junk Signed-off-by: Nikolaj Bjorner --- genaisrc/.#gcm.genai.mts | 1 - genaisrc/fw.genai.mts | 37 ------------------------------------- 2 files changed, 38 deletions(-) delete mode 100644 genaisrc/.#gcm.genai.mts delete mode 100644 genaisrc/fw.genai.mts diff --git a/genaisrc/.#gcm.genai.mts b/genaisrc/.#gcm.genai.mts deleted file mode 100644 index 9102e16be..000000000 --- a/genaisrc/.#gcm.genai.mts +++ /dev/null @@ -1 +0,0 @@ -nbjorner@LAPTOP-04AEAFKH.21956:1726928207 \ No newline at end of file diff --git a/genaisrc/fw.genai.mts b/genaisrc/fw.genai.mts deleted file mode 100644 index 11f4ed579..000000000 --- a/genaisrc/fw.genai.mts +++ /dev/null @@ -1,37 +0,0 @@ -// This script is used to invoke ninja and automatically suggest fixes to build warnings -import { select, input, confirm } from "@inquirer/prompts" - - -// TODO: invoke ninja in z3 build directory -// - pipe output of build to a string buffer -// - chunk up warning/error messages one by one -// - create AI query to have the warning/error fixed -// - stage the changes -// - recompile, rinse repeat until fixes -// - backtrack from failed fixes? - -// let ninjaout = await host.exec("ninja", []) -// console.log(ninjaout.stdout) -// await runPrompt( (_) => { _.def("BUILDMSG", ninjaout, { maxTokens: 20000}) -// _.$`BUILDMSG is the output of a ninja build. Please generate fixes for the warning messages, stage the changes. Repeat the build process for up to three iterations to fix error or warning messages` } - - - -defData("EXAMPLEMSG"," -/home/nbjorner/z3/src/smt/theory_str.cpp: In member function ‘void smt::theory_str::instantiate_axiom_CharAt(smt::enode*)’: -/home/nbjorner/z3/src/smt/theory_str.cpp:1092:15: warning: ‘arg0’ may be used uninitialized [-Wmaybe-uninitialized] - 1092 | expr* arg0, *arg1; - | ^~~~ -In file included from /home/nbjorner/z3/src/ast/ast_smt2_pp.h:26, - from /home/nbjorner/z3/src/smt/theory_str.cpp:17: -In member function ‘app* arith_util::mk_lt(expr*, expr*) const’, - inlined from ‘void smt::theory_str::instantiate_axiom_CharAt(smt::enode*)’ at /home/nbjorner/z3/src/smt/theory_str.cpp:1110:40: -") - -// TODO: script to extract file contents -// TODO: script what to update. - -$` -You are a helpful AI assistant who knows C++ and can fix build warnings. -You are given the following warning message ${EXAMPLEMSG}. Create a fix. -` From 5c583299f1983bcd7300f82d96b1b81e5634baee Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 23 Sep 2024 13:38:07 +0100 Subject: [PATCH 123/187] Remove unnecessary const qualifiers from comparison operator overloads in z3++.h --- src/api/c++/z3++.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index 85d5fce62..e29bde4a8 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -1703,28 +1703,28 @@ namespace z3 { inline expr operator||(bool a, expr const & b) { return b.ctx().bool_val(a) || b; } - inline expr operator==(expr const & a, expr const & b) const { + inline expr operator==(expr const & a, expr const & b) { check_context(a, b); Z3_ast r = Z3_mk_eq(a.ctx(), a, b); a.check_error(); return expr(a.ctx(), r); } - inline expr operator==(expr const & a, int b) const { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a == a.ctx().num_val(b, a.get_sort()); } + inline expr operator==(expr const & a, int b) { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a == a.ctx().num_val(b, a.get_sort()); } inline expr operator==(int a, expr const & b) { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) == b; } - inline expr operator==(expr const & a, double b) const { assert(a.is_fpa()); return a == a.ctx().fpa_val(b); } - inline expr operator==(double a, expr const & b) const { assert(b.is_fpa()); return b.ctx().fpa_val(a) == b; } + inline expr operator==(expr const & a, double b) { assert(a.is_fpa()); return a == a.ctx().fpa_val(b); } + inline expr operator==(double a, expr const & b) { assert(b.is_fpa()); return b.ctx().fpa_val(a) == b; } - inline expr operator!=(expr const & a, expr const & b) const { + inline expr operator!=(expr const & a, expr const & b) { check_context(a, b); Z3_ast args[2] = { a, b }; Z3_ast r = Z3_mk_distinct(a.ctx(), 2, args); a.check_error(); return expr(a.ctx(), r); } - inline expr operator!=(expr const & a, int b) const { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a != a.ctx().num_val(b, a.get_sort()); } - inline expr operator!=(int a, expr const & b) const { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) != b; } - inline expr operator!=(expr const & a, double b) const { assert(a.is_fpa()); return a != a.ctx().fpa_val(b); } - inline expr operator!=(double a, expr const & b) const { assert(b.is_fpa()); return b.ctx().fpa_val(a) != b; } + inline expr operator!=(expr const & a, int b) { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a != a.ctx().num_val(b, a.get_sort()); } + inline expr operator!=(int a, expr const & b) { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) != b; } + inline expr operator!=(expr const & a, double b) { assert(a.is_fpa()); return a != a.ctx().fpa_val(b); } + inline expr operator!=(double a, expr const & b) { assert(b.is_fpa()); return b.ctx().fpa_val(a) != b; } inline expr operator+(expr const & a, expr const & b) { check_context(a, b); From 5a6dc18d0d7843a6b8583be193056fee467995f6 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 23 Sep 2024 13:46:50 +0100 Subject: [PATCH 124/187] Override convert_initialize_value method in bit_blaster_model_converter.cpp --- src/tactic/bv/bit_blaster_model_converter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/bv/bit_blaster_model_converter.cpp b/src/tactic/bv/bit_blaster_model_converter.cpp index 5bc874abb..ee48f48a1 100644 --- a/src/tactic/bv/bit_blaster_model_converter.cpp +++ b/src/tactic/bv/bit_blaster_model_converter.cpp @@ -222,7 +222,7 @@ struct bit_blaster_model_converter : public model_converter { // no-op } - void convert_initialize_value(vector>& var2value) { + void convert_initialize_value(vector>& var2value) override { if (m_vars.empty() || var2value.empty()) return; rational r; From 0604d23c570970155ed56d58f545b8533d336be1 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 23 Sep 2024 13:50:32 +0100 Subject: [PATCH 125/187] Check if model_converter is non-null before initializing values in sat_tactic --- src/sat/tactic/sat_tactic.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp index 6a48bc8ed..105fe94ba 100644 --- a/src/sat/tactic/sat_tactic.cpp +++ b/src/sat/tactic/sat_tactic.cpp @@ -43,7 +43,8 @@ class sat_tactic : public tactic { } void initialize_values(goal_ref const& g, atom2bool_var& map) { - g->mc()->convert_initialize_value(m_var2value); + if (g->mc()) + g->mc()->convert_initialize_value(m_var2value); for (auto & [var, value] : m_var2value) { if (!m.is_bool(var)) continue; From 95d2e009ef93fbcd07d531fc4360249a0afc13fa Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 23 Sep 2024 17:25:44 +0100 Subject: [PATCH 126/187] Update OCaml jobs to use Ubuntu-latest in Azure Pipelines configuration --- azure-pipelines.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b7ad2ab1e..18ab31f50 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -76,10 +76,10 @@ jobs: - script: "pip install build git+https://github.com/rhelmot/auditwheel" - script: "cd src/api/python && CC=aarch64-none-linux-gnu-gcc CXX=aarch64-none-linux-gnu-g++ AR=aarch64-none-linux-gnu-ar LD=aarch64-none-linux-gnu-ld python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." -- job: "Ubuntu20OCaml" - displayName: "Ubuntu 20 with OCaml" +- job: "UbuntuOCaml" + displayName: "Ubuntu with OCaml" pool: - vmImage: "Ubuntu-20.04" + vmImage: "Ubuntu-latest" steps: - script: sudo apt-get install ocaml opam libgmp-dev - script: opam init -y @@ -100,9 +100,9 @@ jobs: - job: "Ubuntu20OCamlStatic" - displayName: "Ubuntu 20 with OCaml on z3-static" + displayName: "Ubuntu with OCaml on z3-static" pool: - vmImage: "Ubuntu-20.04" + vmImage: "Ubuntu-latest" steps: - script: sudo apt-get install ocaml opam libgmp-dev - script: opam init -y From ec14ef765e20a1280d956c57458d3bda52e6ff5b Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 23 Sep 2024 17:42:39 +0100 Subject: [PATCH 127/187] Update Ubuntu job name in Azure pipeline and add string variable creation in C API example --- azure-pipelines.yml | 2 +- examples/c/test_capi.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 18ab31f50..d12872f07 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -99,7 +99,7 @@ jobs: - template: scripts/generate-doc.yml -- job: "Ubuntu20OCamlStatic" +- job: "UbuntuOCamlStatic" displayName: "Ubuntu with OCaml on z3-static" pool: vmImage: "Ubuntu-latest" diff --git a/examples/c/test_capi.c b/examples/c/test_capi.c index 98842bb9c..fe4834f57 100644 --- a/examples/c/test_capi.c +++ b/examples/c/test_capi.c @@ -165,6 +165,15 @@ Z3_ast mk_int_var(Z3_context ctx, const char * name) return mk_var(ctx, name, ty); } +/** + \brief Create a string variable using the given name. +*/ +Z3_ast mk_string_var(Z3_context ctx, const char * name) +{ + Z3_sort ty = Z3_mk_string_sort(ctx); + return mk_var(ctx, name, ty); +} + /** \brief Create a Z3 integer node using a C int. */ @@ -1615,7 +1624,7 @@ void error_code_example2() { Z3_del_config(cfg); x = mk_int_var(ctx, "x"); - y = mk_bool_var(ctx, "y"); + y = mk_string_var(ctx, "y"); printf("before Z3_mk_iff\n"); /* the next call will produce an error */ app = Z3_mk_iff(ctx, x, y); From c34c8477f3d10444f8142e6917a752f06af1e246 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Mon, 23 Sep 2024 09:47:34 -0700 Subject: [PATCH 128/187] Add .gitattributes for genaiscript and update git commit flow script. (#7396) --- genaisrc/.gitattributes | 1 + genaisrc/gcm.genai.mts | 99 ++++++++++++++++++++------------------ genaisrc/genaiscript.d.ts | Bin 0 -> 65101 bytes genaisrc/tsconfig.json | 21 ++++++++ 4 files changed, 74 insertions(+), 47 deletions(-) create mode 100644 genaisrc/.gitattributes create mode 100644 genaisrc/genaiscript.d.ts create mode 100644 genaisrc/tsconfig.json diff --git a/genaisrc/.gitattributes b/genaisrc/.gitattributes new file mode 100644 index 000000000..b89350c92 --- /dev/null +++ b/genaisrc/.gitattributes @@ -0,0 +1 @@ +genaiscript.d.ts -diff merge=ours linguist-generated \ No newline at end of file diff --git a/genaisrc/gcm.genai.mts b/genaisrc/gcm.genai.mts index 54f6762a8..e1ebd1197 100644 --- a/genaisrc/gcm.genai.mts +++ b/genaisrc/gcm.genai.mts @@ -1,73 +1,78 @@ -// https://microsoft.github.io/genaiscript/guides/auto-git-commit-message/ -import { select, input, confirm } from "@inquirer/prompts" +/** + * git commit flow with auto-generated commit message + */ +script({ + title: "git commit message", + description: "Generate a commit message for all staged changes", +}) + +// TODO: update this diff command to match your workspace +const diffCmd = "git diff --cached -- . :!**/genaiscript.d.ts" // Check for staged changes and stage all changes if none are staged -let diff = await host.exec("git", ["diff", "--cached"]) +let diff = await host.exec(diffCmd) if (!diff.stdout) { - const stage = await confirm({ - message: "No staged changes. Stage all changes?", + /** + * Ask user to stage all changes if none are staged + */ + const stage = await host.confirm("No staged changes. Stage all changes?", { default: true, }) if (stage) { - await host.exec("git", ["add", "."]) - diff = await host.exec("git", [ - "diff", - "--cached", - "--", - ".", - ":!**/genaiscript.d.ts", - ]) + // Stage all changes and recompute diff + await host.exec("git add .") + diff = await host.exec(diffCmd) } if (!diff.stdout) cancel("no staged changes") } +// show diff in the console console.log(diff.stdout) let choice let message do { // Generate commit message - message = ( - await runPrompt( - (_) => { - _.def("GIT_DIFF", diff, { maxTokens: 20000 }) - _.$`GIT_DIFF is a diff of all staged changes, coming from the command: + const res = await runPrompt( + (_) => { + _.def("GIT_DIFF", diff, { maxTokens: 20000 }) + _.$`GIT_DIFF is a diff of all staged changes, coming from the command: \`\`\` git diff --cached \`\`\` Please generate a concise, one-line commit message for these changes. -- do NOT add quotes` - }, - { cache: false, temperature: 0.8 } - ) - ).text +- do NOT add quotes +` // TODO: add a better prompt + }, + { cache: false, temperature: 0.8 } + ) + if (res.error) throw res.error + + message = res.text + if (!message) { + console.log("No message generated, did you configure the LLM model?") + break + } // Prompt user for commit message - choice = await select({ - message, - choices: [ - { - name: "commit", - value: "commit", - description: "accept message and commit", - }, - { - name: "edit", - value: "edit", - description: "edit message and commit", - }, - { - name: "regenerate", - value: "regenerate", - description: "regenerate message", - }, - ], - }) + choice = await host.select(message, [ + { + value: "commit", + description: "accept message and commit", + }, + { + value: "edit", + description: "edit message and commit", + }, + { + value: "regenerate", + description: "regenerate message", + }, + ]) // Handle user choice if (choice === "edit") { - message = await input({ - message: "Edit commit message", + message = await host.input("Edit commit message", { required: true, }) choice = "commit" @@ -75,8 +80,8 @@ Please generate a concise, one-line commit message for these changes. // Regenerate message if (choice === "commit" && message) { console.log((await host.exec("git", ["commit", "-m", message])).stdout) - if (await confirm({ message: "Push changes?", default: true })) - console.log((await host.exec("git", ["push"])).stdout) + if (await host.confirm("Push changes?", { default: true })) + console.log((await host.exec("git push")).stdout) break } } while (choice !== "commit") diff --git a/genaisrc/genaiscript.d.ts b/genaisrc/genaiscript.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..df355fd9fa1b190cf319b4f7c3aed7f553ed3c6f GIT binary patch literal 65101 zcmdUY>vkMRa^`)CB-3+UuQTQ|PR`L`Fu&Eh8h>SIe?^xm;KEqItPGTCb|b`Tb)n zD9U&1axra+M#>))UliN=XYoIZpMJSh{9Jg|Pd-_*r^mB$UM|)zSNp5g`0D;Kn;f&+ zci(^VNwrv)tF!T>EDl%oe7XLzT$HOZhd#jQ^{gy@`lP`BX7%~@?(Xh%ydK{x#*3@( zzQ1#?cw1Lf`Fc5CEw1@IEl)SsH7{4IdNt7g7n{YSYJ9$^n{_ogD&Ll?YJG)iY)Q*4 zOlFH908jFFwK%J{(z(UPHl4F-RxZZ#@}8klX0aMC&QWr3Ff1V)5k=mO_CFg9di{8*1WJ;k0)>PqRDvEu<2&;W>H@*dcYK# zs1~fW*vwDMmDQPT=8IT{$+QXVQF&G^DiWAMnc(W-xGARvzHoU8g1>8MR7_RVfF>zV znjY2ja(w{;C}u!Uv30bW&&MlZq?lY(v+1f_Z0!`yMSWRRi{k62dB5vwJxegv?)zB{ zVptW^vYD(Z*_K6pR;(||VkvuOw>Uz_jrLreW0RHBQN3B`gCxx(vU?E3LMPlKz(KF5>wW<2ZbdR@+!v++7~TD)A$t_o1%v^WD%H&+d67|xq~WC9we;(O>w zS||>mPQfqQOjYI#=Am70>z3~@ z-9`TZT%S%SQuw-=T$J;1yR)mhJ^`l|Ijq!pjJ~d= z#r}mvX?F#=bgzla0Kt4})p}M>mu+}~BGUU-CVuT-lK4Gc3!nQFQ04P-bzXioUQB0T zrqEhsw~<^^LA)cSv+-#;b1tGqrzLnmkg{5KuF6Uo#loH9iw8v%ou(sorO?aGdbwGH zGfW`8>(#5W+052mf%Nqf3J=&1*^2Z@1j~XS$7G`LZ?w4s~pj z1Y<0r#+Jv_gP|_|(A109_2~~_DxxULZ{rY9BEw)Q!8`{;n?V^~pb@kdSHo2;PL}4| zi)wOFJbU)Mn6pK(t|_`)OxY?Gf5J4!q_y+qdh`#Ww0t*)>?^ZU)p?{dtYxq0BH=-N z)l2N5>Yj87#h0c0U;E2w4$W)u^WcZkdb2tm?Dp?>|FN&aY&M>c?=3H?zt8*Ca{0IS z%e;EGUO7X1K%$Kbq^yMF-_4-gE)Pk9md%EWk}gg0Rdo)<3A;OfnwR56gB3)ri}7r> znN%vE_a*_7+4qwtjjD+Iu?%mPnyLY`bEU7Q_-QCZvOcyj64a;iEv(!k4>1bI_ zsL7}0lDWE|>p(Q(V0E$s@lF<1{0os5W(Li&1`9f&ZLG+5c z0b)fkpAD3>6=(=8v*wUdZx7~v`>dgXYLKT8!`3at=eIG z0=n*7>sd6y$WwQV$2Lorov{9igTftDoL)hH7p(Qeq>~9y9gd;IQGIFj1NIX8)E_T} zfpmcU_ka7}$My2{^56gM|IprBY$mgE13R5Nn}!KiYg{ztdd(l}i}4x|O)8iL1_vk*D~Gz+FD^i}1qNIDU{C-yC2TuVE~hUn0~UMz1|zPO znDd@@3Rtxu8&n2mG-5MB)vgz1qmmVd>!t9s`S^_yVGy>ey2}=sRxrgQlQROZmxsfY z{p|$@2FUhe==v2!PFBh75X%*XGJ>o?`18SeD?_+2&M%xyP`#R4^}fGRf=EOHi( zL1U}zw4NQX#{2Y32S~9hm*Z+BJySu3+oaR^Bh-7P)rPy@2L*t}$d>8YfC0HKX=yek zbq--tfzD-7^I=$RxbugB;&((U{p$u!0<7g2tPOSzkc0g@-7TKNlwEDg9iaw_uT_bv z&APa(X0zfHcAiz_<_7_bW`|bYXmv`Ap<{ z!j>Oyrst(v#6poo!+5#G*5OtHHG>q2vsw8LNQ6SOiu+cnj-T4JoQb%{aHUMA*bvQa ziAY!M^;tRX|@ab;5+0eNeG(ZyZQ! zg>lS^^-=Vv8W~YvJCbR<+AP-9yd0eSQ3=&*-3Z&MsB>hq&30&`RRM)^kDf`nYNRre zZliKusmO&82ImuJrTFU3%Ebi3(P2@X&g#jVmQRWGUuboVXq>BMMg=`VEewG+@HXQ6 zXV>ubhxektRHLy*QNPeZJH^ZeL1kMV{{9Rs)%an|7fa zmIBug`p1A_)oZ_jS&>xwhZHtQD8=7jA>^6<DV$>a0hsYfiyq)1;;V!;`rI-L_h$_UQp-5M6@sYyauZ8CBIn+JFbErxQ3>0UMQ(5 z|KJ;hU#kdBD!8*O@GXqS}pWzR?QrF}|F<5NP zXbLnJ>#|yiPlV)@mL*8+g)RA>ftHk8yY&Suz>9j;rHSw*-?l~3H!ayB@a2r(j#K}u z;vwvG{rOq(XH-)`M3Mvmjcs}QO*iqh!Ro7?q(26ylUY1hRWj7|{3` zoDGU)qRo!I*g>v_^d4?;4oOF@Z>Uo=GF>ucLcXr^KHW8{;tIPr2>n*akLfa^eL(o$ z;?z(59TfgJ5`+alfeU0+)!Cd;kA~lnWb8ypcq=`eRr29~xZWH(Nmn!iCXp7H=t#2~3o!N95h zx^XC;=&>7*&3RB-!#B;t!I$tH?mvY$K=uNbxU~fA;#RPj0{f=CGS>zD8`$g{>~`9a zD!w2N=&b^X5%_#W@8DMtN|W(@1_rg9R?}(8)9V{izYiOYsspxsZovnU-qIztoT${T zy6-v+$huY1)}r;ZvM?bP*ewzOq91r%9E~xdFjKW-sdXWzp`DK{d#3YUN4`mm|8iAt zmLNcLyz5zbM%m}A5s=%lMiP{UPL{z72buvriAQ2tFE>0TE>6nD+g)zslWd&WC}2A% zvZfDr2iJ&$CC=06x|0et53tSijG67Mr4h#MYuhtK%9-jz zwgJ9=>V^(XycPTBwwTN+IB3o{4A=={neTvSNdbQ;JCx}stV#KyGeT9sur$Qr1ilyS z3b87|hcJP&>YOfdvpkpL!f1_r9jk;Q-{QuULc)o_Qz{;xVPs*#v}yCrPPQNS1RI9! zz#o0)UA_2J_zL1UC@}Xo-oUd2jh|jYgcU4UJvxpQ z$zBRPyQ$Wm-x1`DNOw#M{|CX7#wFwvtQs}TlkVUgkfr(zqKE1T>1RxT@0(`HFf5@t z9Fi8bM4EuZ7?q)Ci0f!wf9p-2kV-pZpN=e-*X(l#1~#@01QgMRb><;hv8wCVny_wq zAlq5rgN*0}-h9#qZy?qD5GMosTUZxIIQWbKFWKkrth6!~uvQNrwwOi`6yw=>ji|7T zdBzMHb`D6)7R)>|bXve&Fc^(=jQvPV1T1bAaso*FiCc6wqyO|dJeK@D9{spe?2rDo zQ`{Z>VTT)QP{Ec7L3 zirOXjJ9)~P!#%AzT5=HA{OBZz3) z@9LrGE+V1!ruC%RlX}gbI2G+I0}_1Cu`}W%p|9QXxl?_#V_5*k1xrUwAzPJa(7xbI zics(XZq&#D*>1f$-{Z;h3I_9nzTHvsb?*)xwmv2R71pnQiSa4aJH?dvDje%x`=xuf zP9kDYfI^<56MH^2qp$^BVN2+Lp|UVc?^O9;_(rxIJyQ7==EgYywvJb1Sju@AAKHq9 zOanwK$n@*JudC&CpT$+zuCU{rk?yHLcs^?6vxjw~@rK*<=%E$jJE7N>t2@+EfF^Lf z-Qr=*a{+LoyQ5QvAp$R8x3o1SAT)IHMe&_7lO1C!aI6|be%Tt<{sB z8lxM=nR>T7*&wk?0|qMwpzy1x3VTsI0bFYC)@(E5y`c`jqJsgcI;8 z^<1R$*vaK%##15FW*`a~%k|XW!MAXR#+vG3f%`0ryoDMNrX~Y(*ScPw6XR2acdXX8 z7!b}gRMhcs8me)=j(-ejB7!p?9_;ETiAREV2il~2zezoUNC`q-YT5InKjz^$9$_GhXqVQGJcS0Etb=OPC? zbxb&`aHT<+1qT5fTc#-}mh4AZWrAK35Y!Za)G!hNz1x=(P*r>(G~x~d`;n|?@ITup zZ*EXo>Cr_wn`w_$k|`rr217{AsaFy+W~IH6Ls|0!o}%9W%TDplgRWZhB@aL-tHtF+ z4|hGOKnZqS$uBUBMX3lQsS?V#UudBV9Njx7Fa9K4oGk=8cPZiIavNp$iobwIat@5I z`UaFAy6iYPpzGcOuHk_l6q!~A47@c4%#Kd_Uhz!=mW6bY1`@-@JxG{^hoq?3V!?LO z{4d{q-!)96bwIKl0r8id5Bn6fI{`QA@EdlRZPjdXRm<ybpaLLg9?;7;X%o}VSq zo`f)FgsmuDP|)2iNYjKGpfqvVil?%Xi<4a#z9-fl^%6aSKH0@-sP1)~cAr7T7vmzd zHmcyL*-AiLn3Cf(dRjr0vySh>=tWS2gxgVfF>CUFVS)5#f!Gn+NYES4aPA=HM)Rgx zVtP1!C%xIK-tF=v35_&LN51 zh#(79g-h1TO!Z5*vuduwzYfKQ3{#7}nEkL?yp`VVK4AV{_+x(K?FvbICa6A|y znD+z@I}i-F!QKYRQ)hOcE4d4Q|D%47F(M(1Tq6?8@WZ(v?!3iXxf_|w(A31@9 zkQu3b7LgGmv(($JWi-(P$31rGLJ5uF(?%RlFm_i6^TR0tdIgPhu4=e5h>@2gFc_rz zbX6~x)Bq%4E_4MqDy|x>>l*qw;%mZSMpFXD3qX;fLQ3!d1u7lr1S*LB@gTCL(9E$S z%@fpQJLe$kGA*f?X;$F$rti^EyjS=~u^V$~>Yq+=70ntkrc~QRCyhW=A)fM{ovoAm z0}asTe^RMJGr>C(^$tMrD86;hBin_ITNehrsj7i8IZ-(G;W2>c&_4^9xK0EE{C--t zgR4XUd+P!3VhXT2i%>C61y!T5oird&@k8f;DggdVj=%&!sCI7|GD;IY!KZrzfUBoa zIpk_#(#mVcIm13(A0h~#npDg2V%@$XAX|>;X1!yaXU4k%hIo}(<`qzbYkhzaIam(x zygb)?lNezVe!hFr{mkB1_xpECx!yB+2)mA}?3_yb-WbjKX?@sD;q zJlU+^9$R~Sq#y5OU3sA&kj0JC>F#Tum#CMEkpy@Txo~pJyZ+&~^es8&}HTPn=n+Fpbe{E#{;P)FaN}tal_D{enVz zSEfbYU#7RZMU?{O3S)bY$Y`bJ@$CNbPH_mr(c?vkJ4h$FEiStQ-w&(F8>#ew3{IIE zngCMii#FwQy$^N_`66GnL{AXG@Hnzw(4N}$8@(?oKj4z9-iqUMEALQ^tF&8L>o}V7 z8ASJpJ6pX8_!WXyHI_D%lho`cNGwCldiW6n&O-?!t-}vFwFZ@eP%IlMxhW`-esU4`i+C8FiC|D__M2yAky$>WH#%pL=}z}}1k*k`fslD%-4-rV zznS71_*PE8xVtK04gVD5)wl*;SvMr484Bs}*2z-5q2OvfPr|cUqbHgN#iT3UJX!Pf z2CDUlvy?RAi*4(Ci~+uP2>T4@=|u^pM*XZ7BA)qNi?7NV&bQ^0?>z)}@LF%{w3N+W zbizgj8_60_&4=2@o4kngrE-DWK7I~h{6W6L+%>>+sm4>dck3W01{eECuI7kRxxgh8 zJ!8Vc<9xNkX(+hVT0`0CqL7nX0JFOKV=+Dh6SG?&@ErT0Htq^6K@VxvSs89%Epd4}yE#*3fSK}_FapffL{^ z3ahGasAbKV1*D5WH8CNIWmV!DEHx9Kz2s2958m$4vnY%#ss{Z{9E@iqUOlG-pM9GU z0wo-PbXT}gEtU^(yF`2%pkUpD# z-XT8>clI#3N`#O^8lWIG&1_Z+kDXPI1FYXz(NmNn2{#;F2gFN?a!jPJk|?j9589>mhWB<%LWJ zIkvFhahWjQiKl>^T=K}y1PKe^LPo)W;>ilMsza0H=!JqywHGQj^fZLymo4o-Xf=x6 z@RRBZZnuTsMgifss^H=0nAwWLuf>MaUG>ZygfM(8KI*?I@ggRwNw0H0v2@YkfE1*6%^Wy+InS204I2Ei6*|!)> zo659!9TAr)0YOq&zMIUzL*ACp`@UjJUDu@jHQV!XO12RBoH8o8#YC+B5ZZK6ZHV8h z0v2)21+c|Rsc~>vN-y4Ak-$9VRqWzB*iOFNzE9&QxMc*#dSbzwmb~&50Kh(D`*8>_ zJxm9bI6X|YAOp{m}8X@BYDf$(4 zVKrhMK?h_DGe7zCi6N0a0d4tWi}2<3?RK{b`@^`%W0t13l0gKTY}ygXe2~^Lunk3( z+!tO~GNuqhw^=?8PD3m&;#u^HsV)B*foEx$iG83Mg<`lUq;p5YQJ(!vzQIO;>xi9P z!{ZgM-eWkqZ7*Vl}$N-i&R{MHUy%TkfUVaF25wou2_(??PPzOFY*3S+h;8-_el*LMPm=r8g zIz_!VL!Eu^M5{u;{&e?K8cwueQA>NJ711{@mdVUyRGib=p+N^`jQoKx_oEUCZQcWw zs^d~G?f`*~L_r2!>r{s^dF+$@p{^F&cl_D|e?fhPJ)q|{oI8BC=Mr%ZOd?8xc4s`M z_kh9?UHP!mC#Vg#=osdZ1}P%c2a^L0i?z5wECwzXG8vy*IBM=u{~JPm9?Kx$BGn>m z!)dP5lyr*&BoihY29C20MG8xtGQ)w9-chX2Pj^8>H0(%AjtZx1U5wBVvoyXxWFC4P z0rOY~lB9nX1Sxr|-3Q|wp|+p{NealS?n=JIkvvg~&80qY$zvd`I1z3Lx^r}n5`w_i zqJYbSZ>x8MTq&%KRR)aUCTxBOVV?z)dEq{s#N_(!q7Bbbjdt|7Ph^{b_|kzYYXAEd z)Ec3%dpcIY6Uc^{8NeF3(`6ADWi0dYRa2J+jI;46R(FHodw%w{O!xbdk-V`2U1lHL z7TN1K_}5Y4Bgg{Xu&sd<0v+tZ+kljTQZ@TFg*NAOJs{H}Re+ipmg67?T6&GX zN@u*3S0;k8nr8R>WX`$3X!=eOl^)Dd|DFm2j?v*(Z(3ej&|`i1Pz{p(HO!b(tRV%o zPnuw>A$`N=N8&Ydg{Is5usR-#g_nMkZB@S8#|T1|6PNFV`j27%3%VsG zv0$o&3$-Y6F+^gA$N*UUj$$YuATB{hD&MILGlb`AR*(H=gsz`_NrEWo4qOBS0INqd z$h982<9b85+}`)S2Hie}v++kt0=i;;`2W4RuQW7_G5*$rKcOsJ zc%NNP4qj^BE1~9$QlxY3`=ihHj|{~^-*Bbh=2-@KW6th^H@}_F&Hpy#Fl0jV<_YKD#Z*47^ps=$bCr@i(sg zPrbSZ0(n}dh*QK(+Q)&M53dWV-L$xew`Os%#xxDNrl{ylf(xqF=Ps;NSx(gFf7QHW zH>OPb1Qno8d|7*5E(Kcz8qVqE2h+a?)5HSCy&DV`8 zS3-Pc{J*44wu4K~aG><1o!tWWb`Bo_cwJjbw6x(t{fGg(uILb}|$49*jh00088|>7mA+B5lQf;82eJ{E_#apdrz0p<`38QPJba zNEaA9Y>`cnV{Z4+vH}()e4>2)GjIDGj1jc7LNdHzSqORVsiin+=%p73)M2m>UHJxu zlWP3XuE_HRIL|a2FhV`#`wzLRn0;@@E?fmnfDQsJ_!ojhp*w@G!__nzh2{X0>v@vL zBjYixdFV-!90i7`HY8l-IZmslZ%WmdC^yV;<`s2=cp)L#*51?8$mA9W#1tmXdPfp4 z2iwDr6+4{$l>~{&svuYw9$rue0#%SPzz6qr5wp#|^+`4!AR>bU{=p11GAtu7Mgwzz zZT92~(~;8BL+6MNGveJOtete3aGW@SAF9O<7(0hvQ74~%-MH9CxxZ=u>A_P35$E2R z1TcmX<7kFk4M?>BNyZk^H38=W;?KyN_|b%nGi`<03d6p$1JB!zfQ#2lT*+i#hpC zfEGg78&1Lp@qyu%POv;i4%e*=Pp3QIRgjQ2S0xCmOc>?@7Hc1E1;g zpsu?XwHeG0$EO<@5@Ve2PY4|>C*ntAQZ31QP641A<+PS0 z0OKLhlwatG!2qJTAbOl>5qNwYGmC_S0;PN4XnSCa;PVN-@(GIzwBw&XP_qk+0U@&z zqDB$Kgbh+3@PI%8jU4^>4mDj5^{vDycOcD0Q!;-*!(L;lZoN%(KDvSk$892i(Z z$a;ld+2n!`y<%JBvxC*yT}>ZlL8BCoEph*Heqpk$8Fe)4?%+t9pvEN#y=Ch5!6oJ* zPi~HDDitrat$_+B`4eRRU%#p^pVX_b;12?-+UIl8O~eZ23YArFBi5E*!4`f3hu%Qr ztj+=MG_-pU6)+t;27_K9k%(L}7y=VLKih9!NWf#PC%Bv7Kxh4EgEuJ{#yA4^|KU(vK? zA3l{no4TJcrGL<|?!)iC?`lqgVaQbJ&DbnC5AZG8(O}Un$dkz^n{cq@Y!#WdBAkQl zVrb9-XUg!9!9~(PY_^uq9}RMp>~I4==HYOoHTeV|I{EbEf*->YnavII8a#I3`2(74 z8K04%5}x`>4%1bG=mJPx!_k#4Q&6G8L=9l z1-(I}j6}!MR?!XR26qoabcS7dql-z`)xLgm9m_gw_aLV+I~hiyZp{tW{l-o1_T=PSOBc!J#^az4!*<1? z;8z`!_+{7;?-AT;L4A$;IJYiyAk%*0je3T{M|sTug$ThQszOKnOmUYVD}~RU|*`%J} zh1GmYoqdCitC#UY&>j>6O^(D1iiq(-)FDq15MUY72gB525)K9j$#YJUm~8B{;(^$% zBYC;p({zm$X7!TV+f?pB#$hZ~3Yk4@dR{I=im2Y6d>CnAUGYvQE|(&T4vjas^=QDW zumjjK6$rZ3T!M8SG~@&HeBQYCiR-80cfjUJ8ZZ`&B3TSZKDF&1#VOs%5ZYhOXJYKN zFNiLof$J8BZ?t;y+uN^=lBTX#h?sYv92@P05)T97&XW-xp%(8U-xyxRRpspky7(&> zUrtarEU0Z8yZ8$ylDtjAjq^LMY9AD&A|+N55}jE-2eLN3>&zU2h!a+4bg}&`K6h~^ zj=+W0@q3YBpq-ZMOL|o9Lat122bBN?$_cxpA1tIPhSd&&RVN#7C4>5K5kxZ%n;VRD ziwFA{i)?z)XH5RKsxec$$}J?i0Gab5GJP_*akpDMAvX1iQKTo{{T#u8Ow7-##1xT4 zks~f(3S)kL_rJT>HXRxdfMfEEos=}H+!*8HA4j183M~M2L>9-uEws6 zxb8EdT<}O|K3THQzWt`Ex6)69S6qX7F#z#Fwl+x6E!}GtL%X9LNgsI*Nx{EQvfS+! z-w<5VxnMpJCu8vRM*LLLoMU0}I-<)ASuLpPXPcS1AmNolc(B}N$Mrm(FTLg6Z?I;p zi*qO2A3TZ4k>W^>vZF15Yy%nbgC0Oseyds!*=$kz#91bYUiqWnU7=~`gA#`OkX8r; zw!yxOyGwFGPR#B}$W_nPdHD3jm#>c=@4q_u>h=EN)7O7_{4Z$5m&AOQuFVO1&H%*- zDiycon;Ue{Ms9sRt?liWh&j6{qT}viwq<|IFB@H-&o%(`3lN_{k{CTWZilMBZ5nMW z%Hs|kKSQ6s`#$z!Y8zI%N6irs-e>NIF?XU;z6r@Zd7{lZTLq?2yY!b$wN>M}TH}rA#Kw@Q|@MAUUI7 zwRjO??IVmdT8s*`;|9J<@mvn_uC!yhl6L!kk2TeRay=P#0AM5?ff@ij$_u}8zWD-v zcwC%yRS|dnIX@gLIf4`TkL1PgID__3?i|t{Weuk8wN+uG`8>!C?P?m;qQSjJPl37I%Cq#%IA#FW~%;q{uw0zC#%5f|~%ppEK z&pG5?zhW)6svfXII^Ft@TLDB{+X zL`VEX6CC+oXQGBD_6$Qij~*`^eNg(sR>nNfL+Ggs6Xqa!Hd9vP>pQTtT`9efRFu3| zhlW&VNOLf`M5(5SK~rF5C<>pkJf?Ti;uh9NF}qyb$sN?UFN*ES`kiLkvr_CC1Fkhq zyR)4!zgB;~zCO$BQ6zhANt23s%?>3z8=sa?>;M}R`MCzSOWIde~LVoCS z4)+IM4%e^}pm};~PGuGKi%S*Ie$9&P}m zk7yHbLpeB)K7mzM zZQ`bNZbWTJQ8uu|nS$I;SDK(Lj%ZBjv0jmWxsvT?yBP%BCisWQ-vQ_F&&5Neoa<#I zAZ#6@MQeeFVA@o6BM8he6VrZ6&g-9x{d2epTPeG`NT_B35mYt;cNW1CrIyt0(G?c){Ra*hyh+W=I^+XdJ}d>hGFm zh?-(LXr^?=0TMi65M@^JYaBjyIyCai-{6U(VzC(p$b8;`*S0ok-&n0GtpWL!kL0vA zwdO=xiV+hb&|!zfk*pgfFm7NZV#$}YHG&PCaH^bbM3!MDYe%&ndS93P#ZlBbO9l}! zI#}c(y{U4QMIpDBqU96jsA3781o@h%!PW%@%RmpLe)K?L@`Qi)bh3}bnVUb$wvN**UjkybI%BGFqh#>~l zx4e=V2TE?zWIZP3t-N4ujGDa&riZ8vu87{$x6?>KM!H9F*1a%faqH3A?+^q>}?iqUIA0ZM)yZ zKP>$YK_)e1b+4^PfAEbJZtjMQbA;a=#)d$gAM zMWVb#%b^xsPPW6#N$u5&^e7z(AwCM5;Zl-I7+I5a&f+8L06pc$kR;AV zLgk)%Py4hRcKozo!^tr8k<|!37RNgxp0x1=z)0nU%%fc?@cnGIy|r4?Z`XN*_a*QO zV4_ZSYq*Ten1|XlIMl)ur9@o{GuA%12c*Vvz1_=rL#^|AT|X@X%Xj zPS4k8uBlw#G%&OCdOXXf($i-g5zWHBXG{MP`9>Ss7g6QugXl0BU{d02v-gg)DgN#nv%avQr>RHWViaUAnn>8Zvf_p+pG_`J5HRG%bJe^YVa0f;h z@(v(}D2!#q?!lUbnZ}nVcA&k!v-xrTmn4T&>-JjqM ziFvh|+cdM;p6Vz7cFU_t&!v zhX8ooEcRdc0BOLpY^+t1NA@MP;!CV3Tmv}0s#jwK>xJ)JSbcaKX`65&&bA0*k*AvZ zP@{n_)n+xkDTvKQC>UJMaC%OV$`-xi@Z5ngkkTIb*?aM`M3mWMFg`XYkC5mP83IGs zhsX{Q*Sw9ZZ#_vX(ih;ZdLI$}GHeIuOng6QiiLa5>)84Nhn|xi*y_pr!A`g=`T8 zw^bvlGh~4SLUS_$(vkHQq-RZA0zDDDv7Q=h{-R9}OBV03R9A zj&!j{%-=jh{~3|8@aq+ybTPxSz0}9``8h)YPp^1Qfam;VBY6Dhfam&)_2>u>C-NPr z(P52fu&aD!C5fu9=|`WCfHayk%X~^wd~kGl%^D<|PVdIzZt3yikv?Z2iIaI_L4&{- z2sTIhP(;^AJYe&mI75YPBqT7B6hclMMsAWnR6rN+R(i3wy^ua-gwibVd?APrS>18h zsQ5D;-O`rIzyN)akGFtQZA9vmX%?66V}=201>wmnu|Jwk~#chP1Qr=4rBi5^CQ?*%_|ub$XVgscOuctsE7*h55AbUIz|@S1R1GKvh zdN#})`4&1AaeWr@y^B&@=(^}u=Eb_6(#58?@O0c?xff!P?uH)*H;Y$T0rg!fUX0&X z=l#rJf$U!$_@E4Q3zdO&>XPB%Ja5@W2u@ByuA6SNReg@{O&=QiCn2T%6vt zerH^i4fIjt3K{QucbYVKB#^JQ_k58ntK9}t+((k(b((G)#2ELDjfV*axGda*>rIz6 zK-%N3UAKSaDVrd}O?Ue=8(c#h`i83wlkUnQD6lht1Pb<+_U&2J#v|(KJ5t6xcssG% z3v{MFbW-)|Rz_iWsc7T&Eg{R-RhNk&(^^m0C?qrNj)@Plaias<{fMX4-r@FOOTmiYfKj{#G4Ppc3O<=K=#BVay>`^w@E2qt&h=DL zLg2bI6|3XsX=_&1VhLYdOTW^)3Kkp=6SAIEaIH^^`{GV}z$A5iI({TSfemP7)`Q%R zRwXT|QUvX+t%z~fw^hWR@m@jH#MspF)w`_i)sRaSq6WY^b z*=?uCV~RLCw)~Hpoe~EUysFN{>$UVW@ojcot=M(nsc65)yiPYorX2n!0F;FH<_JwF z5B7{`^q&>`PK_|%z!fF0DUw&ehpR*kff^}2v&ZRjYa+y>=EcKC#sM_&H*$qr@emg3 z{Q>)p0XTv+HF;wlsl6{Haa|L(!wbkz&tV(R%Cof?hvF-ezvf8%1smWRn)LuXdi%Qp zNw_tPN4Cr@;tL%dyj*ev88`6ORfF?(jq9h>@;sxFntugG7^6Odj+-Hcg*Za#MT=H6 z1}NYFLtr4x2s<_NI{9JFO8Iah+0r8SA7+o&BTw(v=oNc&f-0Ysu!M*fH72Fr#~>aA z=H;F~7Wh3E6%1*Fe`n`iKPjgOZgnFFBpHH5NyZcB^edKHdK)D?&mF8bi05&Hm>Yy$ zr#Vc|9q5^u?PDNcf$!u}lVXnXv4JO=%pdzPz-M>rJ+@f3_(El$XCoQ?V@*uA3wF8) z6UiY;*Uf#|IifS%=cqVF8tX6BYaRq*{1|AE!A9whbQ*-3^9?g+{hH~1$%GWxK0%$) zyTk!-dl>8_XG-iw7yW%|i9dzGEiTMhJCq?fN}OmxF;gIUSROAB6+PA+wc<#mS_O0(dX= zSRJ~PFNR+9=yJhhp10cDmXx7-sHll<#-|ls(`vvlHk(JPaEel}*F*-4WZ!F8LzKO( z%F7);Yqa!FxLnK=Swx=rDIj8+#mff$A6mmx_~H<6E8*=gPvIOw`WT!nNf`CVLLmUf z_0@GfB7mdn3@2kH45v0qQ4P@4-=Nadvlmh&LGPf18K9X2vx_mpj^Ta|$sJu)f>#+C zILOsZD=^lI{7ztdmL!OQ_r#H?)fBBoO#U^wfV}`jqPf;8<_LJGm=0_Wvp8fQxXvl9 z4Lhn+>cXe;1ji)gY_1C{22Hg>g%>rA)f?*^V-~?Q1&>HlzFS`$?S@*zy4W*44Pd;9 z84QQv+!SN!{rC?y9pJ=5YA9xp>#-d|@0}9}ie{`850uRh0M-ai8EX$e6!w;iIqw~> zgfz%CFQ*PnGK343^!@;9VVU|c*Zgz{v)T+Re5!K+!36Q`E+EqLlfdtd96kGNc7PTAHeSf zsO;3yIKiKf^nzRQQ{0mKOnGd<40t>9oN54O`2n^(V-b2c<4U>(&e8x7V-CYsd}`LP zYX~EpD$J52zxPm0*uii3&q(^n=u=9FITzBdDv<}K%ep~2I$Y^tH;fIjPTp(7L^xsx zs^sOX*CweH89XszdXajAq~;;dh=f!zmWtFCgb&_;Kr9ln32B5?JdeTBG0Wk}5y zgWc52P|xY$!&0)yTn`plQi*Q{XSH}}2#4$M<8d%OTesRP6HZ-CFI~w~z4mMDfv2~4 zECwkwg8~^4_CciH=|?Fo7AIQOA&B}YjC*^<6_%444-8Q#B$>J)R~}p=O_Ao2Cre%i z5fuw%h?rvh#0PQ0xQA>c!;;R<%KG-R)Jrz>F#rkg$*Wh5c^}Pr>bjwNgz*6xzT`Pz z=y;Yt5Yd!8Lgh<7&<3Ev6SQKFX%M@i32GHXL)bURKMiV)I)mb&J9_q(2zvDLxkK?D z2r_u{KnE+__Q8GcfZMgS!!~jb7)7Z|d#WLOwvd8gNM{Cm%4Mm*i}Il*3^QGZe*HY% z59(>K?Lb_5dMJN949JccQ6_S>2%AI;c##+w#xcgM`cZ=_Cb5eUoW#>l-9iP z{xR-(BBRCwd8gfh#)V+ZZWYXL#NV#Y!HiHhkvGTJbBWtv#UJHX`TqYHM1t0B2 zl>!(Mrj@|2+Y}nPdqA1gP4L#zY990iwySz!>`c@i*q=z%i1byOQ$#BqT-1o`vT!AO zSb|j~W6BEn){zokTH>KD2r^d9R4xfZf67C+FuJs4UZBm5+&dIO1($ z+KC>79pb^s`b?ElCya}^u<_Cyt>1}44Xh`MHhY+sOdnS+Ch+8Zj|W6Fw0K^@q0`i7 z>)mr;adWy`)q4mU8dpkidx$JAp@vS%JuPVVj6Dxoa39>EEwAflx6{@XnC(k^4M#T|?ut-kj7!b>ve>x{hhZ??@hC*4wg|S;Ha>tEZ)?Uln zI;5;*y)*rRA;PpL=m(SJJl6(r8jO@_eWrP8g%necbLSe8)p{?Jt(IWQO_Vmxc95h# zT|SD~Ik0xr_0V*$^m271_bu;l{m;95>&X)NXlaXFfGx8N zrxGXxeKE^nIP0y;$wLh!v?f_oRwd3w_f#&g))zQ{9?uZP1O;4wAwlfi{tgIk@Mx@a z9x@x~3z8jBz z+#mhz?&uG%N8kUQt+}Bj({bA4JMkbW-);^Cq9OH z<+&Ag3|p5&Hcgb4_F&HtrpBJ}Fe$Hw6~_mM1vCA*(xIJ633_>~)|qG23i~11pshVj zug-EUijljZgb(+tNq@QKj1CX#&% zK{40NB{aZMPz3>)rdI_~FD=zqMi^Cy1?ohYeSE5jnrxdWcumiV+lXw=#3-N-Ku(e; zOU)o>0h>9G?ZAI?pA+ZlS;wLD+TJBCBeg{w<1i1fhT66Fr+#g&8pIUaAWm3Iz}_n2 z$Z%6-(8OGkY~Yhko_pjo&uM^ zGNiX0)JvXcGCh_s10s=!EN%R?#wWb8kI#`ePq`lDgS2i{UDpS`x{+TwF@@=7sGiiz zD_mvwK^)h?nuqcR8V%k0_hh>LsORgtm@7;Go`=(Ygh$!5gwXn}^FlJ|x=3pJ4F87cT*~U&Bv-!kdf@ zo+T+yK!@N6V>ifkFP&kGEK#JQNxBV9hpUhuIs&*ytinsy@+=R$uXe9Nysdbj8ae}W(v7R#9}q49N@4p5p~Fpg zIy^OPnoFt8;d~6&3>J=uJm}oo-H{VUC0v_>K-xEw@b&gcUF!DnG&?Xwg(ZYG6mc?w zA?QS46W|q|!I&#oF{lq=w(9O=T`rCP4psY+(U(P8x^V85ayKEh&>^%hyZtTYv}=@| z2Wtj@_?bH1V7XQ1WJ^qAsuPCj&zS66-7#mW_ccJ*N5IJZp$>Av@q|qL(h2rF-`0WW2Ql8*1902ReP!`D!9iXu&l?69LX`JO_oU7;z z6qlw5e)1nOO_|VHU2{T`WdPa}Ugr=c<%IlwdkbH;?wkzF?YHWNQ!Ilg9UD%L#L~6Q z(lWDF8c)ndc}w0Ra2Q=gd&I2RhR+MfAaZm$f{(tu<%Ip5XD3LOLRd^zA5W@ zRN)FS_!8>tyuj6W<@=pKiaI9gto`r!@dR5X*+E>qWN0uR=>yEUkGsgX_s)~;bo_`3 zETQR~(3(3TBpt3mMz+rHwHCJgM|A65^ zh60!=?xN#J{0eEa&UcHg7cY+=Z!xfCOJdZRrGhGfW~MIW>n(7%XMIam2ulfJ_be6S z#puT_nkn@WMrTp#WBZ6X#N&>{dL(;MNj}i)Bb9wY$(NHsAOu_*3KtNk%O_VnMatX# z3#6S*Py}@X!VXWgk;yCSR|WM~5Iw>hscj^+4Ky1Awm6R)$EU6_#<8S3NMtn_`Y08+ ze1b7m8B(koEIDHP&NdX~5l^wB1YM%#MamXMfym-jFAy~nkxcX$m2w^E3f6|P>}1-~ zWFNDm^Fe;NIG3GnvQMygjNRfC%$=j7$wty~%qN141%C)`m5=_0=l({2kQ+@z7{e*Z zPH-0wSzQ1yee>hyqD0Vy1V+SX6ZM%vDhI#+hZK+mWpEIszfkp(Gbdy|1)P4fZ#hgh z5@A*u;0UjIT-5M_=!+c$>r(m%!swJPmr2EWQt)*SFGcrXQTwsmf zo>3H{rem#WkBOFkiNnp&n}xi9N%o59UHC7%mW#Dvm(n=&8jQDMe-sS#-)_{AEOf?erT=nnb((Y@mNqtF5Kfe)j;+g$4FYZDP_CRX=d z)MsMzJM!P+-!SfepeE#cl7K{VVg#V`byLZL1zSZ4AG@l9ijG^rDM_AQ6d#;gRSaAu zZd_X`EmvOLO`0T(>Mg1oD zjsFO8XE?Tp7OR>MD^hm>bYO4+{LDrxe!&@&_+>sT5|vK!yK9R0aHf;aQ*?|}(Qx%O z!G$$XyULk7>sgKcY-u)*4@jd)P$uL9rDfx%EZ z1ZB|KweOD721Sya9WFa@Dumj;t3fCF-2`*JYV(iQ=LCiP())OcGlbq5WTX?-oIv!; z1YBLD_jHro{L+cTH>5lQ1iHP27~(T02`w{DvX4t+!?xVxw|1QO!bCX)G3-z5BoO4K gJ!k|dJYhJDt(5|jhMjkK%$MJ$fL1>V1qj3Vza?B%(EtDd literal 0 HcmV?d00001 diff --git a/genaisrc/tsconfig.json b/genaisrc/tsconfig.json new file mode 100644 index 000000000..510eefe8f --- /dev/null +++ b/genaisrc/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "lib": [ + "ES2022" + ], + "target": "ES2023", + "module": "NodeNext", + "moduleDetection": "force", + "moduleResolution": "nodenext", + "checkJs": true, + "allowJs": true, + "skipLibCheck": true, + "noEmit": true, + "allowImportingTsExtensions": true + }, + "include": [ + "*.mjs", + "*.mts", + "./genaiscript.d.ts" + ] +} \ No newline at end of file From fa1a2cdc1e5e808c59f6f70647eef4415e405bd5 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 23 Sep 2024 10:10:46 -0700 Subject: [PATCH 129/187] disable simple check in nlsat Signed-off-by: Lev Nachmanson --- src/nlsat/nlsat_solver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index f2c32cf6a..53d7d9fe7 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -222,7 +222,7 @@ namespace nlsat { bool m_check_lemmas; unsigned m_max_conflicts; unsigned m_lemma_count; - bool m_simple_check; + bool m_simple_check = false; unsigned m_variable_ordering_strategy; bool m_set_0_more; bool m_cell_sample; From afaa48d72af0bfad47a3b3b4cf745c3a6f7f1714 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 23 Sep 2024 19:06:23 +0100 Subject: [PATCH 130/187] sample fix script Signed-off-by: Nikolaj Bjorner --- genaisrc/FixBuildIssue.genai.mjs | 21 +++++++++++++++++++++ src/util/scoped_numeral.h | 9 +++++++++ 2 files changed, 30 insertions(+) create mode 100644 genaisrc/FixBuildIssue.genai.mjs diff --git a/genaisrc/FixBuildIssue.genai.mjs b/genaisrc/FixBuildIssue.genai.mjs new file mode 100644 index 000000000..c4b9dfb03 --- /dev/null +++ b/genaisrc/FixBuildIssue.genai.mjs @@ -0,0 +1,21 @@ + +def("FILE", env.files) + +def("ERR", "/home/nbjorner/z3/src/nlsat/nlsat_simple_checker.cpp: In member function ‘bool nlsat::simple_checker::imp::Endpoint::operator==(const nlsat::simple_checker::imp::Endpoint&) const’:\ +/home/nbjorner/z3/src/nlsat/nlsat_simple_checker.cpp:63:82: warning: C++20 says that these are ambiguous, even though the second is reversed:\ + 63 | if (!m_inf && !rhs.m_inf && m_open == rhs.m_open && m_val == rhs.m_val) {\ + | ^~~~~\ +In file included from /home/nbjorner/z3/src/util/mpz.h:26,\ + from /home/nbjorner/z3/src/util/mpq.h:21,\ + from /home/nbjorner/z3/src/util/rational.h:21,\ + from /home/nbjorner/z3/src/math/polynomial/algebraic_numbers.h:21,\ + from /home/nbjorner/z3/src/nlsat/nlsat_simple_checker.h:20,\ + from /home/nbjorner/z3/src/nlsat/nlsat_simple_checker.cpp:1:\ +/home/nbjorner/z3/src/util/scoped_numeral.h:96:17: note: candidate 1: ‘bool operator==(const _scoped_numeral&, const _scoped_numeral::numeral&)’\ + 96 | friend bool operator==(_scoped_numeral const & a, numeral const & b) {\ + | ^~~~~~~~\ +/home/nbjorner/z3/src/util/scoped_numeral.h:96:17: note: candidate 2: ‘bool operator==(const _scoped_numeral&, const _scoped_numeral::numeral&)’ (reversed)") + +$`You are an expert C++ programmer. +Your task is to fix the compilation bug reported in the error message ERR. +How should FILE be changed to fix the error message?` diff --git a/src/util/scoped_numeral.h b/src/util/scoped_numeral.h index f70f5f185..0bbae754b 100644 --- a/src/util/scoped_numeral.h +++ b/src/util/scoped_numeral.h @@ -97,10 +97,19 @@ public: return a.m().eq(a, b); } + friend bool operator==(_scoped_numeral const & a, _scoped_numeral const & b) { + return a.m().eq(a.m_num, b.m_num); + } + friend bool operator!=(_scoped_numeral const & a, numeral const & b) { return !a.m().eq(a, b); } + friend bool operator!=(_scoped_numeral const & a, _scoped_numeral const & b) { + return !(a == b); + } + + friend bool operator<(_scoped_numeral const & a, numeral const & b) { return a.m().lt(a, b); } From a831fe9609488a98ac53fba725bb54707ae27942 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 24 Sep 2024 11:15:47 +0100 Subject: [PATCH 131/187] fix some build warnings Signed-off-by: Nikolaj Bjorner --- src/muz/spacer/spacer_global_generalizer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/muz/spacer/spacer_global_generalizer.cpp b/src/muz/spacer/spacer_global_generalizer.cpp index 55bc4eec7..e4b16cfbb 100644 --- a/src/muz/spacer/spacer_global_generalizer.cpp +++ b/src/muz/spacer/spacer_global_generalizer.cpp @@ -223,7 +223,7 @@ void lemma_global_generalizer::subsumer::setup_cvx_closure( cc.reset(n_vars); - unsigned bv_width; + unsigned bv_width = 0; if (contains_bv(m, lc.get_lemmas()[0].get_sub(), bv_width)) { cc.set_bv(bv_width); } @@ -232,7 +232,7 @@ void lemma_global_generalizer::subsumer::setup_cvx_closure( cc.set_col_var(j, mk_rat_mul(m_col_lcm.get(j), m_col_names.get(j))); vector row; - unsigned i; + unsigned i = 0; for (const auto &lemma : lemmas) { row.reset(); row.reserve(n_vars); From 716a815ce169492837f95bb7613f8ff6cb183b98 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 24 Sep 2024 11:29:35 +0100 Subject: [PATCH 132/187] update lock file Signed-off-by: Nikolaj Bjorner --- src/api/js/package-lock.json | 6942 +++++++++++++++++++++------------- 1 file changed, 4352 insertions(+), 2590 deletions(-) diff --git a/src/api/js/package-lock.json b/src/api/js/package-lock.json index 0db00bfa0..432e00568 100644 --- a/src/api/js/package-lock.json +++ b/src/api/js/package-lock.json @@ -1,40 +1,78 @@ { "name": "z3-solver", "version": "0.1.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@ampproject/remapping": { + "packages": { + "": { + "name": "z3-solver", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "async-mutex": "^0.3.2" + }, + "devDependencies": { + "@types/jest": "^27.5.1", + "@types/node": "^17.0.8", + "@types/prettier": "^2.6.1", + "@types/sprintf-js": "^1.1.2", + "check-engine": "^1.10.1", + "iter-tools": "^7.3.1", + "jest": "^28.1.0", + "npm-run-all": "^4.1.5", + "prettier": "^2.5.1", + "rimraf": "^3.0.2", + "sprintf-js": "^1.1.2", + "ts-expect": "^1.3.0", + "ts-jest": "^28.0.3", + "ts-node": "^10.8.0", + "typedoc": "^0.23.16", + "typescript": "^4.8.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, - "requires": { + "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" } }, - "@babel/code-frame": { + "node_modules/@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, - "requires": { + "dependencies": { "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/compat-data": { + "node_modules/@babel/compat-data": { "version": "7.19.4", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.4.tgz", "integrity": "sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/core": { + "node_modules/@babel/core": { "version": "7.19.3", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", "dev": true, - "requires": { + "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.19.3", @@ -51,80 +89,107 @@ "json5": "^2.2.1", "semver": "^6.3.0" }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "@babel/generator": { + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { "version": "7.19.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.5.tgz", "integrity": "sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.19.4", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-compilation-targets": { + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { "version": "7.19.3", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", "dev": true, - "requires": { + "dependencies": { "@babel/compat-data": "^7.19.3", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", "semver": "^6.3.0" }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/helper-environment-visitor": { + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helper-module-imports": { + "node_modules/@babel/helper-module-imports": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-module-transforms": { + "node_modules/@babel/helper-module-transforms": { "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.18.6", @@ -133,221 +198,305 @@ "@babel/template": "^7.18.10", "@babel/traverse": "^7.19.0", "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-plugin-utils": { + "node_modules/@babel/helper-plugin-utils": { "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helper-simple-access": { + "node_modules/@babel/helper-simple-access": { "version": "7.19.4", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz", "integrity": "sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.19.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-split-export-declaration": { + "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-string-parser": { + "node_modules/@babel/helper-string-parser": { "version": "7.19.4", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helper-validator-identifier": { + "node_modules/@babel/helper-validator-identifier": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helper-validator-option": { + "node_modules/@babel/helper-validator-option": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helpers": { + "node_modules/@babel/helpers": { "version": "7.19.4", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.4.tgz", "integrity": "sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==", "dev": true, - "requires": { + "dependencies": { "@babel/template": "^7.18.10", "@babel/traverse": "^7.19.4", "@babel/types": "^7.19.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/highlight": { + "node_modules/@babel/highlight": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/parser": { + "node_modules/@babel/parser": { "version": "7.19.4", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.4.tgz", "integrity": "sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==", - "dev": true + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } }, - "@babel/plugin-syntax-async-generators": { + "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-bigint": { + "node_modules/@babel/plugin-syntax-bigint": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-class-properties": { + "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-import-meta": { + "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-json-strings": { + "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-logical-assignment-operators": { + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-nullish-coalescing-operator": { + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-numeric-separator": { + "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-object-rest-spread": { + "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-optional-catch-binding": { + "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-optional-chaining": { + "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-top-level-await": { + "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-typescript": { + "node_modules/@babel/plugin-syntax-typescript": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/runtime": { + "node_modules/@babel/runtime": { "version": "7.19.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.4.tgz", "integrity": "sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==", "dev": true, - "requires": { + "dependencies": { "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/template": { + "node_modules/@babel/template": { "version": "7.18.10", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.18.10", "@babel/types": "^7.18.10" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/traverse": { + "node_modules/@babel/traverse": { "version": "7.23.2", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.22.13", "@babel/generator": "^7.23.0", "@babel/helper-environment-visitor": "^7.22.20", @@ -359,190 +508,243 @@ "debug": "^4.1.0", "globals": "^11.1.0" }, - "dependencies": { - "@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "requires": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - } - }, - "@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "requires": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true - }, - "@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true - }, - "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - } - }, - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } + "engines": { + "node": ">=6.9.0" } }, - "@babel/types": { + "node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { "version": "7.19.4", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.4.tgz", "integrity": "sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@bcoe/v8-coverage": { + "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@cspotcode/source-map-support": { + "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, - "requires": { + "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, - "dependencies": { - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } + "engines": { + "node": ">=12" } }, - "@istanbuljs/load-nyc-config": { + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, - "requires": { + "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "@istanbuljs/schema": { + "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "@jest/console": { + "node_modules/@jest/console": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", "chalk": "^4.0.0", @@ -550,64 +752,86 @@ "jest-util": "^28.1.3", "slash": "^3.0.0" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/core": { + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.3.tgz", "integrity": "sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==", "dev": true, - "requires": { + "dependencies": { "@jest/console": "^28.1.3", "@jest/reporters": "^28.1.3", "@jest/test-result": "^28.1.3", @@ -638,154 +862,207 @@ "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true } } }, - "@jest/environment": { + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/core/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.3.tgz", "integrity": "sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA==", "dev": true, - "requires": { + "dependencies": { "@jest/fake-timers": "^28.1.3", "@jest/types": "^28.1.3", "@types/node": "*", "jest-mock": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/expect": { + "node_modules/@jest/expect": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.3.tgz", "integrity": "sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw==", "dev": true, - "requires": { + "dependencies": { "expect": "^28.1.3", "jest-snapshot": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/expect-utils": { + "node_modules/@jest/expect-utils": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", "dev": true, - "requires": { + "dependencies": { "jest-get-type": "^28.0.2" }, - "dependencies": { - "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", - "dev": true - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/fake-timers": { + "node_modules/@jest/expect-utils/node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/fake-timers": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.3.tgz", "integrity": "sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^28.1.3", "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", "jest-message-util": "^28.1.3", "jest-mock": "^28.1.3", "jest-util": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/globals": { + "node_modules/@jest/globals": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.3.tgz", "integrity": "sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA==", "dev": true, - "requires": { + "dependencies": { "@jest/environment": "^28.1.3", "@jest/expect": "^28.1.3", "@jest/types": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/reporters": { + "node_modules/@jest/reporters": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.3.tgz", "integrity": "sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg==", "dev": true, - "requires": { + "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^28.1.3", "@jest/test-result": "^28.1.3", @@ -812,108 +1089,150 @@ "terminal-link": "^2.0.0", "v8-to-istanbul": "^9.0.1" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true } } }, - "@jest/schemas": { + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", "dev": true, - "requires": { + "dependencies": { "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/source-map": { + "node_modules/@jest/source-map": { "version": "28.1.2", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.1.2.tgz", "integrity": "sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==", "dev": true, - "requires": { + "dependencies": { "@jridgewell/trace-mapping": "^0.3.13", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/test-result": { + "node_modules/@jest/test-result": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", "dev": true, - "requires": { + "dependencies": { "@jest/console": "^28.1.3", "@jest/types": "^28.1.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/test-sequencer": { + "node_modules/@jest/test-sequencer": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.1.3.tgz", "integrity": "sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw==", "dev": true, - "requires": { + "dependencies": { "@jest/test-result": "^28.1.3", "graceful-fs": "^4.2.9", "jest-haste-map": "^28.1.3", "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/transform": { + "node_modules/@jest/transform": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.3.tgz", "integrity": "sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==", "dev": true, - "requires": { + "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^28.1.3", "@jridgewell/trace-mapping": "^0.3.13", @@ -930,64 +1249,86 @@ "slash": "^3.0.0", "write-file-atomic": "^4.0.1" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jest/types": { + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", "dev": true, - "requires": { + "dependencies": { "@jest/schemas": "^28.1.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", @@ -995,150 +1336,181 @@ "@types/yargs": "^17.0.8", "chalk": "^4.0.0" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@jridgewell/gen-mapping": { + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, - "requires": { + "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" } }, - "@jridgewell/resolve-uri": { + "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.0.0" + } }, - "@jridgewell/set-array": { + "node_modules/@jridgewell/set-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.0.0" + } }, - "@jridgewell/sourcemap-codec": { + "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, - "@jridgewell/trace-mapping": { + "node_modules/@jridgewell/trace-mapping": { "version": "0.3.17", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "dev": true, - "requires": { + "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, - "@sinclair/typebox": { + "node_modules/@sinclair/typebox": { "version": "0.24.46", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.46.tgz", "integrity": "sha512-ng4ut1z2MCBhK/NwDVwIQp3pAUOCs/KNaW3cBxdFB2xTDrOuo1xuNmpr/9HHFhxqIvHrs1NTH3KJg6q+JSy1Kw==", "dev": true }, - "@sinonjs/commons": { + "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, - "requires": { + "dependencies": { "type-detect": "4.0.8" } }, - "@sinonjs/fake-timers": { + "node_modules/@sinonjs/fake-timers": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", "dev": true, - "requires": { + "dependencies": { "@sinonjs/commons": "^1.7.0" } }, - "@tsconfig/node10": { + "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", "dev": true }, - "@tsconfig/node12": { + "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "dev": true }, - "@tsconfig/node14": { + "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true }, - "@tsconfig/node16": { + "node_modules/@tsconfig/node16": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "dev": true }, - "@types/babel__core": { + "node_modules/@types/babel__core": { "version": "7.1.19", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", "dev": true, - "requires": { + "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0", "@types/babel__generator": "*", @@ -1146,205 +1518,231 @@ "@types/babel__traverse": "*" } }, - "@types/babel__generator": { + "node_modules/@types/babel__generator": { "version": "7.6.4", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.0.0" } }, - "@types/babel__template": { + "node_modules/@types/babel__template": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", "dev": true, - "requires": { + "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, - "@types/babel__traverse": { + "node_modules/@types/babel__traverse": { "version": "7.18.2", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", "dev": true, - "requires": { + "dependencies": { "@babel/types": "^7.3.0" } }, - "@types/graceful-fs": { + "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", "dev": true, - "requires": { + "dependencies": { "@types/node": "*" } }, - "@types/istanbul-lib-coverage": { + "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", "dev": true }, - "@types/istanbul-lib-report": { + "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, - "requires": { + "dependencies": { "@types/istanbul-lib-coverage": "*" } }, - "@types/istanbul-reports": { + "node_modules/@types/istanbul-reports": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, - "requires": { + "dependencies": { "@types/istanbul-lib-report": "*" } }, - "@types/jest": { + "node_modules/@types/jest": { "version": "27.5.2", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", "dev": true, - "requires": { + "dependencies": { "jest-matcher-utils": "^27.0.0", "pretty-format": "^27.0.0" } }, - "@types/node": { + "node_modules/@types/node": { "version": "17.0.45", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", "dev": true }, - "@types/prettier": { + "node_modules/@types/prettier": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==", "dev": true }, - "@types/sprintf-js": { + "node_modules/@types/sprintf-js": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@types/sprintf-js/-/sprintf-js-1.1.2.tgz", "integrity": "sha512-hkgzYF+qnIl8uTO8rmUSVSfQ8BIfMXC4yJAF4n8BE758YsKBZvFC4NumnAegj7KmylP0liEZNpb9RRGFMbFejA==", "dev": true }, - "@types/stack-utils": { + "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, - "@types/yargs": { + "node_modules/@types/yargs": { "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "dev": true, - "requires": { + "dependencies": { "@types/yargs-parser": "*" } }, - "@types/yargs-parser": { + "node_modules/@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, - "acorn": { + "node_modules/acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } }, - "acorn-walk": { + "node_modules/acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, - "ansi-escapes": { + "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, - "requires": { + "dependencies": { "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "ansi-regex": { + "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "ansi-styles": { + "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "requires": { + "dependencies": { "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "anymatch": { + "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, - "requires": { + "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" } }, - "arg": { + "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "argparse": { + "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - }, "dependencies": { - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - } + "sprintf-js": "~1.0.2" } }, - "array-back": { + "node_modules/argparse/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/array-back": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "async-mutex": { + "node_modules/async-mutex": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz", "integrity": "sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==", - "requires": { + "dependencies": { "tslib": "^2.3.1" } }, - "babel-jest": { + "node_modules/babel-jest": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.3.tgz", "integrity": "sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q==", "dev": true, - "requires": { + "dependencies": { "@jest/transform": "^28.1.3", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", @@ -1353,89 +1751,120 @@ "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "babel-plugin-istanbul": { + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" } }, - "babel-plugin-jest-hoist": { + "node_modules/babel-plugin-jest-hoist": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz", "integrity": "sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q==", "dev": true, - "requires": { + "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", "@types/babel__core": "^7.1.14", "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "babel-preset-current-node-syntax": { + "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, - "requires": { + "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.8.3", @@ -1448,365 +1877,461 @@ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "babel-preset-jest": { + "node_modules/babel-preset-jest": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz", "integrity": "sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A==", "dev": true, - "requires": { + "dependencies": { "babel-plugin-jest-hoist": "^28.1.3", "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "balanced-match": { + "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "bluebird": { + "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, - "brace-expansion": { + "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "requires": { + "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "braces": { + "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, - "requires": { + "dependencies": { "fill-range": "^7.1.1" }, - "dependencies": { - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - } + "engines": { + "node": ">=8" } }, - "browserslist": { + "node_modules/braces/node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", "dev": true, - "requires": { + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { "caniuse-lite": "^1.0.30001400", "electron-to-chromium": "^1.4.251", "node-releases": "^2.0.6", "update-browserslist-db": "^1.0.9" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "bs-logger": { + "node_modules/bs-logger": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, - "requires": { + "dependencies": { "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" } }, - "bser": { + "node_modules/bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, - "requires": { + "dependencies": { "node-int64": "^0.4.0" } }, - "buffer-from": { + "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "call-bind": { + "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, - "requires": { + "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "callsites": { + "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "camelcase": { + "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "caniuse-lite": { + "node_modules/caniuse-lite": { "version": "1.0.30001419", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001419.tgz", "integrity": "sha512-aFO1r+g6R7TW+PNQxKzjITwLOyDhVRLjW0LcwS/HCZGUUKTGNp9+IwLC4xyDSZBygVL/mxaFR3HIV6wEKQuSzw==", - "dev": true + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] }, - "chalk": { + "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "char-regex": { + "node_modules/char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "check-engine": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/check-engine/-/check-engine-1.10.1.tgz", - "integrity": "sha512-KqZ6sV7onqcc81qoK+NsCNjNfik1rRHzmxYJ+tDdCc+6nbpaj0X8SKSzb8lYIcQ+ire5ypMr4YP832/7RH843Q==", "dev": true, - "requires": { - "bluebird": "3.7.2", - "colors": "1.4.0", - "command-line-usage": "6.1.0", - "jsonfile": "6.0.1", - "semver": "7.3.2", - "yargs": "16.1.0" - }, - "dependencies": { - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - }, - "yargs": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz", - "integrity": "sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.2", - "yargs-parser": "^20.2.2" - } - } + "engines": { + "node": ">=10" } }, - "ci-info": { + "node_modules/check-engine": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/check-engine/-/check-engine-1.14.0.tgz", + "integrity": "sha512-CZZ3UmZKMer4O63yNWit5KLm7FoO69shcdPbkP8Dj4N728jqI7d8YyAigOgKnajVBA7TtaL7BuaMRDXcoYJKxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "3.7.2", + "colors": "1.4.0", + "command-line-usage": "6.1.3", + "jsonfile": "6.1.0", + "semver": "7.5.4", + "yargs": "17.7.1" + }, + "bin": { + "check-engine": "bin/check-engine.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/check-engine/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", "dev": true }, - "cjs-module-lexer": { + "node_modules/cjs-module-lexer": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "co": { + "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } }, - "collect-v8-coverage": { + "node_modules/collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", "dev": true }, - "color-convert": { + "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "requires": { + "dependencies": { "color-name": "1.1.3" } }, - "color-name": { + "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "colors": { + "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true - }, - "command-line-usage": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.0.tgz", - "integrity": "sha512-Ew1clU4pkUeo6AFVDFxCbnN7GIZfXl48HIOQeFQnkO3oOqvpI7wdqtLRwv9iOCZ/7A+z4csVZeiDdEcj8g6Wiw==", "dev": true, - "requires": { - "array-back": "^4.0.0", - "chalk": "^2.4.2", - "table-layout": "^1.0.0", - "typical": "^5.2.0" + "engines": { + "node": ">=0.1.90" } }, - "concat-map": { + "node_modules/command-line-usage": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", + "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^4.0.2", + "chalk": "^2.4.2", + "table-layout": "^1.0.2", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "convert-source-map": { + "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, - "create-require": { + "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "cross-spawn": { + "node_modules/cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, - "requires": { + "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" } }, - "debug": { + "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "requires": { + "dependencies": { "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "dedent": { + "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, - "deep-extend": { + "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } }, - "deepmerge": { + "node_modules/deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "define-properties": { + "node_modules/define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", "dev": true, - "requires": { + "dependencies": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "detect-newline": { + "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "diff": { + "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.3.1" + } }, - "diff-sequences": { + "node_modules/diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } }, - "electron-to-chromium": { + "node_modules/electron-to-chromium": { "version": "1.4.282", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.282.tgz", "integrity": "sha512-Dki0WhHNh/br/Xi1vAkueU5mtIc9XLHcMKB6tNfQKk+kPG0TEUjRh5QEMAUbRp30/rYNMFD1zKKvbVzwq/4wmg==", "dev": true }, - "emittery": { + "node_modules/emittery": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", - "dev": true + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } }, - "emoji-regex": { + "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "error-ex": { + "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, - "requires": { + "dependencies": { "is-arrayish": "^0.2.1" } }, - "es-abstract": { + "node_modules/es-abstract": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", @@ -1830,43 +2355,68 @@ "string.prototype.trimend": "^1.0.5", "string.prototype.trimstart": "^1.0.5", "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "es-to-primitive": { + "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, - "requires": { + "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "escalade": { + "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "escape-string-regexp": { + "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "esprima": { + "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } }, - "execa": { + "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, - "requires": { + "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", @@ -1877,756 +2427,964 @@ "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "exit": { + "node_modules/execa/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8.0" + } }, - "expect": { + "node_modules/expect": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", "dev": true, - "requires": { + "dependencies": { "@jest/expect-utils": "^28.1.3", "jest-get-type": "^28.0.2", "jest-matcher-utils": "^28.1.3", "jest-message-util": "^28.1.3", "jest-util": "^28.1.3" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "diff-sequences": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-diff": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", - "dev": true - }, - "jest-matcher-utils": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "fast-json-stable-stringify": { + "node_modules/expect/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/expect/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/expect/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/expect/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/expect/node_modules/diff-sequences": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", + "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/expect/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/expect/node_modules/jest-diff": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", + "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/expect/node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/expect/node_modules/jest-matcher-utils": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", + "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/expect/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/expect/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/expect/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/expect/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "fb-watchman": { + "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, - "requires": { + "dependencies": { "bser": "2.1.1" } }, - "find-up": { + "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "requires": { + "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "fs.realpath": { + "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "fsevents": { + "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "optional": true + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, - "function-bind": { + "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "function.prototype.name": { + "node_modules/function.prototype.name": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", "es-abstract": "^1.19.0", "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "functions-have-names": { + "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "gensync": { + "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "get-caller-file": { + "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } }, - "get-intrinsic": { + "node_modules/get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dev": true, - "requires": { + "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "get-package-type": { + "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=8.0.0" + } }, - "get-stream": { + "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "get-symbol-description": { + "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "glob": { + "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "requires": { + "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "globals": { + "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "graceful-fs": { + "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, - "has": { + "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, - "requires": { + "dependencies": { "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" } }, - "has-bigints": { + "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "has-flag": { + "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "has-property-descriptors": { + "node_modules/has-property-descriptors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", "dev": true, - "requires": { + "dependencies": { "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "has-symbols": { + "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "has-tostringtag": { + "node_modules/has-tostringtag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dev": true, - "requires": { + "dependencies": { "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "hosted-git-info": { + "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, - "html-escaper": { + "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "human-signals": { + "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true + "dev": true, + "engines": { + "node": ">=10.17.0" + } }, - "import-local": { + "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, - "requires": { + "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "imurmurhash": { + "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.19" + } }, - "inflight": { + "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, - "requires": { + "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, - "inherits": { + "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "internal-slot": { + "node_modules/internal-slot": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "dev": true, - "requires": { + "dependencies": { "get-intrinsic": "^1.1.0", "has": "^1.0.3", "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" } }, - "is-arrayish": { + "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, - "is-bigint": { + "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, - "requires": { + "dependencies": { "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-boolean-object": { + "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-callable": { + "node_modules/is-callable": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "is-core-module": { + "node_modules/is-core-module": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, - "requires": { + "dependencies": { "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-date-object": { + "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, - "requires": { + "dependencies": { "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-fullwidth-code-point": { + "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "is-generator-fn": { + "node_modules/is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "is-negative-zero": { + "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "is-number": { + "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.12.0" + } }, - "is-number-object": { + "node_modules/is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, - "requires": { + "dependencies": { "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-regex": { + "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-shared-array-buffer": { + "node_modules/is-shared-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-stream": { + "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "is-string": { + "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, - "requires": { + "dependencies": { "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-symbol": { + "node_modules/is-symbol": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, - "requires": { + "dependencies": { "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-weakref": { + "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "isexe": { + "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "istanbul-lib-coverage": { + "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "istanbul-lib-instrument": { + "node_modules/istanbul-lib-instrument": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, - "requires": { + "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "engines": { + "node": ">=8" } }, - "istanbul-lib-report": { + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, - "requires": { + "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": ">=8" } }, - "istanbul-lib-source-maps": { + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, - "requires": { + "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" } }, - "istanbul-reports": { + "node_modules/istanbul-reports": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, - "requires": { + "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "iter-tools": { + "node_modules/iter-tools": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/iter-tools/-/iter-tools-7.5.0.tgz", "integrity": "sha512-L0p/RG3Hwk1urilryDKqU8pQ1t5AaaMc7CHmiwJD/uh63Lv7VyjNng/esstf+Tct1587IpetpcDFdufz8sG+sQ==", "dev": true, - "requires": { + "dependencies": { "@babel/runtime": "^7.12.1" } }, - "jest": { + "node_modules/jest": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz", "integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==", "dev": true, - "requires": { + "dependencies": { "@jest/core": "^28.1.3", "@jest/types": "^28.1.3", "import-local": "^3.0.2", "jest-cli": "^28.1.3" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-cli": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.3.tgz", - "integrity": "sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==", - "dev": true, - "requires": { - "@jest/core": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true } } }, - "jest-changed-files": { + "node_modules/jest-changed-files": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.1.3.tgz", "integrity": "sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA==", "dev": true, - "requires": { + "dependencies": { "execa": "^5.0.0", "p-limit": "^3.1.0" }, - "dependencies": { - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-circus": { + "node_modules/jest-changed-files/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-circus": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.3.tgz", "integrity": "sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==", "dev": true, - "requires": { + "dependencies": { "@jest/environment": "^28.1.3", "@jest/expect": "^28.1.3", "@jest/test-result": "^28.1.3", @@ -2647,135 +3405,182 @@ "slash": "^3.0.0", "stack-utils": "^2.0.3" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "diff-sequences": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-diff": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", - "dev": true - }, - "jest-matcher-utils": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-config": { + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-circus/node_modules/diff-sequences": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", + "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/jest-diff": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", + "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-matcher-utils": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", + "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-circus/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-circus/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-circus/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.3.tgz", "integrity": "sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==", "dev": true, - "requires": { + "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^28.1.3", "@jest/types": "^28.1.3", @@ -2799,421 +3604,574 @@ "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", - "dev": true - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } + "ts-node": { + "optional": true } } }, - "jest-diff": { + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-config/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-config/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-config/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", "dev": true, - "requires": { + "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^27.5.1", "jest-get-type": "^27.5.1", "pretty-format": "^27.5.1" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-docblock": { + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { "version": "28.1.1", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", "dev": true, - "requires": { + "dependencies": { "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-each": { + "node_modules/jest-each": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.3.tgz", "integrity": "sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^28.1.3", "chalk": "^4.0.0", "jest-get-type": "^28.0.2", "jest-util": "^28.1.3", "pretty-format": "^28.1.3" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-environment-node": { + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-each/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-each/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-node": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.3.tgz", "integrity": "sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==", "dev": true, - "requires": { + "dependencies": { "@jest/environment": "^28.1.3", "@jest/fake-timers": "^28.1.3", "@jest/types": "^28.1.3", "@types/node": "*", "jest-mock": "^28.1.3", "jest-util": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-get-type": { + "node_modules/jest-get-type": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "dev": true + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } }, - "jest-haste-map": { + "node_modules/jest-haste-map": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.3.tgz", "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^28.1.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", "jest-regex-util": "^28.0.2", "jest-util": "^28.1.3", "jest-worker": "^28.1.3", "micromatch": "^4.0.4", "walker": "^1.0.8" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "jest-leak-detector": { + "node_modules/jest-leak-detector": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz", "integrity": "sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==", "dev": true, - "requires": { + "dependencies": { "jest-get-type": "^28.0.2", "pretty-format": "^28.1.3" }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-matcher-utils": { + "node_modules/jest-leak-detector/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-leak-detector/node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/jest-matcher-utils": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", "dev": true, - "requires": { + "dependencies": { "chalk": "^4.0.0", "jest-diff": "^27.5.1", "jest-get-type": "^27.5.1", "pretty-format": "^27.5.1" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "jest-message-util": { + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", "@types/stack-utils": "^2.0.0", @@ -3224,112 +4182,158 @@ "slash": "^3.0.0", "stack-utils": "^2.0.3" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-mock": { + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-message-util/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.3.tgz", "integrity": "sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-pnp-resolver": { + "node_modules/jest-pnp-resolver": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } }, - "jest-regex-util": { + "node_modules/jest-regex-util": { "version": "28.0.2", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", - "dev": true + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } }, - "jest-resolve": { + "node_modules/jest-resolve": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.3.tgz", "integrity": "sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ==", "dev": true, - "requires": { + "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^28.1.3", @@ -3340,74 +4344,99 @@ "resolve.exports": "^1.1.0", "slash": "^3.0.0" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-resolve-dependencies": { + "node_modules/jest-resolve-dependencies": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz", "integrity": "sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA==", "dev": true, - "requires": { + "dependencies": { "jest-regex-util": "^28.0.2", "jest-snapshot": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-runner": { + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.3.tgz", "integrity": "sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==", "dev": true, - "requires": { + "dependencies": { "@jest/console": "^28.1.3", "@jest/environment": "^28.1.3", "@jest/test-result": "^28.1.3", @@ -3430,73 +4459,101 @@ "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-runtime": { + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.3.tgz", "integrity": "sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw==", "dev": true, - "requires": { + "dependencies": { "@jest/environment": "^28.1.3", "@jest/fake-timers": "^28.1.3", "@jest/globals": "^28.1.3", @@ -3520,70 +4577,95 @@ "slash": "^3.0.0", "strip-bom": "^4.0.0" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-snapshot": { + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.3.tgz", "integrity": "sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==", "dev": true, - "requires": { + "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", @@ -3608,135 +4690,180 @@ "pretty-format": "^28.1.3", "semver": "^7.3.5" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "diff-sequences": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-diff": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", - "dev": true - }, - "jest-matcher-utils": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-util": { + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/diff-sequences": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", + "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/jest-diff": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", + "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-matcher-utils": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", + "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", "chalk": "^4.0.0", @@ -3744,64 +4871,86 @@ "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-validate": { + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.3.tgz", "integrity": "sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA==", "dev": true, - "requires": { + "dependencies": { "@jest/types": "^28.1.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", @@ -3809,102 +4958,140 @@ "leven": "^3.1.0", "pretty-format": "^28.1.3" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-watcher": { + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate/node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-validate/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-validate/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", "dev": true, - "requires": { + "dependencies": { "@jest/test-result": "^28.1.3", "@jest/types": "^28.1.3", "@types/node": "*", @@ -3914,331 +5101,530 @@ "jest-util": "^28.1.3", "string-length": "^4.0.1" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "jest-worker": { + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", "dev": true, - "requires": { + "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest/node_modules/jest-cli": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.3.tgz", + "integrity": "sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==", + "dev": true, + "dependencies": { + "@jest/core": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^28.1.3", + "jest-util": "^28.1.3", + "jest-validate": "^28.1.3", + "prompts": "^2.0.1", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true } } }, - "js-tokens": { + "node_modules/jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "js-yaml": { + "node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, - "requires": { + "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "jsesc": { + "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } }, - "json-parse-better-errors": { + "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-parse-even-better-errors": { + "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "json5": { + "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } }, - "jsonc-parser": { + "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true }, - "jsonfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", - "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^1.0.0" + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "kleur": { + "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "leven": { + "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "lines-and-columns": { + "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "load-json-file": { + "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, - "requires": { + "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^4.0.0", "pify": "^3.0.0", "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "locate-path": { + "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "requires": { + "dependencies": { "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "lodash.memoize": { + "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, - "lru-cache": { + "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "requires": { + "dependencies": { "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "lunr": { + "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, - "make-dir": { + "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, - "requires": { + "dependencies": { "semver": "^6.0.0" }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "make-error": { + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "makeerror": { + "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, - "requires": { + "dependencies": { "tmpl": "1.0.5" } }, - "marked": { + "node_modules/marked": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==", - "dev": true + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } }, - "memorystream": { + "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.10.0" + } }, - "merge-stream": { + "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, - "requires": { - "braces": "^3.0.2", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" } }, - "mimic-fn": { + "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "minimatch": { + "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "requires": { + "dependencies": { "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "ms": { + "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "natural-compare": { + "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "nice-try": { + "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "node-int64": { + "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, - "node-releases": { + "node_modules/node-releases": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, - "normalize-package-data": { + "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, - "requires": { + "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, - "normalize-path": { + "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "npm-run-all": { + "node_modules/npm-run-all": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^3.2.1", "chalk": "^2.4.1", "cross-spawn": "^6.0.5", @@ -4248,622 +5634,848 @@ "read-pkg": "^3.0.0", "shell-quote": "^1.6.1", "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" } }, - "npm-run-path": { + "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, - "requires": { + "dependencies": { "path-key": "^3.0.0" }, - "dependencies": { - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - } + "engines": { + "node": ">=8" } }, - "object-inspect": { + "node_modules/npm-run-path/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-inspect": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.1.tgz", "integrity": "sha512-Y/jF6vnvEtOPGiKD1+q+X0CiUYRQtEHp89MLLUJ7TUivtH8Ugn2+3A7Rynqk7BRsAoqeOQWnFnjpDrKSxDgIGA==", - "dev": true + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "object-keys": { + "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + } }, - "object.assign": { + "node_modules/object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", "has-symbols": "^1.0.1", "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "once": { + "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "requires": { + "dependencies": { "wrappy": "1" } }, - "onetime": { + "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, - "requires": { + "dependencies": { "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-limit": { + "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "requires": { + "dependencies": { "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-locate": { + "node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "requires": { + "dependencies": { "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" } }, - "p-try": { + "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "parse-json": { + "node_modules/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, - "requires": { + "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" } }, - "path-exists": { + "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "path-is-absolute": { + "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "path-key": { + "node_modules/path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "path-parse": { + "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "path-type": { + "node_modules/path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, - "requires": { + "dependencies": { "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "picocolors": { + "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, - "picomatch": { + "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } }, - "pidtree": { + "node_modules/pidtree": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", - "dev": true + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } }, - "pify": { + "node_modules/pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "pirates": { + "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true + "dev": true, + "engines": { + "node": ">= 6" + } }, - "pkg-dir": { + "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, - "requires": { + "dependencies": { "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "prettier": { + "node_modules/prettier": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } }, - "pretty-format": { + "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "prompts": { + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, - "requires": { + "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" } }, - "react-is": { + "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, - "read-pkg": { + "node_modules/read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, - "requires": { + "dependencies": { "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "reduce-flatten": { + "node_modules/reduce-flatten": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "regenerator-runtime": { + "node_modules/regenerator-runtime": { "version": "0.13.10", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz", "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==", "dev": true }, - "regexp.prototype.flags": { + "node_modules/regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "require-directory": { + "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "resolve": { + "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, - "requires": { + "dependencies": { "is-core-module": "^2.8.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "resolve-cwd": { + "node_modules/resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, - "requires": { + "dependencies": { "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "resolve-from": { + "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "resolve.exports": { + "node_modules/resolve.exports": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + } }, - "rimraf": { + "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, - "requires": { + "dependencies": { "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } }, - "shebang-command": { + "node_modules/shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, - "requires": { + "dependencies": { "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "shebang-regex": { + "node_modules/shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "shell-quote": { + "node_modules/shell-quote": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", "dev": true }, - "shiki": { + "node_modules/shiki": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==", "dev": true, - "requires": { + "dependencies": { "jsonc-parser": "^3.0.0", "vscode-oniguruma": "^1.6.1", "vscode-textmate": "^6.0.0" } }, - "side-channel": { + "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "signal-exit": { + "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, - "sisteransi": { + "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, - "slash": { + "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "source-map": { + "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "source-map-support": { + "node_modules/source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, - "requires": { + "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, - "spdx-correct": { + "node_modules/spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, - "requires": { + "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, - "spdx-exceptions": { + "node_modules/spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, - "spdx-expression-parse": { + "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, - "requires": { + "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, - "spdx-license-ids": { + "node_modules/spdx-license-ids": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", "dev": true }, - "sprintf-js": { + "node_modules/sprintf-js": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", "dev": true }, - "stack-utils": { + "node_modules/stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", "dev": true, - "requires": { + "dependencies": { "escape-string-regexp": "^2.0.0" }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } + "engines": { + "node": ">=10" } }, - "string-length": { + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, - "requires": { + "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" } }, - "string-width": { + "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "requires": { + "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "string.prototype.padend": { + "node_modules/string.prototype.padend": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "string.prototype.trimend": { + "node_modules/string.prototype.trimend": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "string.prototype.trimstart": { + "node_modules/string.prototype.trimstart": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "strip-ansi": { + "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "strip-bom": { + "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "strip-final-newline": { + "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "strip-json-comments": { + "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "supports-color": { + "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "requires": { + "dependencies": { "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "supports-hyperlinks": { + "node_modules/supports-hyperlinks": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, - "requires": { + "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "engines": { + "node": ">=8" } }, - "supports-preserve-symlinks-flag": { + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "table-layout": { + "node_modules/table-layout": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "array-back": "^4.0.1", "deep-extend": "~0.6.0", "typical": "^5.2.0", "wordwrapjs": "^4.0.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "terminal-link": { + "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", "dev": true, - "requires": { + "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "test-exclude": { + "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, - "requires": { + "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" } }, - "tmpl": { + "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "to-fast-properties": { + "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "to-regex-range": { + "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "requires": { + "dependencies": { "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "ts-expect": { + "node_modules/ts-expect": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-expect/-/ts-expect-1.3.0.tgz", "integrity": "sha512-e4g0EJtAjk64xgnFPD6kTBUtpnMVzDrMb12N1YZV0VvSlhnVT3SGxiYTLdGy8Q5cYHOIC/FAHmZ10eGrAguicQ==", "dev": true }, - "ts-jest": { + "node_modules/ts-jest": { "version": "28.0.8", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-28.0.8.tgz", "integrity": "sha512-5FaG0lXmRPzApix8oFG8RKjAz4ehtm8yMKOTy5HX3fY6W8kmvOrmcY0hKDElW52FJov+clhUbrKAqofnj4mXTg==", "dev": true, - "requires": { + "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", "jest-util": "^28.0.0", @@ -4873,30 +6485,62 @@ "semver": "7.x", "yargs-parser": "^21.0.1" }, - "dependencies": { - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^28.0.0", + "babel-jest": "^28.0.0", + "jest": "^28.0.0", + "typescript": ">=4.3" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true } } }, - "ts-node": { + "node_modules/ts-jest/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, - "requires": { + "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", @@ -4910,293 +6554,411 @@ "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "tslib": { + "node_modules/tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, - "type-detect": { + "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "type-fest": { + "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "typedoc": { + "node_modules/typedoc": { "version": "0.23.16", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.16.tgz", "integrity": "sha512-rumYsCeNRXlyuZVzefD7050n7ptL2uudsCJg50dY0v/stKniqIlRpvx/F/6expC0/Q6Dbab+g/JpZuB7Sw90FA==", "dev": true, - "requires": { + "dependencies": { "lunr": "^2.3.9", "marked": "^4.0.19", "minimatch": "^5.1.0", "shiki": "^0.11.1" }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x" } }, - "typescript": { + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typescript": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } }, - "typical": { + "node_modules/typical": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "unbox-primitive": { + "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, - "requires": { + "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "dev": true + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } }, - "update-browserslist-db": { + "node_modules/update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", "dev": true, - "requires": { + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "v8-compile-cache-lib": { + "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, - "v8-to-istanbul": { + "node_modules/v8-to-istanbul": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", "dev": true, - "requires": { + "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" } }, - "validate-npm-package-license": { + "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "requires": { + "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "vscode-oniguruma": { + "node_modules/vscode-oniguruma": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", "dev": true }, - "vscode-textmate": { + "node_modules/vscode-textmate": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz", "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==", "dev": true }, - "walker": { + "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, - "requires": { + "dependencies": { "makeerror": "1.0.12" } }, - "which": { + "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "requires": { + "dependencies": { "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "which-boxed-primitive": { + "node_modules/which-boxed-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, - "requires": { + "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", "is-number-object": "^1.0.4", "is-string": "^1.0.5", "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "wordwrapjs": { + "node_modules/wordwrapjs": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "reduce-flatten": "^2.0.0", "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "wrap-ansi": { + "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "wrappy": { + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "write-file-atomic": { + "node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, - "requires": { + "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "y18n": { + "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + } }, - "yallist": { + "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "yargs": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", - "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", + "node_modules/yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, - "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } + "engines": { + "node": ">=12" } }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true + "node_modules/yargs/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } }, - "yn": { + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "yocto-queue": { + "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } From 994056f347a637bfe90b224d4ffdeb2fde43b469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1ll=20Haraldsson?= Date: Tue, 24 Sep 2024 14:17:00 +0000 Subject: [PATCH 133/187] C API now used by Julia. (#7387) See: https://github.com/ahumenberger/Z3.jl/releases/tag/v1.0.0 --- src/api/julia/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/api/julia/README.md b/src/api/julia/README.md index 12e846191..f64b0c4ab 100644 --- a/src/api/julia/README.md +++ b/src/api/julia/README.md @@ -1,6 +1,8 @@ # Julia bindings -The Julia package [Z3.jl](https://github.com/ahumenberger/Z3.jl) provides and interface to Z3 by exposing its C++ API via [CxxWrap.jl](https://github.com/JuliaInterop/CxxWrap.jl). The bindings therefore consist of a [C++ part](z3jl.cpp) and a [Julia part](https://github.com/ahumenberger/Z3.jl). The C++ part defines the Z3 types/methods which are exposed. The resulting library is loaded in the Julia part via CxxWrap.jl which creates the corresponding Julia types/methods. +The Julia package [Z3.jl](https://github.com/ahumenberger/Z3.jl) provides and interface to Z3 by exposing its C API. + +A previous version exposed the C++ API via [CxxWrap.jl](https://github.com/JuliaInterop/CxxWrap.jl). The bindings therefore consisted of a [C++ part](z3jl.cpp) and a [Julia part](https://github.com/ahumenberger/Z3.jl). The C++ part defines the Z3 types/methods which are exposed. The resulting library is loaded in the Julia part via CxxWrap.jl which creates the corresponding Julia types/methods. ## Building the C++ part From 8b81bda46959e82c7e333f5838f4a424f4289f92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1ll=20Haraldsson?= Date: Tue, 24 Sep 2024 14:17:11 +0000 Subject: [PATCH 134/187] Julia now used the C API. (#7388) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0254160c7..5350bc38b 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,7 @@ See [``examples/ml``](examples/ml) for examples. ### ``Python`` -You can install the Python wrapper for Z3 for the latest release from pypi using the command +You can install the Python wrapper for Z3 for the latest release from pypi using the command: ```bash pip install z3-solver @@ -206,7 +206,7 @@ See [``examples/python``](examples/python) for examples. ### ``Julia`` -The Julia package [Z3.jl](https://github.com/ahumenberger/Z3.jl) wraps the C++ API of Z3. Information about updating and building the Julia bindings can be found in [src/api/julia](src/api/julia). +The Julia package [Z3.jl](https://github.com/ahumenberger/Z3.jl) wraps the C API of Z3. A previous version of it wrapped the C++ API: Information about updating and building the Julia bindings can be found in [src/api/julia](src/api/julia). ### ``Web Assembly`` / ``TypeScript`` / ``JavaScript`` From 2655301afcdab4d98f2844f0a69d8ca2ff7aba38 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 24 Sep 2024 23:01:00 +0100 Subject: [PATCH 135/187] comment out simple proofs unit test Signed-off-by: Nikolaj Bjorner --- src/api/js/src/high-level/high-level.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/api/js/src/high-level/high-level.test.ts b/src/api/js/src/high-level/high-level.test.ts index 99f95e5b4..a54f167c2 100644 --- a/src/api/js/src/high-level/high-level.test.ts +++ b/src/api/js/src/high-level/high-level.test.ts @@ -355,7 +355,9 @@ describe('high-level', () => { }); }); - describe('bitvectors', () => { + + describe('bitvectors', () => { + /** it('can do simple proofs', async () => { const { BitVec, Concat, Implies, isBitVecVal } = api.Context('main'); @@ -374,6 +376,7 @@ describe('high-level', () => { await prove(Implies(Concat(x, y).eq(Concat(y, x)), x.eq(y))); }); + **/ it('finds x and y such that: x ^ y - 103 == x * y', async () => { const { BitVec, isBitVecVal } = api.Context('main'); @@ -393,6 +396,7 @@ describe('high-level', () => { }); }); + describe('arrays', () => { it('Example 1', async () => { const Z3 = api.Context('main'); From eb5d036786d1c1571067f656ef9c42afa4a828b7 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 25 Sep 2024 10:21:54 +0100 Subject: [PATCH 136/187] fix #7392 Signed-off-by: Nikolaj Bjorner --- src/smt/params/smt_params.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp index 02919b287..71587b5cc 100644 --- a/src/smt/params/smt_params.cpp +++ b/src/smt/params/smt_params.cpp @@ -331,7 +331,7 @@ void smt_params::setup_QF_BV() { } void smt_params::setup_QF_AUFBV() { - m_array_mode = AR_SIMPLE; + m_array_mode = AR_FULL; m_relevancy_lvl = 0; m_bv_cc = false; m_bb_ext_gates = true; From 82eb18674b446f3a90992fc57cbb690ccd4cfa08 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 25 Sep 2024 10:40:03 +0100 Subject: [PATCH 137/187] remove ubuntu build 20 from nightly Signed-off-by: Nikolaj Bjorner --- scripts/nightly.yaml | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index ccbed95f8..33026b0df 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -80,35 +80,6 @@ stages: artifactName: 'UbuntuBuild' targetPath: $(Build.ArtifactStagingDirectory) - - job: UbuntuBuild20 - displayName: "Ubuntu build 20" - pool: - vmImage: "ubuntu-20.04" - steps: - - task: PythonScript@0 - displayName: Build - inputs: - scriptSource: 'filepath' - scriptPath: scripts/mk_unix_dist.py - arguments: --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk - - script: git clone https://github.com/z3prover/z3test z3test - displayName: 'Clone z3test' - - task: PythonScript@0 - displayName: Test - inputs: - scriptSource: 'filepath' - scriptPath: z3test/scripts/test_benchmarks.py - arguments: build-dist/z3 z3test/regressions/smt2 - - task: CopyFiles@2 - inputs: - sourceFolder: dist - contents: '*.zip' - targetFolder: $(Build.ArtifactStagingDirectory) - - task: PublishPipelineArtifact@0 - inputs: - artifactName: 'UbuntuBuild20' - targetPath: $(Build.ArtifactStagingDirectory) - - job: UbuntuArm64 displayName: "Ubuntu ARM64 build" pool: @@ -258,7 +229,7 @@ stages: - task: DownloadPipelineArtifact@2 displayName: 'Download Ubuntu 20.04 Build' inputs: - artifact: 'UbuntuBuild20' + artifact: 'UbuntuBuild' path: $(Agent.TempDirectory)\package - task: DownloadPipelineArtifact@2 displayName: 'Download Ubuntu ARM64 Build' @@ -561,9 +532,9 @@ stages: artifactName: 'UbuntuArm64' targetPath: tmp - task: DownloadPipelineArtifact@2 - displayName: "Download Ubuntu-20.04" + displayName: "Download Ubuntu" inputs: - artifactName: 'UbuntuBuild20' + artifactName: 'UbuntuBuild' targetPath: tmp - task: DownloadPipelineArtifact@2 displayName: "Download Doc" From 103c5ad71c4526bfc0b7580bce3383940f953c8f Mon Sep 17 00:00:00 2001 From: Kevin Gibbons Date: Wed, 25 Sep 2024 07:53:36 -0700 Subject: [PATCH 138/187] wasm: attempt to GC in tests (#7400) --- .github/workflows/wasm.yml | 2 +- src/api/js/package.json | 2 +- src/api/js/scripts/build-wasm.ts | 2 +- src/api/js/src/high-level/high-level.test.ts | 10 +++++++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index f0b8bd91b..8e157f5a4 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -48,7 +48,7 @@ jobs: source $(dirname $(which emsdk))/emsdk_env.sh which node which clang++ - npm run build:wasm -- -sINITIAL_MEMORY=128MB -sALLOW_MEMORY_GROWTH + npm run build:wasm - name: Test run: npm test diff --git a/src/api/js/package.json b/src/api/js/package.json index 3e79ba8f4..bc6e006d4 100644 --- a/src/api/js/package.json +++ b/src/api/js/package.json @@ -29,7 +29,7 @@ "clean": "rimraf build 'src/**/*.__GENERATED__.*'", "lint": "prettier -c '{./,src/,scripts/,examples/}**/*.{js,ts}'", "format": "prettier --write '{./,src/,scripts/}**/*.{js,ts}'", - "test": "jest", + "test": "node --expose-gc ./node_modules/.bin/jest", "docs": "typedoc", "check-engine": "check-engine" }, diff --git a/src/api/js/scripts/build-wasm.ts b/src/api/js/scripts/build-wasm.ts index 5bdbdea3b..497b67c10 100644 --- a/src/api/js/scripts/build-wasm.ts +++ b/src/api/js/scripts/build-wasm.ts @@ -69,7 +69,7 @@ const fns = JSON.stringify(exportedFuncs()); const methods = '["ccall","FS","allocate","UTF8ToString","intArrayFromString","ALLOC_NORMAL"]'; const libz3a = path.normalize('../../../build/libz3.a'); spawnSync( - `emcc build/async-fns.cc ${libz3a} --std=c++20 --pre-js src/low-level/async-wrapper.js -g2 -pthread -fexceptions -s WASM_BIGINT -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=0 -s PTHREAD_POOL_SIZE_STRICT=0 -s MODULARIZE=1 -s 'EXPORT_NAME="initZ3"' -s EXPORTED_RUNTIME_METHODS=${methods} -s EXPORTED_FUNCTIONS=${fns} -s DISABLE_EXCEPTION_CATCHING=0 -s SAFE_HEAP=0 -s DEMANGLE_SUPPORT=1 -s TOTAL_MEMORY=1GB -s TOTAL_STACK=20MB -I z3/src/api/ -o build/z3-built.js`, + `emcc build/async-fns.cc ${libz3a} --std=c++20 --pre-js src/low-level/async-wrapper.js -g2 -pthread -fexceptions -s WASM_BIGINT -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=0 -s PTHREAD_POOL_SIZE_STRICT=0 -s MODULARIZE=1 -s 'EXPORT_NAME="initZ3"' -s EXPORTED_RUNTIME_METHODS=${methods} -s EXPORTED_FUNCTIONS=${fns} -s DISABLE_EXCEPTION_CATCHING=0 -s SAFE_HEAP=0 -s DEMANGLE_SUPPORT=1 -s TOTAL_MEMORY=2GB -s TOTAL_STACK=20MB -I z3/src/api/ -o build/z3-built.js`, ); fs.rmSync(ccWrapperPath); diff --git a/src/api/js/src/high-level/high-level.test.ts b/src/api/js/src/high-level/high-level.test.ts index a54f167c2..53a0e724b 100644 --- a/src/api/js/src/high-level/high-level.test.ts +++ b/src/api/js/src/high-level/high-level.test.ts @@ -4,6 +4,12 @@ import { init, killThreads } from '../jest'; import { Arith, Bool, Model, Quantifier, Z3AssertionError, Z3HighLevel, AstVector } from './types'; import { expectType } from 'ts-expect'; +// this should not be necessary but there may be a Jest bug +// https://github.com/jestjs/jest/issues/7874 +afterEach(() => { + global.gc && global.gc(); +}); + /** * Generate all possible solutions from given assumptions. * @@ -356,8 +362,7 @@ describe('high-level', () => { }); - describe('bitvectors', () => { - /** + describe('bitvectors', () => { it('can do simple proofs', async () => { const { BitVec, Concat, Implies, isBitVecVal } = api.Context('main'); @@ -376,7 +381,6 @@ describe('high-level', () => { await prove(Implies(Concat(x, y).eq(Concat(y, x)), x.eq(y))); }); - **/ it('finds x and y such that: x ^ y - 103 == x * y', async () => { const { BitVec, isBitVecVal } = api.Context('main'); From 77aa5280dfd4960f615e98b669ff411c774598c5 Mon Sep 17 00:00:00 2001 From: Kevin Gibbons Date: Wed, 25 Sep 2024 10:33:14 -0700 Subject: [PATCH 139/187] wasm: increase timeout in tests (#7401) --- src/api/js/src/high-level/high-level.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/js/src/high-level/high-level.test.ts b/src/api/js/src/high-level/high-level.test.ts index 53a0e724b..f36291764 100644 --- a/src/api/js/src/high-level/high-level.test.ts +++ b/src/api/js/src/high-level/high-level.test.ts @@ -380,7 +380,7 @@ describe('high-level', () => { const y = BitVec.const('y', 32); await prove(Implies(Concat(x, y).eq(Concat(y, x)), x.eq(y))); - }); + }, 10_000 /* timeout ms */); it('finds x and y such that: x ^ y - 103 == x * y', async () => { const { BitVec, isBitVecVal } = api.Context('main'); @@ -455,7 +455,7 @@ describe('high-level', () => { await prove(Eq(arr2.select(0), FIVE_VAL)); await prove(Not(Eq(arr2.select(0), BitVec.val(6, 256)))); await prove(Eq(arr2.store(idx, val).select(idx), constArr.store(idx, val).select(idx))); - }); + }, 10_000 /* timeout ms */); it('Finds arrays that differ but that sum to the same', async () => { const Z3 = api.Context('main'); From c690279912111e4386545c5cfb72ff7d1dfbdaab Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 26 Sep 2024 10:03:02 +0100 Subject: [PATCH 140/187] skip pypi publish during dry run Signed-off-by: Nikolaj Bjorner --- scripts/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/release.yml b/scripts/release.yml index 3125595d7..f67bd2ac2 100644 --- a/scripts/release.yml +++ b/scripts/release.yml @@ -643,7 +643,7 @@ stages: # Enable on release: - job: PyPIPublish - condition: eq(1,1) + condition: eq(1,0) displayName: "Publish to PyPI" pool: vmImage: "ubuntu-latest" From ebdb0374ec972b7f0dd78d0f71793d36f64854ec Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 26 Sep 2024 11:01:59 +0100 Subject: [PATCH 141/187] fix indent Signed-off-by: Nikolaj Bjorner --- scripts/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/release.yml b/scripts/release.yml index f67bd2ac2..4691aeb7b 100644 --- a/scripts/release.yml +++ b/scripts/release.yml @@ -119,7 +119,7 @@ stages: pool: vmImage: "ubuntu-latest" steps: - - script: curl -L -o /tmp/arm-toolchain.tar.xz 'https://developer.arm.com/-/media/Files/downloads/gnu/11.2-2022.02/binrel/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu.tar.xz?rev=33c6e30e5ac64e6dba8f0431f2c35f1b&hash=9918A05BF47621B632C7A5C8D2BB438FB80A4480' + - script: curl -L -o /tmp/arm-toolchain.tar.xz 'https://developer.arm.com/-/media/Files/downloads/gnu/11.2-2022.02/binrel/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu.tar.xz?rev=33c6e30e5ac64e6dba8f0431f2c35f1b&hash=9918A05BF47621B632C7A5C8D2BB438FB80A4480' - script: mkdir -p /tmp/arm-toolchain/ - script: tar xf /tmp/arm-toolchain.tar.xz -C /tmp/arm-toolchain/ --strip-components=1 - script: echo '##vso[task.prependpath]/tmp/arm-toolchain/bin' From b39bcd6a423f278a40ec139fbbf9ad4b0ce679db Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 26 Sep 2024 11:20:54 +0100 Subject: [PATCH 142/187] remove ubuntu20 Signed-off-by: Nikolaj Bjorner --- scripts/release.yml | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/scripts/release.yml b/scripts/release.yml index 4691aeb7b..e487eb76b 100644 --- a/scripts/release.yml +++ b/scripts/release.yml @@ -85,34 +85,6 @@ stages: artifactName: 'UbuntuBuild' targetPath: $(Build.ArtifactStagingDirectory) - - job: UbuntuBuild20 - displayName: "Ubuntu build 20" - pool: - vmImage: "ubuntu-20.04" - steps: - - task: PythonScript@0 - displayName: Build - inputs: - scriptSource: 'filepath' - scriptPath: scripts/mk_unix_dist.py - arguments: --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk - - script: git clone https://github.com/z3prover/z3test z3test - displayName: 'Clone z3test' - - task: PythonScript@0 - displayName: Test - inputs: - scriptSource: 'filepath' - scriptPath: z3test/scripts/test_benchmarks.py - arguments: build-dist/z3 z3test/regressions/smt2 - - task: CopyFiles@2 - inputs: - sourceFolder: dist - contents: '*.zip' - targetFolder: $(Build.ArtifactStagingDirectory) - - task: PublishPipelineArtifact@0 - inputs: - artifactName: 'UbuntuBuild20' - targetPath: $(Build.ArtifactStagingDirectory) - job: UbuntuArm64 displayName: "Ubuntu ARM64 build" @@ -283,11 +255,6 @@ stages: inputs: artifact: 'UbuntuBuild' path: $(Agent.TempDirectory)\package - - task: DownloadPipelineArtifact@2 - displayName: 'Download Ubuntu20 Build' - inputs: - artifact: 'UbuntuBuild20' - path: $(Agent.TempDirectory)\package - task: DownloadPipelineArtifact@2 displayName: 'Download Ubuntu ARM64 Build' inputs: @@ -545,11 +512,6 @@ stages: pool: vmImage: "windows-latest" steps: - - task: DownloadPipelineArtifact@2 - displayName: 'Download Ubuntu Build' - inputs: - artifact: 'UbuntuBuild20' - path: $(Agent.TempDirectory) - task: DownloadPipelineArtifact@2 displayName: 'Download Ubuntu Build' inputs: From 8d831a1adf4f6a38cf51c18541084932df5a2427 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 26 Sep 2024 11:22:18 +0100 Subject: [PATCH 143/187] set to macos latest Signed-off-by: Nikolaj Bjorner --- scripts/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/release.yml b/scripts/release.yml index e487eb76b..a5f356690 100644 --- a/scripts/release.yml +++ b/scripts/release.yml @@ -17,7 +17,7 @@ stages: - job: MacBuild displayName: "macOS Build" pool: - vmImage: "macOS-11" + vmImage: "macOS-latest" steps: - task: PythonScript@0 displayName: Build @@ -46,7 +46,7 @@ stages: - job: MacBuildArm64 displayName: "macOS ARM64 Build" pool: - vmImage: "macOS-11" + vmImage: "macOS-latest" steps: - script: python scripts/mk_unix_dist.py --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk --arch=arm64 --os=osx-11.0 - script: git clone https://github.com/z3prover/z3test z3test From 649c36aa03c41eb40f0300bf5c49c77d99aa04e8 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 26 Sep 2024 13:59:17 +0100 Subject: [PATCH 144/187] align nightly and release yamls Signed-off-by: Nikolaj Bjorner --- scripts/nightly.yaml | 46 +++++++++------- scripts/release.yml | 127 +++++++++++++++++++++---------------------- 2 files changed, 88 insertions(+), 85 deletions(-) diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index 33026b0df..d1c565883 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -10,7 +10,7 @@ stages: - stage: Build jobs: - job: MacBuild - displayName: "macOS Build" + displayName: "Mac Build" pool: vmImage: "macOS-latest" steps: @@ -35,7 +35,7 @@ stages: targetFolder: $(Build.ArtifactStagingDirectory) - task: PublishPipelineArtifact@0 inputs: - artifactName: 'macOSBuild' + artifactName: 'macOsBuild' targetPath: $(Build.ArtifactStagingDirectory) - job: MacBuildArm64 @@ -227,7 +227,7 @@ stages: artifact: 'WindowsBuild-x64' path: $(Agent.TempDirectory)\package - task: DownloadPipelineArtifact@2 - displayName: 'Download Ubuntu 20.04 Build' + displayName: 'Download Ubuntu Build' inputs: artifact: 'UbuntuBuild' path: $(Agent.TempDirectory)\package @@ -449,30 +449,36 @@ stages: pool: vmImage: "ubuntu-latest" steps: - - task: DownloadPipelineArtifact@2 - inputs: - artifactName: 'WindowsBuild-x86' - targetPath: $(Agent.TempDirectory) - - task: DownloadPipelineArtifact@2 - inputs: - artifactName: 'WindowsBuild-x64' - targetPath: $(Agent.TempDirectory) - - task: DownloadPipelineArtifact@2 - inputs: - artifactName: 'ManyLinuxPythonBuildAMD64' - targetPath: $(Agent.TempDirectory) - - task: DownloadPipelineArtifact@2 - inputs: - artifactName: 'ManyLinuxPythonBuildArm64' - targetPath: $(Agent.TempDirectory) - - task: DownloadPipelineArtifact@2 + - task: DownloadPipelineArtifact@2 + displayName: 'Download macOS Build' inputs: artifactName: 'macOsBuild' targetPath: $(Agent.TempDirectory) - task: DownloadPipelineArtifact@2 + displayName: 'Download macOS Arm64 Build' inputs: artifactName: 'MacArm64' targetPath: $(Agent.TempDirectory) + - task: DownloadPipelineArtifact@2 + displayName: 'Download Win64 Build' + inputs: + artifactName: 'WindowsBuild-x64' + targetPath: $(Agent.TempDirectory) + - task: DownloadPipelineArtifact@2 + displayName: 'Download Win32 Build' + inputs: + artifactName: 'WindowsBuild-x86' + targetPath: $(Agent.TempDirectory) + - task: DownloadPipelineArtifact@2 + displayName: 'Download ManyLinux Build' + inputs: + artifactName: 'ManyLinuxPythonBuildAMD64' + targetPath: $(Agent.TempDirectory) + - task: DownloadPipelineArtifact@2 + displayName: 'Download ManyLinux Arm64 Build' + inputs: + artifactName: 'ManyLinuxPythonBuildArm64' + targetPath: $(Agent.TempDirectory) - script: cd $(Agent.TempDirectory); mkdir osx-x64-bin; cd osx-x64-bin; unzip ../*x64-osx*.zip - script: cd $(Agent.TempDirectory); mkdir osx-arm64-bin; cd osx-arm64-bin; unzip ../*arm64-osx*.zip # - script: cd $(Agent.TempDirectory); mkdir musl-bin; cd musl-bin; unzip ../*-linux.zip diff --git a/scripts/release.yml b/scripts/release.yml index a5f356690..50ac4e31d 100644 --- a/scripts/release.yml +++ b/scripts/release.yml @@ -15,7 +15,7 @@ stages: jobs: - job: MacBuild - displayName: "macOS Build" + displayName: "Mac Build" pool: vmImage: "macOS-latest" steps: @@ -40,11 +40,11 @@ stages: targetFolder: $(Build.ArtifactStagingDirectory) - task: PublishPipelineArtifact@0 inputs: - artifactName: 'macOSBuild' + artifactName: 'macOsBuild' targetPath: $(Build.ArtifactStagingDirectory) - job: MacBuildArm64 - displayName: "macOS ARM64 Build" + displayName: "Mac ARM64 Build" pool: vmImage: "macOS-latest" steps: @@ -145,43 +145,29 @@ stages: artifactName: 'UbuntuDoc' targetPath: $(Build.ArtifactStagingDirectory) - - job: LinuxBuilds - displayName: "ManyLinux build" - variables: - name: ManyLinux - python: "/opt/python/cp37-cp37m/bin/python" + - job: "ManylinuxPythonBuildAmd64" + displayName: "Python bindings (manylinux Centos AMD64) build" pool: vmImage: "ubuntu-latest" container: "quay.io/pypa/manylinux2014_x86_64:latest" steps: - - task: PythonScript@0 - displayName: Build - inputs: - scriptSource: 'filepath' - scriptPath: scripts/mk_unix_dist.py - arguments: --nodotnet --nojava - pythonInterpreter: $(python) - - script: git clone https://github.com/z3prover/z3test z3test - displayName: 'Clone z3test' - - task: PythonScript@0 - displayName: Test - inputs: - scriptSource: 'filepath' - scriptPath: z3test/scripts/test_benchmarks.py - arguments: build-dist/z3 z3test/regressions/smt2 - pythonInterpreter: $(python) + - script: "/opt/python/cp38-cp38/bin/python -m venv $PWD/env" + - script: 'echo "##vso[task.prependpath]$PWD/env/bin"' + - script: "pip install build git+https://github.com/rhelmot/auditwheel" # @TODO remove when patches make it upstream + - script: "cd src/api/python && python -m build && AUDITWHEEL_PLAT= auditwheel repair --best-plat dist/*.whl && cd ../../.." + - script: "pip install ./src/api/python/wheelhouse/*.whl && python - Date: Thu, 26 Sep 2024 14:47:51 +0100 Subject: [PATCH 145/187] update signature of operator== Signed-off-by: Nikolaj Bjorner --- src/muz/rel/dl_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/muz/rel/dl_base.h b/src/muz/rel/dl_base.h index d1d946d10..d6394ddb1 100644 --- a/src/muz/rel/dl_base.h +++ b/src/muz/rel/dl_base.h @@ -93,7 +93,7 @@ namespace datalog { */ class signature_base : public signature_base_base { public: - bool operator==(const signature & o) const { + bool operator==(const signature_base & o) const { unsigned n=signature_base_base::size(); if (n!=o.size()) { return false; From f4452a0348f31b0d10b987e856a7b195fe7f1aed Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 26 Sep 2024 21:34:55 +0100 Subject: [PATCH 146/187] pypi publish Signed-off-by: Nikolaj Bjorner --- scripts/release.yml | 2 +- src/ast/ast.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/release.yml b/scripts/release.yml index 50ac4e31d..349c8d6ce 100644 --- a/scripts/release.yml +++ b/scripts/release.yml @@ -602,7 +602,7 @@ stages: # Enable on release: - job: PyPIPublish - condition: eq(1,0) + condition: eq(1,1) displayName: "Publish to PyPI" pool: vmImage: "ubuntu-latest" diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 5194154f0..426a933ad 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -58,7 +58,7 @@ parameter::parameter(parameter const& other) : m_val(other.m_val) { } void parameter::init_eh(ast_manager & m) { - if (is_ast()) { + if (is_ast()) { x m.inc_ref(get_ast()); } } From d047b86439ec209446d211f0f6b251ebfba070d8 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 26 Sep 2024 21:35:28 +0100 Subject: [PATCH 147/187] pypi publish Signed-off-by: Nikolaj Bjorner --- src/ast/ast.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 426a933ad..2d6f6f9b2 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -58,7 +58,7 @@ parameter::parameter(parameter const& other) : m_val(other.m_val) { } void parameter::init_eh(ast_manager & m) { - if (is_ast()) { x + if (is_ast()) { m.inc_ref(get_ast()); } } From 01cf0427b4f788e854005f15fcbe3db6f6a6155b Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 27 Sep 2024 11:36:10 +0100 Subject: [PATCH 148/187] fix #7404, relates to #7400. --- src/tactic/core/simplify_tactic.cpp | 4 ++++ src/tactic/core/simplify_tactic.h | 1 + src/tactic/smtlogics/qfnra_tactic.cpp | 19 ++++++++++++------- src/tactic/tactic.cpp | 26 ++++++++++++++++++++++++++ src/tactic/tactic.h | 1 + src/tactic/tactical.cpp | 14 +++++++++++--- 6 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/tactic/core/simplify_tactic.cpp b/src/tactic/core/simplify_tactic.cpp index f05b4c4fc..ee5cd0f73 100644 --- a/src/tactic/core/simplify_tactic.cpp +++ b/src/tactic/core/simplify_tactic.cpp @@ -98,6 +98,7 @@ void simplify_tactic::operator()(goal_ref const & in, (*m_imp)(*(in.get())); in->inc_depth(); result.push_back(in.get()); + m_clean = false; } catch (rewriter_exception & ex) { throw tactic_exception(ex.msg()); @@ -106,10 +107,13 @@ void simplify_tactic::operator()(goal_ref const & in, void simplify_tactic::cleanup() { + if (m_clean) + return; ast_manager & m = m_imp->m(); params_ref p = std::move(m_params); m_imp->~imp(); new (m_imp) imp(m, p); + m_clean = true; } void simplify_tactic::collect_statistics(statistics& st) const { diff --git a/src/tactic/core/simplify_tactic.h b/src/tactic/core/simplify_tactic.h index 7baabb8d6..af0806162 100644 --- a/src/tactic/core/simplify_tactic.h +++ b/src/tactic/core/simplify_tactic.h @@ -69,6 +69,7 @@ There are several options to control its behavior. #include "tactic/tactical.h" class simplify_tactic : public tactic { + bool m_clean = true; struct imp; imp * m_imp; params_ref m_params; diff --git a/src/tactic/smtlogics/qfnra_tactic.cpp b/src/tactic/smtlogics/qfnra_tactic.cpp index f95ae8a8c..ab28ffab7 100644 --- a/src/tactic/smtlogics/qfnra_tactic.cpp +++ b/src/tactic/smtlogics/qfnra_tactic.cpp @@ -89,7 +89,7 @@ tactic * mk_qfnra_very_small_solver(ast_manager& m, params_ref const& p) { p_i.set_bool("shuffle_vars", true); // if ((i & 1) == 0) // p_i.set_bool("randomize", false); - ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_i), 3 * 1000)); + ts.push_back(mk_lazy_tactic(m, p_i, [&](ast_manager& m, params_ref const& p) { return try_for(mk_qfnra_nlsat_tactic(m, p_i), 3 * 1000); })); } { ts.push_back(mk_qfnra_nlsat_tactic(m, p)); @@ -147,7 +147,7 @@ tactic * mk_qfnra_small_solver(ast_manager& m, params_ref const& p) { p_i.set_bool("shuffle_vars", true); // if ((i & 1) == 0) // p_i.set_bool("randomize", false); - ts.push_back(try_for(mk_qfnra_nlsat_tactic(m, p_i), 5 * 1000)); + ts.push_back(mk_lazy_tactic(m, p_i, [&](ast_manager& m, params_ref const& p) { return try_for(mk_qfnra_nlsat_tactic(m, p_i), 5 * 1000); })); } { ts.push_back(mk_qfnra_nlsat_tactic(m, p)); @@ -308,15 +308,20 @@ const double SMALL_THRESHOLD = 80.0; const double MIDDLE_THRESHOLD = 300.0; const double LARGE_THRESHOLD = 600.0; tactic * mk_qfnra_mixed_solver(ast_manager& m, params_ref const& p) { + auto very_small_t = mk_lazy_tactic(m, p, [&](ast_manager& m, params_ref const& p) {return mk_qfnra_very_small_solver(m, p); }); + auto small_t = mk_lazy_tactic(m, p, [&](ast_manager& m, params_ref const& p) {return mk_qfnra_small_solver(m, p); }); + auto middle_t = mk_lazy_tactic(m, p, [&](ast_manager& m, params_ref const& p) {return mk_qfnra_middle_solver(m, p); }); + auto large_t = mk_lazy_tactic(m, p, [&](ast_manager& m, params_ref const& p) {return mk_qfnra_large_solver(m, p); }); + auto very_large_t = mk_lazy_tactic(m, p, [&](ast_manager& m, params_ref const& p) {return mk_qfnra_very_large_solver(m, p); }); return cond(mk_lt(mk_memory_probe(), mk_const_probe(VERY_SMALL_THRESHOLD)), - mk_qfnra_very_small_solver(m, p), + very_small_t, cond(mk_lt(mk_memory_probe(), mk_const_probe(SMALL_THRESHOLD)), - mk_qfnra_small_solver(m, p), + small_t, cond(mk_lt(mk_memory_probe(), mk_const_probe(MIDDLE_THRESHOLD)), - mk_qfnra_middle_solver(m, p), + middle_t, cond(mk_lt(mk_memory_probe(), mk_const_probe(LARGE_THRESHOLD)), - mk_qfnra_large_solver(m, p), - mk_qfnra_very_large_solver(m, p) + large_t, + very_large_t ) ) ) diff --git a/src/tactic/tactic.cpp b/src/tactic/tactic.cpp index e4e7b246a..19a370caa 100644 --- a/src/tactic/tactic.cpp +++ b/src/tactic/tactic.cpp @@ -95,6 +95,32 @@ tactic * mk_skip_tactic() { return alloc(skip_tactic); } +class lazy_tactic : public tactic { + ast_manager& m; + params_ref p; + std::function m_mk_tactic; + tactic* m_tactic = nullptr; + void ensure_tactic() { if (!m_tactic) m_tactic = m_mk_tactic(m, p); } +public: + lazy_tactic(ast_manager& m, params_ref const& p, std::function mk_tactic) : m(m), p(p), m_mk_tactic(mk_tactic) {} + ~lazy_tactic() override { dealloc(m_tactic); } + void operator()(goal_ref const& in, goal_ref_buffer& result) override { + ensure_tactic(); + (*m_tactic)(in, result); + } + void cleanup() override { if (m_tactic) m_tactic->cleanup(); } + char const* name() const override { return "lazy tactic"; } + void collect_statistics(statistics& st) const override { if (m_tactic) m_tactic->collect_statistics(st); } + void user_propagate_initialize_value(expr* var, expr* value) override { if (m_tactic) m_tactic->user_propagate_initialize_value(var, value); } + tactic* translate(ast_manager& m) override { ensure_tactic(); return m_tactic->translate(m); } + void reset() override { if (m_tactic) m_tactic->reset(); } +}; + + +tactic* mk_lazy_tactic(ast_manager& m, params_ref const& p, std::function mkt) { + return alloc(lazy_tactic, m, p, mkt); +} + class fail_tactic : public tactic { public: void operator()(goal_ref const & in, goal_ref_buffer & result) override { diff --git a/src/tactic/tactic.h b/src/tactic/tactic.h index c69276424..698146c0d 100644 --- a/src/tactic/tactic.h +++ b/src/tactic/tactic.h @@ -135,6 +135,7 @@ public: tactic * mk_skip_tactic(); tactic * mk_fail_tactic(); tactic * mk_fail_if_undecided_tactic(); +tactic* mk_lazy_tactic(ast_manager& m, params_ref const& p, std::function); /* ADD_TACTIC("skip", "do nothing tactic.", "mk_skip_tactic()") diff --git a/src/tactic/tactical.cpp b/src/tactic/tactical.cpp index db0a6d44d..78e15aef7 100644 --- a/src/tactic/tactical.cpp +++ b/src/tactic/tactical.cpp @@ -30,6 +30,7 @@ class binary_tactical : public tactic { protected: tactic_ref m_t1; tactic_ref m_t2; + bool m_clean = true; public: @@ -61,8 +62,11 @@ public: } void cleanup() override { + if (m_clean) + return; m_t1->cleanup(); m_t2->cleanup(); + m_clean = true; } void reset() override { @@ -103,7 +107,8 @@ public: char const* name() const override { return "and_then"; } - void operator()(goal_ref const & in, goal_ref_buffer& result) override { + void operator()(goal_ref const & in, goal_ref_buffer& result) override { + m_clean = false; bool proofs_enabled = in->proofs_enabled(); bool cores_enabled = in->unsat_core_enabled(); @@ -872,6 +877,7 @@ tactic * par_and_then(unsigned num, tactic * const * ts) { class unary_tactical : public tactic { protected: tactic_ref m_t; + bool m_clean = true; public: @@ -880,11 +886,12 @@ public: SASSERT(t); } - void operator()(goal_ref const & in, goal_ref_buffer& result) override { + void operator()(goal_ref const & in, goal_ref_buffer& result) override { + m_clean = false; m_t->operator()(in, result); } - void cleanup(void) override { m_t->cleanup(); } + void cleanup(void) override { if (!m_clean) m_t->cleanup(); m_clean = true; } void collect_statistics(statistics & st) const override { m_t->collect_statistics(st); } void reset_statistics() override { m_t->reset_statistics(); } void updt_params(params_ref const & p) override { m_t->updt_params(p); } @@ -1158,6 +1165,7 @@ public: char const* name() const override { return "cond"; } void operator()(goal_ref const & in, goal_ref_buffer & result) override { + m_clean = false; if (m_p->operator()(*(in.get())).is_true()) m_t1->operator()(in, result); else From 40b0210dda9b695d884afea01d3ff6ef07da2fd0 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 27 Sep 2024 14:33:09 +0100 Subject: [PATCH 149/187] fixes to lazy tactic uses Signed-off-by: Nikolaj Bjorner --- src/tactic/smtlogics/qfnra_tactic.cpp | 4 ++-- src/tactic/tactic.cpp | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tactic/smtlogics/qfnra_tactic.cpp b/src/tactic/smtlogics/qfnra_tactic.cpp index ab28ffab7..5e5f2508b 100644 --- a/src/tactic/smtlogics/qfnra_tactic.cpp +++ b/src/tactic/smtlogics/qfnra_tactic.cpp @@ -89,7 +89,7 @@ tactic * mk_qfnra_very_small_solver(ast_manager& m, params_ref const& p) { p_i.set_bool("shuffle_vars", true); // if ((i & 1) == 0) // p_i.set_bool("randomize", false); - ts.push_back(mk_lazy_tactic(m, p_i, [&](ast_manager& m, params_ref const& p) { return try_for(mk_qfnra_nlsat_tactic(m, p_i), 3 * 1000); })); + ts.push_back(mk_lazy_tactic(m, p_i, [&](ast_manager& m, params_ref const& p) { return try_for(mk_qfnra_nlsat_tactic(m, p), 3 * 1000); })); } { ts.push_back(mk_qfnra_nlsat_tactic(m, p)); @@ -147,7 +147,7 @@ tactic * mk_qfnra_small_solver(ast_manager& m, params_ref const& p) { p_i.set_bool("shuffle_vars", true); // if ((i & 1) == 0) // p_i.set_bool("randomize", false); - ts.push_back(mk_lazy_tactic(m, p_i, [&](ast_manager& m, params_ref const& p) { return try_for(mk_qfnra_nlsat_tactic(m, p_i), 5 * 1000); })); + ts.push_back(mk_lazy_tactic(m, p_i, [&](ast_manager& m, params_ref const& p) { return try_for(mk_qfnra_nlsat_tactic(m, p), 5 * 1000); })); } { ts.push_back(mk_qfnra_nlsat_tactic(m, p)); diff --git a/src/tactic/tactic.cpp b/src/tactic/tactic.cpp index 19a370caa..36dc5d4d0 100644 --- a/src/tactic/tactic.cpp +++ b/src/tactic/tactic.cpp @@ -114,6 +114,11 @@ public: void user_propagate_initialize_value(expr* var, expr* value) override { if (m_tactic) m_tactic->user_propagate_initialize_value(var, value); } tactic* translate(ast_manager& m) override { ensure_tactic(); return m_tactic->translate(m); } void reset() override { if (m_tactic) m_tactic->reset(); } + void reset_statistics() override { if (m_tactic) m_tactic->reset_statistics(); } + void register_on_clause(void* ctx, user_propagator::on_clause_eh_t& on_clause) override { + ensure_tactic(); + m_tactic->register_on_clause(ctx, on_clause); + } }; From 11bb19d99bf9081acf48f0399871f5a08d10c5f9 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 27 Sep 2024 15:11:43 +0100 Subject: [PATCH 150/187] make default tactic cases lazy --- src/tactic/portfolio/default_tactic.cpp | 27 +++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 7f145b614..fc69b45ae 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -35,20 +35,21 @@ Notes: tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), - cond(mk_and(mk_is_propositional_probe(), mk_not(mk_produce_proofs_probe())), mk_fd_tactic(m, p), - cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), - cond(mk_is_qfaufbv_probe(), mk_qfaufbv_tactic(m), - cond(mk_is_qflia_probe(), mk_qflia_tactic(m), - cond(mk_is_qfauflia_probe(), mk_qfauflia_tactic(m), - cond(mk_is_qflra_probe(), mk_qflra_tactic(m), - cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), - cond(mk_is_qfnia_probe(), mk_qfnia_tactic(m), - cond(mk_is_lira_probe(), mk_lira_tactic(m, p), - cond(mk_is_nra_probe(), mk_nra_tactic(m), - cond(mk_is_qffp_probe(), mk_qffp_tactic(m, p), - cond(mk_is_qffplra_probe(), mk_qffplra_tactic(m, p), + cond(mk_and(mk_is_propositional_probe(), mk_not(mk_produce_proofs_probe())), + mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_fd_tactic(m, p); }), + cond(mk_is_qfbv_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_qfbv_tactic(m); }), + cond(mk_is_qfaufbv_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_qfaufbv_tactic(m); }), + cond(mk_is_qflia_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_qflia_tactic(m); }), + cond(mk_is_qfauflia_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_qfauflia_tactic(m); }), + cond(mk_is_qflra_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_qflra_tactic(m); }), + cond(mk_is_qfnra_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_qfnra_tactic(m); }), + cond(mk_is_qfnia_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_qfnia_tactic(m); }), + cond(mk_is_lira_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_lira_tactic(m, p); }), + cond(mk_is_nra_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_nra_tactic(m); }), + cond(mk_is_qffp_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_qffp_tactic(m, p); }), + cond(mk_is_qffplra_probe(), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_qffplra_tactic(m, p); }), //cond(mk_is_qfufnra_probe(), mk_qfufnra_tactic(m, p), - and_then(mk_preamble_tactic(m), mk_smt_tactic(m))))))))))))))), + and_then(mk_preamble_tactic(m), mk_lazy_tactic(m, p, [&](auto& m, auto const& p) { return mk_smt_tactic(m);}))))))))))))))), p); return st; } From 9a8ff74924561557f2b0e748f95a7764540e866a Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 27 Sep 2024 17:49:05 +0100 Subject: [PATCH 151/187] update version number and release notes --- CMakeLists.txt | 2 +- RELEASE_NOTES.md | 4 ++++ scripts/mk_project.py | 2 +- scripts/nightly.yaml | 2 +- scripts/release.yml | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4603ae1de..526cd9b83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake") -project(Z3 VERSION 4.13.1.0 LANGUAGES CXX) +project(Z3 VERSION 4.13.2.0 LANGUAGES CXX) ################################################################################ # Project version diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 50e181aeb..c35875fed 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -10,6 +10,10 @@ Version 4.next - native word level bit-vector solving. - introduction of simple induction lemmas to handle a limited repertoire of induction proofs. +Version 4.13.2 +============== +- Performance regression fix. #7404 + Version 4.13.1 ============== - single-sample cell projection in nlsat was designed by Haokun Li and Bican Xia. diff --git a/scripts/mk_project.py b/scripts/mk_project.py index ce2e7cb7e..8284e80b2 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -8,7 +8,7 @@ from mk_util import * def init_version(): - set_version(4, 13, 1, 0) # express a default build version or pick up ci build version + set_version(4, 13, 2, 0) # express a default build version or pick up ci build version # Z3 Project definition def init_project_def(): diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index d1c565883..5e595a8f5 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -1,7 +1,7 @@ variables: Major: '4' Minor: '13' - Patch: '1' + Patch: '2' ReleaseVersion: $(Major).$(Minor).$(Patch) AssemblyVersion: $(Major).$(Minor).$(Patch).$(Build.BuildId) NightlyVersion: $(AssemblyVersion)-$(Build.buildId) diff --git a/scripts/release.yml b/scripts/release.yml index 349c8d6ce..4e0032803 100644 --- a/scripts/release.yml +++ b/scripts/release.yml @@ -6,7 +6,7 @@ trigger: none variables: - ReleaseVersion: '4.13.1' + ReleaseVersion: '4.13.2' stages: From fc1c6b48ce2240be4c29383a2af2f0651356cb62 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 04:14:12 +0100 Subject: [PATCH 152/187] try to build java on linux/arm nightly Signed-off-by: Nikolaj Bjorner --- genaisrc/genaiscript.d.ts | Bin 65101 -> 73251 bytes scripts/nightly.yaml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/genaisrc/genaiscript.d.ts b/genaisrc/genaiscript.d.ts index df355fd9fa1b190cf319b4f7c3aed7f553ed3c6f..c0a6426d2c5fa168f0c708d8f185820733d3431f 100644 GIT binary patch delta 6888 zcmc&(U2I%O6_)FyEiN%}{hyz9>Wb8M96J#qfMYu`PC^{=SI3YD*L7y^on2pi_ulQD zxpvoa+4O-Ts)C3IRpJR%yzl^0qLqpWMKte}01{AWgi_!Mi6SJVs4WkiGc)&ZcS9T` zgkS7Czvq1C%y)kL*1wv+_r|8H@3qU-wyl*(;yPRqKTnFj&0ONxoKVjuVv#ukDbnYi zVpt?zSj@2iS6RMig+ahPK?3$%$hhFcEd+lCN7Qe1%v7|>DjympGtBY>dyI>~@d`uc zu!)uzT3Q^r+}R_4*x6p)*>P)kHy*P_`f87mcMg4i%Sp#$rLyz8&bgx)zpMaapxx(-YT2$ozXnB5nRPzw#TfKKC7g4BdX!F;Zp8p%_~4FeW$ z^;jqZ>c-!E$tjgm>$#wAvYLmM#W;^w3#Z8J1wRz=h*R+vN`YSp(#yb?!_=9^xlp#nWvl|)0koMRe1vYu z0ng0vqA0oxVc=#4t$ z$hc^iC2f}}peZEchCWs=d?QZ)Y{HUV=OE|@#tL}fw7%~w$TFizKjv9IV?abkuc4+X zh$`n84Xni(#zR-$ywE#Sq9W^a;BFb1qq{SM9D)eIssUG!Agysn_(2(k{7lwa8>3R^ zY$yxv{*+OX795WvQ)M}|L<>lRsmn_&Sb$NvZ>{H9z4w^ovKSZSMqYxbp+>cZkUGKo zd03}RZ99Sb&BGjoywHsDa?y3XCCxM3S!MFZ16>d5E9C8w?vwEPJ%|<{BXK+kUPUD@ z!7%1q!e4TPLMIByxTb$#ltghvpJddNlg~bO;Ur`LoU9l&=Wr^ahT$fL~G~f<>m3N@#HoF+`*OXloXt0=EZWD`^e!E4QMeQp0?!; z>&XLY0U-YHe!UzVH_}5fl774JuC(Rki|ZY-e}C%}n)tGh8}_On22u$5)9c-1ig{zL zA|2vz7hm}T*_G8CY$GS$?ylia*a!i>MQu|#2wpcxjzGY6eTs=!g!-g5Z=?!>M1bpR zAc4_o+l=YtD~$@Ubx#TwwK(!%#KBnRER8%KC2r4}3(n9MdmOw1i85=d#5vF=kKpZ! z33$J}LObNZ{w?z6&o++$f_=zv%GoW~=Z5O2Yht>_oe-Din9C7**AE14Gn}P%8luvt zXzDXjKH3itNR=B;wZj+tHk2d9+gZz0Hf$Mw4||k+kcbA3 zC@aie-z)3^kMrV$siBDm@6SfYIaBJybkfjJX^?8{g;ObWjn=?4!PM=koE&GqLNxpgG!3XpW7Dp^LeELir z6;D#H5JGam(;>ET!Hb%l+W0+S@Z=gOsG+VEiS^O)hvawv&@108w?REsQ@Nr2@TcJV zIe6r$6jqNz!C|6~IT;q^eBWi%OMC&ALIWTQPv;;NfmNv#C^||INNixL9}^tt5olAQ zw+_tp;aHz+T5a#lCLlNs(XhHZywlu%PPGP{d^yRwI3hdBCk{kSikc@TpkF}tkXb1Iai>Wagij#p;A|Me zT2}|mYq6+HI1_jcm#bge0nhTGsbOfEI7J6q1m>9JJA^og?uxyI!}>Un}1@t)!=E zy$rH709$<702AvJT?9HoD!a@Ap&;1R2xk@Av{k@60QvtlT3R@=#L97BD}|TQcRMz+ z>VeYe%$K@{KbMx`6d~T#`Pehe#M0G1o)*fFr6MD#wC189kk}t3K$bt25w3&wF*lbi*%6~l5 z-83O@|Ah3qEDs%>*(B-*PGJ#8Ah+*nhBl^r@!Q*~udjD+k{{XMS^eFs?;LH~TfKJc zmF9<`oA@+#yX1>6w?Ag9y2E2DNGjN9L|VdUuNq=<&u@Avy0)OUJvJE>LY)vteb&%h z^1!9g%V!j;%mUv}BylPqdb;rk;bC}qm_`RIjFR}U0Wv;8Cb7SUb{{m1Bm5I3)p?tazW2+}||F#As z*ZVr;q1&%lltgg~JV>Tg0~FHjw2x~r0c$8y2<2tZiY)-Wi8>d^V65$JUWgM&>@}oJ_HtMlfP~5 zsD9<|e|~6YQuWBu*>tjouRU-~d5@1F`6o}(|ABvo*vx`5kC9~>K)XgPhPkNcQ@wEK zdh^j4Xo|A{I~g`m5N0rVm{{>mb4R-l{`bYSb&$qVpNhm}<^A2Q_@9_8@ihaj$g}HR Zof+zjY46<+Iuz}Vy}zyc=!XZJ{|!My?ezcv delta 336 zcmZ3yhvn=a<_+(JC;!Rkoy;Z1KiNV|c=9So!Oc5GPHRt|>)^@imYSEGx_P0aI^$#> z$F#{cM+G*YaN=Q|Y@^GyIol&oW-{|6xk;)0lMl0qZ(g6uDZrJVl$DxX5*-^IJ9%QE zQTty()d zDNcOy2?rr@g&Kw6jMSVQ|I(6z(h?vK?D~|+jL9OCzptLKS#GU3%Vez$T${Z%-ge!r z{=J)d^1Z)1HtYUZ Date: Mon, 30 Sep 2024 04:16:29 +0100 Subject: [PATCH 153/187] Update nightly.yaml for Azure Pipelines --- scripts/nightly.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index 510aa7cfd..ab8cacf38 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -449,7 +449,7 @@ stages: pool: vmImage: "ubuntu-latest" steps: - - task: DownloadPipelineArtifact@2 + - task: DownloadPipelineArtifact@2 displayName: 'Download macOS Build' inputs: artifactName: 'macOsBuild' From c2b2626e9ba622c6370e4b54efcf3180717f906e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 07:27:09 -0700 Subject: [PATCH 154/187] remove --java option Signed-off-by: Nikolaj Bjorner --- scripts/nightly.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index ab8cacf38..bbcb01a1d 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -92,7 +92,7 @@ stages: - script: echo '##vso[task.prependpath]/tmp/arm-toolchain/aarch64-none-linux-gnu/libc/usr/bin' - script: echo $PATH - script: stat /tmp/arm-toolchain/bin/aarch64-none-linux-gnu-gcc - - script: python scripts/mk_unix_dist.py --nodotnet --java --arch=arm64 + - script: python scripts/mk_unix_dist.py --nodotnet --arch=arm64 - task: CopyFiles@2 inputs: sourceFolder: dist From 2ac6f8bb06ec9f298526f7960a0f90eb84c21ff3 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 07:28:20 -0700 Subject: [PATCH 155/187] increment minor revision number Signed-off-by: Nikolaj Bjorner --- CMakeLists.txt | 2 +- scripts/mk_project.py | 2 +- scripts/nightly.yaml | 2 +- scripts/release.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 526cd9b83..797087641 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake") -project(Z3 VERSION 4.13.2.0 LANGUAGES CXX) +project(Z3 VERSION 4.13.3.0 LANGUAGES CXX) ################################################################################ # Project version diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 8284e80b2..5d1b2983f 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -8,7 +8,7 @@ from mk_util import * def init_version(): - set_version(4, 13, 2, 0) # express a default build version or pick up ci build version + set_version(4, 13, 3, 0) # express a default build version or pick up ci build version # Z3 Project definition def init_project_def(): diff --git a/scripts/nightly.yaml b/scripts/nightly.yaml index bbcb01a1d..74768fbea 100644 --- a/scripts/nightly.yaml +++ b/scripts/nightly.yaml @@ -1,7 +1,7 @@ variables: Major: '4' Minor: '13' - Patch: '2' + Patch: '3' ReleaseVersion: $(Major).$(Minor).$(Patch) AssemblyVersion: $(Major).$(Minor).$(Patch).$(Build.BuildId) NightlyVersion: $(AssemblyVersion)-$(Build.buildId) diff --git a/scripts/release.yml b/scripts/release.yml index 4e0032803..148adc26b 100644 --- a/scripts/release.yml +++ b/scripts/release.yml @@ -6,7 +6,7 @@ trigger: none variables: - ReleaseVersion: '4.13.2' + ReleaseVersion: '4.13.3' stages: From 826835fd7c74ba1c9debb590b23a8e95fe00accb Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 08:23:31 -0700 Subject: [PATCH 156/187] fixes to build warnings --- src/ast/euf/euf_ac_plugin.cpp | 5 +++-- src/ast/euf/euf_egraph.cpp | 4 ++-- src/math/lp/nla_divisions.cpp | 2 -- src/muz/ddnf/ddnf.cpp | 9 ++------- src/muz/fp/datalog_parser.cpp | 4 +--- src/muz/rel/dl_product_relation.cpp | 1 + src/muz/spacer/spacer_unsat_core_plugin.cpp | 4 +--- src/opt/opt_cores.cpp | 3 +-- src/opt/opt_lns.cpp | 2 -- src/parsers/smt2/smt2parser.cpp | 1 - src/sat/sat_clause_use_list.cpp | 6 +++--- src/sat/sat_lookahead.cpp | 1 - src/shell/dimacs_frontend.cpp | 1 - src/smt/diff_logic.h | 1 + src/smt/dyn_ack.cpp | 6 ------ src/smt/theory_arith_core.h | 17 +---------------- src/smt/theory_bv.cpp | 1 + src/smt/theory_lra.cpp | 2 -- src/smt/theory_pb.cpp | 6 +++--- src/tactic/smtlogics/qfnra_tactic.cpp | 8 -------- src/util/params.cpp | 1 - 21 files changed, 20 insertions(+), 65 deletions(-) diff --git a/src/ast/euf/euf_ac_plugin.cpp b/src/ast/euf/euf_ac_plugin.cpp index 69d0e6572..9a7202362 100644 --- a/src/ast/euf/euf_ac_plugin.cpp +++ b/src/ast/euf/euf_ac_plugin.cpp @@ -440,8 +440,9 @@ namespace euf { TRACE("plugin", tout << "propagate " << eq_id << ": " << eq_pp(*this, m_eqs[eq_id]) << "\n"); // simplify eq using processed - for (auto other_eq : backward_iterator(eq_id)) - TRACE("plugin", tout << "backward iterator " << eq_id << " vs " << other_eq << " " << is_processed(other_eq) << "\n"); + TRACE("plugin", + for (auto other_eq : backward_iterator(eq_id)) + tout << "backward iterator " << eq_id << " vs " << other_eq << " " << is_processed(other_eq) << "\n");); for (auto other_eq : backward_iterator(eq_id)) if (is_processed(other_eq) && backward_simplify(eq_id, other_eq)) goto loop_start; diff --git a/src/ast/euf/euf_egraph.cpp b/src/ast/euf/euf_egraph.cpp index 21bc14ba4..eaa290bbf 100644 --- a/src/ast/euf/euf_egraph.cpp +++ b/src/ast/euf/euf_egraph.cpp @@ -107,8 +107,8 @@ namespace euf { void egraph::update_children(enode* n) { for (enode* child : enode_args(n)) child->get_root()->add_parent(n); - for (enode* child : enode_args(n)) - SASSERT(child->get_root()->m_parents.back() == n); + DEBUG_CODE(for (enode* child : enode_args(n)) + SASSERT(child->get_root()->m_parents.back() == n);); m_updates.push_back(update_record(n, update_record::update_children())); } diff --git a/src/math/lp/nla_divisions.cpp b/src/math/lp/nla_divisions.cpp index 6c3bb178c..72b6d73f0 100644 --- a/src/math/lp/nla_divisions.cpp +++ b/src/math/lp/nla_divisions.cpp @@ -19,7 +19,6 @@ Description: namespace nla { void divisions::add_idivision(lpvar q, lpvar x, lpvar y) { - const auto& lra = m_core.lra; if (x == null_lpvar || y == null_lpvar || q == null_lpvar) return; m_idivisions.push_back({q, x, y}); @@ -27,7 +26,6 @@ namespace nla { } void divisions::add_rdivision(lpvar q, lpvar x, lpvar y) { - auto& lra = m_core.lra; if (x == null_lpvar || y == null_lpvar || q == null_lpvar) return; m_rdivisions.push_back({ q, x, y }); diff --git a/src/muz/ddnf/ddnf.cpp b/src/muz/ddnf/ddnf.cpp index f4f946d09..eaf352475 100644 --- a/src/muz/ddnf/ddnf.cpp +++ b/src/muz/ddnf/ddnf.cpp @@ -678,14 +678,9 @@ namespace datalog { } bool compile_rules1(rule_set const& rules, rule_set& new_rules) { - datalog::rule_set::iterator it = rules.begin(); - datalog::rule_set::iterator end = rules.end(); - unsigned idx = 0; - for (; it != end; ++idx, ++it) { - if (!compile_rule1(**it, rules, new_rules)) { + for (auto const & r : rules) + if (!compile_rule1(*r, rules, new_rules)) return false; - } - } return true; } diff --git a/src/muz/fp/datalog_parser.cpp b/src/muz/fp/datalog_parser.cpp index d748dca63..4d8f60121 100644 --- a/src/muz/fp/datalog_parser.cpp +++ b/src/muz/fp/datalog_parser.cpp @@ -902,7 +902,6 @@ protected: unsigned arg_idx = 0; tok = m_lexer->next_token(); while (tok != TK_EOS && tok != TK_ERROR) { - symbol alias; sort* s = nullptr; if(!f) { @@ -939,7 +938,6 @@ protected: } s = f->get_domain(arg_idx); - symbol var_symbol; tok = parse_arg(tok, s, args); } @@ -1067,7 +1065,7 @@ protected: bool read_line(std::istream& strm, std::string& line) { line.clear(); - char ch = strm.get(); + int ch = strm.get(); while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') { ch = strm.get(); } diff --git a/src/muz/rel/dl_product_relation.cpp b/src/muz/rel/dl_product_relation.cpp index 52c168f12..701bad3cc 100644 --- a/src/muz/rel/dl_product_relation.cpp +++ b/src/muz/rel/dl_product_relation.cpp @@ -1030,6 +1030,7 @@ namespace datalog { } new_rels.push_back(irel); } + (void)old_remain; SASSERT(old_remain==0); //the new specification must be a superset of the old one m_relations = new_rels; diff --git a/src/muz/spacer/spacer_unsat_core_plugin.cpp b/src/muz/spacer/spacer_unsat_core_plugin.cpp index c0a9d7e6f..f0cfcbcd2 100644 --- a/src/muz/spacer/spacer_unsat_core_plugin.cpp +++ b/src/muz/spacer/spacer_unsat_core_plugin.cpp @@ -97,7 +97,6 @@ namespace spacer { // XXX this assertion should be true so there is no need to check for it SASSERT (!m_ctx.is_closed (step)); func_decl* d = step->get_decl(); - symbol sym; TRACE("spacer.farkas", tout << "looking at: " << mk_pp(step, m) << "\n";); if (!m_ctx.is_closed(step) && is_farkas_lemma(m, step)) { @@ -239,9 +238,8 @@ namespace spacer { SASSERT(m_ctx.is_b(step)); func_decl* d = step->get_decl(); - symbol sym; if (!m_ctx.is_closed(step) && // if step is not already interpolated - is_farkas_lemma(m, step)) { + is_farkas_lemma(m, step)) { SASSERT(d->get_num_parameters() == m.get_num_parents(step) + 2); SASSERT(m.has_fact(step)); diff --git a/src/opt/opt_cores.cpp b/src/opt/opt_cores.cpp index 124df63d7..44376e2f5 100644 --- a/src/opt/opt_cores.cpp +++ b/src/opt/opt_cores.cpp @@ -256,12 +256,11 @@ namespace opt { void cores::rotate_cores() { expr_ref_vector soft(m); soft.append(ctx.soft()); - unsigned num_sat = 0, num_unsat = 0, num_undef = 0; + unsigned num_sat = 0, num_undef = 0; lbool is_sat = l_false; while (m.inc() && m_cores.size() < m_max_num_cores) { switch (is_sat) { case l_false: { - ++num_unsat; auto core = unsat_core(); add_core(core); if (core.empty()) diff --git a/src/opt/opt_lns.cpp b/src/opt/opt_lns.cpp index 878c4a3ea..ae9bff215 100644 --- a/src/opt/opt_lns.cpp +++ b/src/opt/opt_lns.cpp @@ -174,7 +174,6 @@ namespace opt { void lns::relax_cores() { if (!m_cores.empty() && m_cores_are_valid) { std::sort(m_cores.begin(), m_cores.end(), [&](expr_ref_vector const& a, expr_ref_vector const& b) { return a.size() < b.size(); }); - unsigned num_disjoint = 0; vector new_cores; for (auto const& c : m_cores) { bool in_core = false; @@ -185,7 +184,6 @@ namespace opt { for (auto* e : c) m_in_core.mark(e); new_cores.push_back(c); - ++num_disjoint; } IF_VERBOSE(2, verbose_stream() << "num cores: " << m_cores.size() << " new cores: " << new_cores.size() << "\n"); ctx.relax_cores(new_cores); diff --git a/src/parsers/smt2/smt2parser.cpp b/src/parsers/smt2/smt2parser.cpp index 98323816a..48c48d0a9 100644 --- a/src/parsers/smt2/smt2parser.cpp +++ b/src/parsers/smt2/smt2parser.cpp @@ -942,7 +942,6 @@ namespace smt2 { } for (unsigned i = 0; i < sz; i++) { pdatatype_decl * d = new_dt_decls[i]; - symbol duplicated; check_duplicate(d, line, pos); if (!is_smt2_6) { // datatypes are inserted up front in SMT2.6 mode, so no need to re-insert them. diff --git a/src/sat/sat_clause_use_list.cpp b/src/sat/sat_clause_use_list.cpp index 7ca0aa2c6..347e49db9 100644 --- a/src/sat/sat_clause_use_list.cpp +++ b/src/sat/sat_clause_use_list.cpp @@ -25,13 +25,13 @@ namespace sat { unsigned sz = 0; for (clause* c : m_clauses) if (!c->was_removed()) - sz++; - SASSERT(sz == m_size); + sz++; + VERIFY(sz == m_size); unsigned redundant = 0; for (clause* c : m_clauses) if (c->is_learned()) redundant++; - SASSERT(redundant == m_num_redundant); + VERIFY(redundant == m_num_redundant); return true; } diff --git a/src/sat/sat_lookahead.cpp b/src/sat/sat_lookahead.cpp index 2f3fc91b2..3fef08559 100644 --- a/src/sat/sat_lookahead.cpp +++ b/src/sat/sat_lookahead.cpp @@ -1392,7 +1392,6 @@ namespace sat { void lookahead::propagate_clauses_searching(literal l) { // clauses where l is negative unsigned sz = m_nary_count[(~l).index()]; - literal lit; SASSERT(m_search_mode == lookahead_mode::searching); for (nary* n : m_nary[(~l).index()]) { if (sz-- == 0) break; diff --git a/src/shell/dimacs_frontend.cpp b/src/shell/dimacs_frontend.cpp index 12dedb64f..afeb604a8 100644 --- a/src/shell/dimacs_frontend.cpp +++ b/src/shell/dimacs_frontend.cpp @@ -110,7 +110,6 @@ static void track_clauses(sat::solver const& src, dst.mk_var(false, true); } sat::literal_vector lits; - sat::literal lit; sat::clause * const * it = src.begin_clauses(); sat::clause * const * end = src.end_clauses(); svector bin_clauses; diff --git a/src/smt/diff_logic.h b/src/smt/diff_logic.h index ee1dbd63a..cd4c8bf75 100644 --- a/src/smt/diff_logic.h +++ b/src/smt/diff_logic.h @@ -569,6 +569,7 @@ public: void traverse_neg_cycle2(bool try_relax, Functor & f) { static unsigned num_conflicts = 0; ++num_conflicts; + (void)num_conflicts; SASSERT(!is_feasible(m_edges[m_last_enabled_edge])); vector potentials; svector edges; diff --git a/src/smt/dyn_ack.cpp b/src/smt/dyn_ack.cpp index 978f1fbe3..66a2c2d5d 100644 --- a/src/smt/dyn_ack.cpp +++ b/src/smt/dyn_ack.cpp @@ -294,7 +294,6 @@ namespace smt { void dyn_ack_manager::gc() { TRACE("dyn_ack", tout << "dyn_ack GC\n";); - unsigned num_deleted = 0; m_to_instantiate.reset(); m_qhead = 0; svector::iterator it = m_app_pairs.begin(); @@ -318,7 +317,6 @@ namespace smt { // SASSERT(num_occs > 0); num_occs = static_cast(num_occs * m_params.m_dack_gc_inv_decay); if (num_occs <= 1) { - num_deleted++; TRACE("dyn_ack", tout << "2) erasing:\n" << mk_pp(p.first, m) << "\n" << mk_pp(p.second, m) << "\n";); m_app_pair2num_occs.erase(p.first, p.second); m.dec_ref(p.first); @@ -337,7 +335,6 @@ namespace smt { // app_pair_lt is not a total order on pairs of expressions. // So, we should use stable_sort to avoid different behavior in different platforms. std::stable_sort(m_to_instantiate.begin(), m_to_instantiate.end(), f); - // IF_VERBOSE(10, if (num_deleted > 0) verbose_stream() << "dynamic ackermann GC: " << num_deleted << "\n";); } class dyn_ack_clause_del_eh : public clause_del_eh { @@ -519,7 +516,6 @@ namespace smt { void dyn_ack_manager::gc_triples() { TRACE("dyn_ack", tout << "dyn_ack GC\n";); - unsigned num_deleted = 0; m_triple.m_to_instantiate.reset(); m_triple.m_qhead = 0; svector::iterator it = m_triple.m_apps.begin(); @@ -544,7 +540,6 @@ namespace smt { // SASSERT(num_occs > 0); num_occs = static_cast(num_occs * m_params.m_dack_gc_inv_decay); if (num_occs <= 1) { - num_deleted++; TRACE("dyn_ack", tout << "2) erasing:\n" << mk_pp(p.first, m) << "\n" << mk_pp(p.second, m) << "\n";); m_triple.m_app2num_occs.erase(p.first, p.second, p.third); m.dec_ref(p.first); @@ -563,7 +558,6 @@ namespace smt { app_triple_lt f(m_triple.m_app2num_occs); // app_triple_lt is not a total order std::stable_sort(m_triple.m_to_instantiate.begin(), m_triple.m_to_instantiate.end(), f); - // IF_VERBOSE(10, if (num_deleted > 0) verbose_stream() << "dynamic ackermann GC: " << num_deleted << "\n";); } diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index 4e4464a52..8a2d9f3c9 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -3030,7 +3030,7 @@ namespace smt { template void theory_arith::propagate_bounds() { TRACE("propagate_bounds_detail", display(tout);); - unsigned num_prop = 0, count = 0; + unsigned count = 0; for (unsigned r_idx : m_to_check) { row & r = m_rows[r_idx]; if (r.get_base_var() != null_theory_var) { @@ -3039,34 +3039,19 @@ namespace smt { int upper_idx; is_row_useful_for_bound_prop(r, lower_idx, upper_idx); - ++num_prop; if (lower_idx >= 0) count += imply_bound_for_monomial(r, lower_idx, true); else if (lower_idx == -1) count += imply_bound_for_all_monomials(r, true); - else - --num_prop; - ++num_prop; if (upper_idx >= 0) count += imply_bound_for_monomial(r, upper_idx, false); else if (upper_idx == -1) count += imply_bound_for_all_monomials(r, false); - else - --num_prop; // sneaking cheap eq detection in this loop propagate_cheap_eq(r_idx); } - -#if 0 - theory_var v = r.get_base_var(); - if (!is_int(v) || get_value(v).is_int()) { - // If an integer value is not assigned to an integer value, then - // bound propagation can diverge. - m_in_to_check.remove(v); - } -#endif } } diff --git a/src/smt/theory_bv.cpp b/src/smt/theory_bv.cpp index ca327891c..5740285a2 100644 --- a/src/smt/theory_bv.cpp +++ b/src/smt/theory_bv.cpp @@ -1988,6 +1988,7 @@ namespace smt { while (curr != v); zero_one_bits const & _bits = m_zero_one_bits[v]; + (void)num_bits; SASSERT(_bits.size() == num_bits); bool_vector already_found; already_found.resize(bv_sz, false); diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 135744f02..f0615293d 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -3495,10 +3495,8 @@ public: bool validate_eq(enode* x, enode* y) { static bool s_validating = false; - static unsigned s_count = 0; if (s_validating) return true; - ++s_count; flet _svalid(s_validating, true); context nctx(m, ctx().get_fparams(), ctx().get_params()); add_background(nctx); diff --git a/src/smt/theory_pb.cpp b/src/smt/theory_pb.cpp index 25c8e7195..ed3ff0942 100644 --- a/src/smt/theory_pb.cpp +++ b/src/smt/theory_pb.cpp @@ -2127,9 +2127,9 @@ namespace smt { tout << "sum: " << sum << " " << maxsum << " "; tout << ctx.get_assignment(c.lit()) << "\n";); - SASSERT(sum <= maxsum); - SASSERT((sum >= c.k()) == (ctx.get_assignment(c.lit()) == l_true)); - SASSERT((maxsum < c.k()) == (ctx.get_assignment(c.lit()) == l_false)); + VERIFY(sum <= maxsum); + VERIFY((sum >= c.k()) == (ctx.get_assignment(c.lit()) == l_true)); + VERIFY((maxsum < c.k()) == (ctx.get_assignment(c.lit()) == l_false)); } void theory_pb::validate_final_check(ineq& c) { diff --git a/src/tactic/smtlogics/qfnra_tactic.cpp b/src/tactic/smtlogics/qfnra_tactic.cpp index 5e5f2508b..79e0a4b39 100644 --- a/src/tactic/smtlogics/qfnra_tactic.cpp +++ b/src/tactic/smtlogics/qfnra_tactic.cpp @@ -25,14 +25,6 @@ Notes: #include "tactic/smtlogics/qflra_tactic.h" -static tactic * mk_qfnra_sat_solver(ast_manager& m, params_ref const& p, unsigned bv_size) { - params_ref nra2sat_p = p; - nra2sat_p.set_uint("nla2bv_max_bv_size", p.get_uint("nla2bv_max_bv_size", bv_size)); - - return and_then(mk_nla2bv_tactic(m, nra2sat_p), - mk_smt_tactic(m), - mk_fail_if_undecided_tactic()); -} tactic * mk_multilinear_ls_tactic(ast_manager & m, params_ref const & p, unsigned ls_time = 60) { params_ref p_mls = p; diff --git a/src/util/params.cpp b/src/util/params.cpp index 3440673b7..8ea7c1da3 100644 --- a/src/util/params.cpp +++ b/src/util/params.cpp @@ -390,7 +390,6 @@ public: void reset(char const * k); void validate(param_descrs const & p) { - symbol suffix, prefix; for (params::entry& e : m_entries) { param_kind expected = p.get_kind_in_module(e.first); if (expected == CPK_INVALID) { From 5413018d8690e04a85c979a6e6750305c3beb2af Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 08:43:17 -0700 Subject: [PATCH 157/187] Update euf_ac_plugin.cpp --- src/ast/euf/euf_ac_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/euf/euf_ac_plugin.cpp b/src/ast/euf/euf_ac_plugin.cpp index 9a7202362..0c890a26f 100644 --- a/src/ast/euf/euf_ac_plugin.cpp +++ b/src/ast/euf/euf_ac_plugin.cpp @@ -442,7 +442,7 @@ namespace euf { // simplify eq using processed TRACE("plugin", for (auto other_eq : backward_iterator(eq_id)) - tout << "backward iterator " << eq_id << " vs " << other_eq << " " << is_processed(other_eq) << "\n");); + tout << "backward iterator " << eq_id << " vs " << other_eq << " " << is_processed(other_eq) << "\n"); for (auto other_eq : backward_iterator(eq_id)) if (is_processed(other_eq) && backward_simplify(eq_id, other_eq)) goto loop_start; From b65afd41ed8c157168ca157e0b31d9d37290b48f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 08:58:21 -0700 Subject: [PATCH 158/187] attempt to use uniform java library location under bin #7406 --- scripts/mk_win_dist_cmake.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/mk_win_dist_cmake.py b/scripts/mk_win_dist_cmake.py index f3c83cfb6..ae73f91ff 100644 --- a/scripts/mk_win_dist_cmake.py +++ b/scripts/mk_win_dist_cmake.py @@ -376,9 +376,10 @@ def cp_into_bin(arch): shutil.rmtree(lib_dir) if JAVA_ENABLED: java_dir = get_java_dist_path(arch) - shutil.copytree(java_dir, - bin_dir, - dirs_exist_ok=True) + for file in os.listdir(java_dir): + src_path = os.path.join(java_dir, file) + dst_path = os.path.join(bin_dir, file) + shutil.copy2(src_path, dst_path) shutil.rmtree(java_dir) def cp_pdb(arch): From 30b4fe69e481d839443e75c0cc0c0ce8fb763516 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 10:05:09 -0700 Subject: [PATCH 159/187] 2nd attempt to use uniform java library location under bin #7406 Signed-off-by: Nikolaj Bjorner --- scripts/mk_win_dist_cmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_win_dist_cmake.py b/scripts/mk_win_dist_cmake.py index ae73f91ff..157965184 100644 --- a/scripts/mk_win_dist_cmake.py +++ b/scripts/mk_win_dist_cmake.py @@ -375,7 +375,7 @@ def cp_into_bin(arch): os.path.join(bin_dir, "libz3.lib")) shutil.rmtree(lib_dir) if JAVA_ENABLED: - java_dir = get_java_dist_path(arch) + java_dir = os.path.join(bin_dir, "java") for file in os.listdir(java_dir): src_path = os.path.join(java_dir, file) dst_path = os.path.join(bin_dir, file) From 7da58b9e843fe14a874757bb33991cf511f9e37c Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 10:34:26 -0700 Subject: [PATCH 160/187] fix build warnings --- src/ast/rewriter/inj_axiom.cpp | 1 + src/sat/sat_solver.cpp | 4 ++-- src/smt/diff_logic.h | 2 -- src/smt/theory_arith_aux.h | 1 + 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ast/rewriter/inj_axiom.cpp b/src/ast/rewriter/inj_axiom.cpp index bdf784230..a46e60e5c 100644 --- a/src/ast/rewriter/inj_axiom.cpp +++ b/src/ast/rewriter/inj_axiom.cpp @@ -74,6 +74,7 @@ bool simplify_inj_axiom(ast_manager & m, quantifier * q, expr_ref & result) { } } if (found_vars && !has_free_vars(q)) { + (void)num_vars; TRACE("inj_axiom", tout << "Cadidate for simplification:\n" << mk_ll_pp(q, m) << mk_pp(app1, m) << "\n" << mk_pp(app2, m) << "\n" << mk_pp(var1, m) << "\n" << mk_pp(var2, m) << "\nnum_vars: " << num_vars << "\n";); diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index 2589c51b8..5fe5c5e4e 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -1012,7 +1012,7 @@ namespace sat { } bool solver::propagate_literal(literal l, bool update) { - literal l1, l2; + literal l1; bool keep; unsigned curr_level = lvl(l); @@ -4733,7 +4733,7 @@ namespace sat { num_lits += c.size(); } } - unsigned total_cls = num_cls + num_ter + num_bin; + unsigned total_cls = num_cls + num_ter + num_bin + num_ext; double mem = static_cast(memory::get_allocation_size())/static_cast(1024*1024); out << "(sat-status\n"; out << " :inconsistent " << (m_inconsistent ? "true" : "false") << "\n"; diff --git a/src/smt/diff_logic.h b/src/smt/diff_logic.h index cd4c8bf75..4628721ab 100644 --- a/src/smt/diff_logic.h +++ b/src/smt/diff_logic.h @@ -1872,13 +1872,11 @@ public: // found path. reset_marks(); m_heap.reset(); - unsigned length = 0; do { inc_activity(m_parent[w]); edge const& ee = m_edges[m_parent[w]]; f(ee.get_explanation()); w = ee.get_source(); - ++length; } while (w != src2); return; diff --git a/src/smt/theory_arith_aux.h b/src/smt/theory_arith_aux.h index acb036d2a..e624f84b5 100644 --- a/src/smt/theory_arith_aux.h +++ b/src/smt/theory_arith_aux.h @@ -1554,6 +1554,7 @@ namespace smt { min_gain.reset(); ++round; + (void)round; TRACE("opt", tout << "round: " << round << ", max: " << max << "\n"; display_row(tout, r, true); tout << "state:\n"; display(tout);); typename vector::const_iterator it = r.begin_entries(); typename vector::const_iterator end = r.end_entries(); From 2c94a3a1b399e2536f1abdaa3d2a38d5a5a35b3e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 13:09:01 -0700 Subject: [PATCH 161/187] fix build warnings Signed-off-by: Nikolaj Bjorner --- src/smt/smt_context.cpp | 1 - src/smt/smt_lookahead.cpp | 5 +---- src/test/cnf_backbones.cpp | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index deee05f6d..722782591 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -2942,7 +2942,6 @@ namespace smt { if (!e_internalized(var)) return; - enode* n = get_enode(var); theory* th = m_theories.get_plugin(s->get_family_id()); if (!th) { IF_VERBOSE(5, verbose_stream() << "No theory is attached to variable " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n"); diff --git a/src/smt/smt_lookahead.cpp b/src/smt/smt_lookahead.cpp index 8de3f2f34..221c2d0ea 100644 --- a/src/smt/smt_lookahead.cpp +++ b/src/smt/smt_lookahead.cpp @@ -79,7 +79,7 @@ namespace smt { compare comp(ctx); std::sort(vars.begin(), vars.end(), comp); - unsigned nf = 0, nc = 0, ns = 0, n = 0; + unsigned ns = 0, n = 0; for (bool_var v : vars) { if (!ctx.bool_var2expr(v)) continue; @@ -98,7 +98,6 @@ namespace smt { if (inconsistent) { ctx.assign(~lit, b_justification::mk_axiom(), false); ctx.propagate(); - ++nf; continue; } @@ -114,7 +113,6 @@ namespace smt { if (inconsistent) { ctx.assign(lit, b_justification::mk_axiom(), false); ctx.propagate(); - ++nf; continue; } double score = score1 + score2 + 1024*score1*score2; @@ -132,7 +130,6 @@ namespace smt { best_v = v; ns = 0; } - ++nc; ++ns; if (ns > budget) { break; diff --git a/src/test/cnf_backbones.cpp b/src/test/cnf_backbones.cpp index 32a8149bd..a764ed9cf 100644 --- a/src/test/cnf_backbones.cpp +++ b/src/test/cnf_backbones.cpp @@ -86,7 +86,6 @@ static void track_clauses(sat::solver const& src, dst.mk_var(false, true); } sat::literal_vector lits; - sat::literal lit; sat::clause * const * it = src.begin_clauses(); sat::clause * const * end = src.end_clauses(); svector bin_clauses; From 551cc53a2f9d975d536ce9486cc9a1e60b0fd5f9 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 15:08:33 -0700 Subject: [PATCH 162/187] fix un-intialized variable warnings --- src/math/lp/nla_core.cpp | 2 +- src/muz/base/dl_context.cpp | 2 +- src/muz/spacer/spacer_antiunify.cpp | 2 +- src/muz/spacer/spacer_context.h | 6 +++--- src/muz/spacer/spacer_legacy_mev.cpp | 2 +- src/sat/smt/arith_axioms.cpp | 2 +- src/smt/theory_arith_int.h | 2 +- src/smt/theory_lra.cpp | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/math/lp/nla_core.cpp b/src/math/lp/nla_core.cpp index 449ecad4c..2d7e453ec 100644 --- a/src/math/lp/nla_core.cpp +++ b/src/math/lp/nla_core.cpp @@ -1678,7 +1678,7 @@ bool core::is_nl_var(lpvar j) const { unsigned core::get_var_weight(lpvar j) const { - unsigned k; + unsigned k = 0; switch (lra.get_column_type(j)) { case lp::column_type::fixed: diff --git a/src/muz/base/dl_context.cpp b/src/muz/base/dl_context.cpp index 230a452df..b1e74c1ef 100644 --- a/src/muz/base/dl_context.cpp +++ b/src/muz/base/dl_context.cpp @@ -313,7 +313,7 @@ namespace datalog { void context::register_finite_sort(sort * s, sort_kind k) { m_pinned.push_back(s); SASSERT(!m_sorts.contains(s)); - sort_domain * dom; + sort_domain * dom = nullptr; switch (k) { case SK_SYMBOL: dom = alloc(symbol_sort_domain, *this, s); diff --git a/src/muz/spacer/spacer_antiunify.cpp b/src/muz/spacer/spacer_antiunify.cpp index 11fe80f60..1c65b4e29 100644 --- a/src/muz/spacer/spacer_antiunify.cpp +++ b/src/muz/spacer/spacer_antiunify.cpp @@ -158,7 +158,7 @@ void anti_unifier::operator()(expr *e1, expr *e2, expr_ref &res, m_todo.pop_back(); } - expr *r; + expr *r = nullptr; VERIFY(m_cache.find(e1, e2, r)); res = r; diff --git a/src/muz/spacer/spacer_context.h b/src/muz/spacer/spacer_context.h index 1283a525f..269142146 100644 --- a/src/muz/spacer/spacer_context.h +++ b/src/muz/spacer/spacer_context.h @@ -404,7 +404,7 @@ class pred_transformer { } pt_rule &mk_rule(const pt_rule &v); void set_tag(expr *tag, pt_rule &v) { - pt_rule *p; + pt_rule *p = nullptr; VERIFY(find_by_rule(v.rule(), p)); p->set_tag(tag); m_tags.insert(tag, p); @@ -569,7 +569,7 @@ class pred_transformer { expr *transition() const { return m_transition; } expr *init() const { return m_init; } expr *rule2tag(datalog::rule const *r) { - pt_rule *p; + pt_rule *p = nullptr; return m_pt_rules.find_by_rule(*r, p) ? p->tag() : nullptr; } unsigned get_num_levels() const { return m_frames.size(); } @@ -600,7 +600,7 @@ class pred_transformer { bool_vector &reach_pred_used, unsigned &num_reuse_reach); expr *get_transition(datalog::rule const &r) { - pt_rule *p; + pt_rule *p = nullptr; return m_pt_rules.find_by_rule(r, p) ? p->trans() : nullptr; } ptr_vector &get_aux_vars(datalog::rule const &r) { diff --git a/src/muz/spacer/spacer_legacy_mev.cpp b/src/muz/spacer/spacer_legacy_mev.cpp index a0c95fbd9..86ee731d8 100644 --- a/src/muz/spacer/spacer_legacy_mev.cpp +++ b/src/muz/spacer/spacer_legacy_mev.cpp @@ -569,7 +569,7 @@ void model_evaluator::eval_eq(app* e, expr* arg1, expr* arg2) void model_evaluator::eval_basic(app* e) { expr* arg1, *arg2; - expr *argCond, *argThen, *argElse, *arg; + expr *argCond = nullptr, *argThen = nullptr, *argElse = nullptr, *arg = nullptr; bool has_x = false; unsigned arity = e->get_num_args(); switch (e->get_decl_kind()) { diff --git a/src/sat/smt/arith_axioms.cpp b/src/sat/smt/arith_axioms.cpp index f35f3851a..508a6d805 100644 --- a/src/sat/smt/arith_axioms.cpp +++ b/src/sat/smt/arith_axioms.cpp @@ -207,7 +207,7 @@ namespace arith { bool solver::check_bv_term(app* n) { unsigned sz; - expr* _x, * _y; + expr* _x = nullptr, * _y = nullptr; if (!ctx.is_relevant(expr2enode(n))) return true; expr_ref vx(m), vy(m),vn(m); diff --git a/src/smt/theory_arith_int.h b/src/smt/theory_arith_int.h index 75c8785a7..905f67704 100644 --- a/src/smt/theory_arith_int.h +++ b/src/smt/theory_arith_int.h @@ -360,7 +360,7 @@ namespace smt { for (unsigned i = 1; i < unsat_row.size(); ++i) { numeral c(unsat_row[i]); if (!c.is_zero()) { - theory_var var; + theory_var var = null_theory_var; if (!index2var.find(i, var)) { UNREACHABLE(); } diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index f0615293d..5a3cbbd1a 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -1572,7 +1572,7 @@ public: } final_check_status eval_power(expr* e) { - expr* x, * y; + expr* x = nullptr, * y = nullptr; rational r; VERIFY(a.is_power(e, x, y)); if (a.is_numeral(x, r) && r == 0 && a.is_numeral(y, r) && r == 0) From 86b97186b0a4b3a8f8a041f2443b540952a5c530 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 15:51:48 -0700 Subject: [PATCH 163/187] fix build warnings --- src/muz/fp/datalog_parser.cpp | 26 +++++++++----------------- src/smt/theory_str.cpp | 2 ++ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/muz/fp/datalog_parser.cpp b/src/muz/fp/datalog_parser.cpp index 4d8f60121..a15c80609 100644 --- a/src/muz/fp/datalog_parser.cpp +++ b/src/muz/fp/datalog_parser.cpp @@ -228,20 +228,20 @@ public: class dlexer { - std::istream* m_input; - char_reader* m_reader; - char m_prev_char; - char m_curr_char; - int m_line; - int m_pos; - int m_tok_pos; + std::istream* m_input = nullptr; + char_reader* m_reader = nullptr; + int m_prev_char = 0; + int m_curr_char = 0; + int m_line = 1; + int m_pos = 0; + int m_tok_pos = 0; string_buffer<> m_buffer; reserved_symbols m_reserved_symbols; public: //when parsing domains, we want '.' character to be allowed in IDs, but elsewhere //we don't (because of the "y." in rules like "P(x,y):-x=y.") - bool m_parsing_domains; + bool m_parsing_domains = false; bool eos() const { return m_curr_char == EOF; @@ -267,15 +267,7 @@ public: next(); } - dlexer(): - m_input(nullptr), - m_reader(nullptr), - m_prev_char(0), - m_curr_char(0), - m_line(1), - m_pos(0), - m_tok_pos(0), - m_parsing_domains(false) { + dlexer() { } void set_stream(std::istream* s, char_reader* r) { diff --git a/src/smt/theory_str.cpp b/src/smt/theory_str.cpp index 1e12f8bd3..61f6ec644 100644 --- a/src/smt/theory_str.cpp +++ b/src/smt/theory_str.cpp @@ -4089,6 +4089,7 @@ namespace smt { expr_ref_vector arrangement_disjunction(mgr); int pos = 1; + (void)pos; for (unsigned int i = 0; i <= strValue.length(); i++) { zstring part1Str = strValue.extract(0, i); zstring part2Str = strValue.extract(i, strValue.length() - i); @@ -4522,6 +4523,7 @@ namespace smt { expr_ref_vector arrangement_disjunction(mgr); int pos = 1; + (void)pos; if (!avoidLoopCut || !has_self_cut(m, y)) { expr_ref_vector and_item(mgr); From 19f63cd6e336e5795c3a65fd0af1254e78a3ded2 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 15:57:49 -0700 Subject: [PATCH 164/187] add sequoia to os versions #7407 Signed-off-by: Nikolaj Bjorner --- src/api/python/setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/python/setup.py b/src/api/python/setup.py index f788aaf69..38e34b92f 100644 --- a/src/api/python/setup.py +++ b/src/api/python/setup.py @@ -17,7 +17,7 @@ class LibError(Exception): build_env = dict(os.environ) build_env['PYTHON'] = sys.executable -build_env['CXXFLAGS'] = build_env.get('CXXFLAGS', '') + " -std=c++17" +build_env['CXXFLAGS'] = build_env.get('CXXFLAGS', '') + " -std=c++20" # determine where we're building and where sources are ROOT_DIR = os.path.abspath(os.path.dirname(__file__)) @@ -56,7 +56,7 @@ HEADERS_DIR = os.path.join(ROOT_DIR, 'z3', 'include') BINS_DIR = os.path.join(ROOT_DIR, 'bin') # determine platform-specific filenames -if BUILD_PLATFORM in ('darwin', 'osx'): +if BUILD_PLATFORM in ('sequoia','darwin', 'osx'): LIBRARY_FILE = "libz3.dylib" EXECUTABLE_FILE = "z3" elif BUILD_PLATFORM in ('win32', 'cygwin', 'win'): @@ -199,7 +199,7 @@ def _copy_bins(): link_name = None if BUILD_PLATFORM in ('win32', 'cygwin', 'win'): pass # TODO: When windows VMs work on M1, fill this in - elif BUILD_PLATFORM in ('darwin', 'osx'): + elif BUILD_PLATFORM in ('sequoia', 'darwin', 'osx'): split = LIBRARY_FILE.split('.') link_name = split[0] + '.' + major_minor + '.' + split[1] else: From 4cefc513eb24e6077ec77d6282a5cbfd212c886d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 16:05:53 -0700 Subject: [PATCH 165/187] add sequoia to os versions #7407 Signed-off-by: Nikolaj Bjorner --- src/api/python/setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/api/python/setup.py b/src/api/python/setup.py index 38e34b92f..b9bfd810c 100644 --- a/src/api/python/setup.py +++ b/src/api/python/setup.py @@ -263,6 +263,12 @@ class bdist_wheel(_bdist_wheel): ("win", "x86"): "win32", ("osx", "x64"): f"macosx_{os_version_tag}_x86_64", ("osx", "arm64"): f"macosx_{os_version_tag}_arm64", + ("darwin", "x86_64"): f"macosx_{os_version_tag}_x86_64", + ("darwin", "x64"): f"macosx_{os_version_tag}_x86_64", + ("darwin", "arm64"): f"macosx_{os_version_tag}_arm64", + ("sequoia", "x64"): f"macosx_{os_version_tag}_x86_64", + ("sequoia", "x86_64"): f"macosx_{os_version_tag}_x86_64", + ("sequoia", "xarm64"): f"macosx_{os_version_tag}_arm64", } # type: dict[tuple[str, str], str] self.plat_name = TAGS[(BUILD_PLATFORM, BUILD_ARCH)] return super().finalize_options() From 8c39863019f32c12ae11869a38598849c2c2b404 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 16:17:40 -0700 Subject: [PATCH 166/187] fix typo in arch for setup.py Signed-off-by: Nikolaj Bjorner --- src/api/python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/setup.py b/src/api/python/setup.py index b9bfd810c..11ba42cf8 100644 --- a/src/api/python/setup.py +++ b/src/api/python/setup.py @@ -268,7 +268,7 @@ class bdist_wheel(_bdist_wheel): ("darwin", "arm64"): f"macosx_{os_version_tag}_arm64", ("sequoia", "x64"): f"macosx_{os_version_tag}_x86_64", ("sequoia", "x86_64"): f"macosx_{os_version_tag}_x86_64", - ("sequoia", "xarm64"): f"macosx_{os_version_tag}_arm64", + ("sequoia", "arm64"): f"macosx_{os_version_tag}_arm64", } # type: dict[tuple[str, str], str] self.plat_name = TAGS[(BUILD_PLATFORM, BUILD_ARCH)] return super().finalize_options() From 328616b8b28feddca2fdb55b2865ca525d584e91 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 30 Sep 2024 17:25:19 -0700 Subject: [PATCH 167/187] fix build warnings --- src/ast/fpa/fpa2bv_converter.cpp | 2 +- src/muz/spacer/spacer_legacy_mev.cpp | 2 +- src/sat/smt/arith_axioms.cpp | 2 +- src/smt/mam.cpp | 6 +++--- src/smt/theory_str.cpp | 2 +- src/test/dlist.cpp | 1 + 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 25a0e77ad..d138cc082 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2692,7 +2692,7 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * SASSERT(tmp_rat.is_int32()); SASSERT(sz == 3); - mpf_rounding_mode mrm; + mpf_rounding_mode mrm = MPF_ROUND_TOWARD_ZERO; switch ((BV_RM_VAL)tmp_rat.get_unsigned()) { case BV_RM_TIES_TO_AWAY: mrm = MPF_ROUND_NEAREST_TAWAY; break; case BV_RM_TIES_TO_EVEN: mrm = MPF_ROUND_NEAREST_TEVEN; break; diff --git a/src/muz/spacer/spacer_legacy_mev.cpp b/src/muz/spacer/spacer_legacy_mev.cpp index 86ee731d8..57f249274 100644 --- a/src/muz/spacer/spacer_legacy_mev.cpp +++ b/src/muz/spacer/spacer_legacy_mev.cpp @@ -568,7 +568,7 @@ void model_evaluator::eval_eq(app* e, expr* arg1, expr* arg2) void model_evaluator::eval_basic(app* e) { - expr* arg1, *arg2; + expr* arg1 = nullptr, *arg2 = nullptr; expr *argCond = nullptr, *argThen = nullptr, *argElse = nullptr, *arg = nullptr; bool has_x = false; unsigned arity = e->get_num_args(); diff --git a/src/sat/smt/arith_axioms.cpp b/src/sat/smt/arith_axioms.cpp index 508a6d805..97a8ee563 100644 --- a/src/sat/smt/arith_axioms.cpp +++ b/src/sat/smt/arith_axioms.cpp @@ -206,7 +206,7 @@ namespace arith { } bool solver::check_bv_term(app* n) { - unsigned sz; + unsigned sz = 0; expr* _x = nullptr, * _y = nullptr; if (!ctx.is_relevant(expr2enode(n))) return true; diff --git a/src/smt/mam.cpp b/src/smt/mam.cpp index b9ac45039..a10c243f8 100644 --- a/src/smt/mam.cpp +++ b/src/smt/mam.cpp @@ -906,9 +906,9 @@ namespace { void linearise_core() { m_aux.reset(); app * first_app = nullptr; - unsigned first_app_reg; - unsigned first_app_sz; - unsigned first_app_num_unbound_vars; + unsigned first_app_reg = 0; + unsigned first_app_sz = 0; + unsigned first_app_num_unbound_vars = 0; // generate first the non-BIND operations for (unsigned reg : m_todo) { expr * p = m_registers[reg]; diff --git a/src/smt/theory_str.cpp b/src/smt/theory_str.cpp index 61f6ec644..f88887feb 100644 --- a/src/smt/theory_str.cpp +++ b/src/smt/theory_str.cpp @@ -1089,7 +1089,7 @@ namespace smt { void theory_str::instantiate_axiom_CharAt(enode * e) { ast_manager & m = get_manager(); - expr* arg0, *arg1; + expr* arg0 = nullptr, *arg1 = nullptr; app * expr = e->get_expr(); if (axiomatized_terms.contains(expr)) { TRACE("str", tout << "already set up CharAt axiom for " << mk_pp(expr, m) << std::endl;); diff --git a/src/test/dlist.cpp b/src/test/dlist.cpp index 32a54f9ff..9ad04d6b2 100644 --- a/src/test/dlist.cpp +++ b/src/test/dlist.cpp @@ -179,5 +179,6 @@ void tst_dlist() { test_detach(); test_invariant(); test_contains(); + (void)test_remove_from; std::cout << "All tests passed." << std::endl; } From c7af97364a55394396b69feb04c449aa3fe60f1f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 1 Oct 2024 15:15:47 -0700 Subject: [PATCH 168/187] fixes for #7402 Signed-off-by: Nikolaj Bjorner --- src/opt/opt_context.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp index c571753e9..f3b4c78b7 100644 --- a/src/opt/opt_context.cpp +++ b/src/opt/opt_context.cpp @@ -401,9 +401,24 @@ namespace opt { void context::set_model(model_ref& m) { m_model = m; opt_params optp(m_params); - if (optp.dump_models() && m) { + symbol prefix = optp.solution_prefix(); + bool model2console = optp.dump_models(); + bool model2file = prefix != symbol::null && prefix != symbol(""); + + if ((model2console || model2file) && m) { model_ref md = m->copy(); fix_model(md); + if (model2file) { + std::ostringstream buffer; + buffer << prefix << (m_model_counter++) << ".smt2"; + std::ofstream out(buffer.str()); + if (out) { + out << *md; + out.close(); + } + } + if (model2console) + std::cout << *md; } if (m_on_model_eh && m) { model_ref md = m->copy(); @@ -1168,20 +1183,6 @@ namespace opt { void context::model_updated(model* md) { model_ref mdl = md; set_model(mdl); -#if 0 - opt_params optp(m_params); - symbol prefix = optp.solution_prefix(); - if (prefix == symbol::null || prefix == symbol("")) return; - model_ref mdl = md->copy(); - fix_model(mdl); - std::ostringstream buffer; - buffer << prefix << (m_model_counter++) << ".smt2"; - std::ofstream out(buffer.str()); - if (out) { - out << *mdl; - out.close(); - } -#endif } rational context::adjust(unsigned id, rational const& v) { From 93ff89bf9807ca305b49faae77f379f0bfab36ac Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 2 Oct 2024 08:00:23 -0700 Subject: [PATCH 169/187] add == for const_ref and ref to disambiguate equality. --- src/math/lp/stacked_vector.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/math/lp/stacked_vector.h b/src/math/lp/stacked_vector.h index 69ff99263..88e79749b 100644 --- a/src/math/lp/stacked_vector.h +++ b/src/math/lp/stacked_vector.h @@ -51,13 +51,21 @@ public: operator const B&() const { return m_vec.m_vector[m_i]; } - + bool operator==(B const& other) const { return m_vec.m_vector[m_i] == other; } bool operator!=(B const& other) const { return m_vec.m_vector[m_i] != other; } + bool operator==(ref const& other) const { + return m_vec.m_vector[m_i] == other.m_vec.m_vector[other.m_i]; + } + bool operator!=(ref const& other) const { + return m_vec.m_vector[m_i] != other.m_vec.m_vectpr[other.m_i]; + } + + B& operator+=(B const &delta) { // not tracking the change here! return m_vec.m_vector[m_i] += delta; @@ -74,12 +82,16 @@ public: public: ref_const(const stacked_vector &m, unsigned key) :m_vec(m), m_i(key) { lp_assert(key < m.size()); - } - + } operator const B&() const { return m_vec.m_vector[m_i]; } - + bool operator==(ref_const const& other) const { + return m_vec.m_vector[m_i] == other.m_vec.m_vector[other.m_i]; + } + bool operator!=(ref_const const& other) const { + return m_vec.m_vector[m_i] != other.m_vec.m_vectpr[other.m_i]; + } }; private: From d686e92bfa48eac2c980b103a7c121387e83d851 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 2 Oct 2024 10:45:11 -0700 Subject: [PATCH 170/187] disambiguate Signed-off-by: Nikolaj Bjorner --- src/math/lp/lar_solver.cpp | 5 +++-- src/math/lp/stacked_vector.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/math/lp/lar_solver.cpp b/src/math/lp/lar_solver.cpp index b0f153e46..3e3d98548 100644 --- a/src/math/lp/lar_solver.cpp +++ b/src/math/lp/lar_solver.cpp @@ -1930,9 +1930,10 @@ namespace lp { default: UNREACHABLE(); } - if (m_mpq_lar_core_solver.m_r_upper_bounds[j] == m_mpq_lar_core_solver.m_r_lower_bounds[j]) { + numeric_pair const& lo = m_mpq_lar_core_solver.m_r_lower_bounds[j]; + numeric_pair const& hi = m_mpq_lar_core_solver.m_r_upper_bounds[j]; + if (lo == hi) m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; - } } void lar_solver::update_bound_with_no_ub_lb(lpvar j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep) { diff --git a/src/math/lp/stacked_vector.h b/src/math/lp/stacked_vector.h index 88e79749b..791cddc85 100644 --- a/src/math/lp/stacked_vector.h +++ b/src/math/lp/stacked_vector.h @@ -62,7 +62,7 @@ public: return m_vec.m_vector[m_i] == other.m_vec.m_vector[other.m_i]; } bool operator!=(ref const& other) const { - return m_vec.m_vector[m_i] != other.m_vec.m_vectpr[other.m_i]; + return m_vec.m_vector[m_i] != other.m_vec.m_vector[other.m_i]; } @@ -90,7 +90,7 @@ public: return m_vec.m_vector[m_i] == other.m_vec.m_vector[other.m_i]; } bool operator!=(ref_const const& other) const { - return m_vec.m_vector[m_i] != other.m_vec.m_vectpr[other.m_i]; + return m_vec.m_vector[m_i] != other.m_vec.m_vector[other.m_i]; } }; From 6dec943b297f455b178b2f0369544e99b0d79779 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 13:23:39 -0700 Subject: [PATCH 171/187] Bump docker/build-push-action from 6.7.0 to 6.9.0 (#7408) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.7.0 to 6.9.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.7.0...v6.9.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 7e8ca0b12..c3949d6c5 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -41,7 +41,7 @@ jobs: type=edge type=sha,prefix=ubuntu-20.04-bare-z3-sha- - name: Build and push Bare Z3 Docker Image - uses: docker/build-push-action@v6.7.0 + uses: docker/build-push-action@v6.9.0 with: context: . push: true From b170f101481c51e4d753212b484bc5a48191f6ed Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 2 Oct 2024 13:26:46 -0700 Subject: [PATCH 172/187] reorder template definition Signed-off-by: Nikolaj Bjorner --- src/qe/qe_mbp.cpp | 64 ++++++++++++++++++++---------------- src/sat/smt/arith_axioms.cpp | 2 +- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/qe/qe_mbp.cpp b/src/qe/qe_mbp.cpp index b5fafeeac..00926f3fb 100644 --- a/src/qe/qe_mbp.cpp +++ b/src/qe/qe_mbp.cpp @@ -45,35 +45,35 @@ using namespace qe; namespace { // rewrite select(store(a, i, k), j) into k if m \models i = j and select(a, j) if m \models i != j struct rd_over_wr_rewriter : public default_rewriter_cfg { - ast_manager &m; - array_util m_arr; - model_evaluator m_eval; - expr_ref_vector m_sc; - - rd_over_wr_rewriter(ast_manager& man, model& mdl): m(man), m_arr(m), m_eval(mdl), m_sc(m) { - m_eval.set_model_completion(false); - } - - br_status reduce_app(func_decl *f, unsigned num, expr *const *args, - expr_ref &result, proof_ref &result_pr) { - if (m_arr.is_select(f) && m_arr.is_store(args[0])) { - expr_ref ind1(m), ind2(m); - ind1 = m_eval(args[1]); - ind2 = m_eval(to_app(args[0])->get_arg(1)); - if (ind1 == ind2) { - result = to_app(args[0])->get_arg(2); - m_sc.push_back(m.mk_eq(args[1], to_app(args[0])->get_arg(1))); - return BR_DONE; - } - m_sc.push_back(m.mk_not(m.mk_eq(args[1], to_app(args[0])->get_arg(1)))); - expr_ref_vector new_args(m); - new_args.push_back(to_app(args[0])->get_arg(0)); - new_args.push_back(args[1]); - result = m_arr.mk_select(new_args); - return BR_REWRITE1; + ast_manager &m; + array_util m_arr; + model_evaluator m_eval; + expr_ref_vector m_sc; + + rd_over_wr_rewriter(ast_manager& man, model& mdl): m(man), m_arr(m), m_eval(mdl), m_sc(m) { + m_eval.set_model_completion(false); + } + + br_status reduce_app(func_decl *f, unsigned num, expr *const *args, + expr_ref &result, proof_ref &result_pr) { + if (m_arr.is_select(f) && m_arr.is_store(args[0])) { + expr_ref ind1(m), ind2(m); + ind1 = m_eval(args[1]); + ind2 = m_eval(to_app(args[0])->get_arg(1)); + if (ind1 == ind2) { + result = to_app(args[0])->get_arg(2); + m_sc.push_back(m.mk_eq(args[1], to_app(args[0])->get_arg(1))); + return BR_DONE; } - return BR_FAILED; + m_sc.push_back(m.mk_not(m.mk_eq(args[1], to_app(args[0])->get_arg(1)))); + expr_ref_vector new_args(m); + new_args.push_back(to_app(args[0])->get_arg(0)); + new_args.push_back(args[1]); + result = m_arr.mk_select(new_args); + return BR_REWRITE1; } + return BR_FAILED; + } }; // rewrite all occurrences of (as const arr c) to (as const arr v) where v = m_eval(c) struct app_const_arr_rewriter : public default_rewriter_cfg { @@ -123,6 +123,11 @@ namespace { } }; } + +template class rewriter_tpl; +template class rewriter_tpl; + + void rewrite_as_const_arr(expr* in, model& mdl, expr_ref& out) { app_const_arr_rewriter cfg(out.m(), mdl); rewriter_tpl rw(out.m(), false, cfg); @@ -675,6 +680,8 @@ public: vars.reset(); vars.append(other_vars); } + + }; mbproj::mbproj(ast_manager& m, params_ref const& p) { @@ -715,5 +722,4 @@ opt::inf_eps mbproj::maximize(expr_ref_vector const& fmls, model& mdl, app* t, e scoped_no_proof _sp(fmls.get_manager()); return m_impl->maximize(fmls, mdl, t, ge, gt); } -template class rewriter_tpl; -template class rewriter_tpl; + diff --git a/src/sat/smt/arith_axioms.cpp b/src/sat/smt/arith_axioms.cpp index 97a8ee563..59529658b 100644 --- a/src/sat/smt/arith_axioms.cpp +++ b/src/sat/smt/arith_axioms.cpp @@ -324,7 +324,7 @@ namespace arith { void solver::mk_bv_axiom(app* n) { - unsigned sz; + unsigned sz = 0; expr* _x = nullptr, * _y = nullptr; VERIFY(a.is_band(n, sz, _x, _y) || a.is_shl(n, sz, _x, _y) || a.is_ashr(n, sz, _x, _y) || a.is_lshr(n, sz, _x, _y)); rational N = rational::power_of_two(sz); From 3586b613f7e0cdd404d9c44e51d27d01be08019e Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Wed, 2 Oct 2024 22:20:12 +0100 Subject: [PATCH 173/187] remove default destructors --- src/ast/arith_decl_plugin.cpp | 3 -- src/ast/ast_trail.h | 3 +- src/ast/datatype_decl_plugin.cpp | 5 ---- src/ast/datatype_decl_plugin.h | 1 - src/ast/expr2polynomial.cpp | 3 -- src/ast/expr2polynomial.h | 1 - src/ast/fpa/fpa2bv_rewriter.h | 3 -- src/ast/fpa_decl_plugin.cpp | 6 ---- src/ast/fpa_decl_plugin.h | 2 -- src/ast/macros/cond_macro.h | 5 +--- src/ast/macros/macro_finder.cpp | 3 -- src/ast/macros/macro_finder.h | 1 - src/ast/macros/macro_manager.cpp | 3 -- src/ast/macros/macro_manager.h | 1 - src/ast/macros/quasi_macros.cpp | 3 -- src/ast/macros/quasi_macros.h | 1 - src/ast/normal_forms/defined_names.cpp | 5 +--- src/ast/pattern/expr_pattern_match.cpp | 3 -- src/ast/pattern/expr_pattern_match.h | 1 - src/ast/recfun_decl_plugin.cpp | 3 -- src/ast/recfun_decl_plugin.h | 1 - src/ast/sls/bvsls_opt_engine.cpp | 4 --- src/ast/sls/bvsls_opt_engine.h | 1 - src/cmd_context/cmd_context.cpp | 3 -- src/cmd_context/cmd_context.h | 1 - src/cmd_context/tactic_cmds.cpp | 4 --- src/cmd_context/tactic_cmds.h | 3 +- src/math/lp/core_solver_pretty_printer.cpp | 2 -- src/math/lp/core_solver_pretty_printer.h | 1 - src/math/lp/core_solver_pretty_printer_def.h | 2 -- src/math/polynomial/algebraic_numbers.cpp | 3 -- src/math/realclosure/mpz_matrix.cpp | 3 -- src/math/realclosure/mpz_matrix.h | 1 - src/math/realclosure/realclosure.cpp | 2 -- src/model/numeral_factory.cpp | 6 ---- src/model/numeral_factory.h | 2 -- src/model/value_factory.cpp | 3 -- src/model/value_factory.h | 2 +- src/muz/base/bind_variables.cpp | 3 -- src/muz/base/bind_variables.h | 1 - src/muz/fp/datalog_parser.cpp | 3 -- src/muz/rel/check_relation.cpp | 2 -- src/muz/rel/check_relation.h | 1 - src/muz/rel/dl_external_relation.cpp | 3 -- src/muz/rel/dl_external_relation.h | 1 - src/muz/rel/dl_mk_explanations.cpp | 3 -- src/muz/rel/dl_mk_explanations.h | 2 -- src/muz/transforms/dl_mk_array_blast.cpp | 3 -- src/muz/transforms/dl_mk_array_blast.h | 2 -- .../dl_mk_quantifier_abstraction.cpp | 3 -- .../transforms/dl_mk_quantifier_abstraction.h | 2 -- .../dl_mk_quantifier_instantiation.cpp | 3 -- .../dl_mk_quantifier_instantiation.h | 2 -- src/muz/transforms/dl_mk_scale.cpp | 3 -- src/muz/transforms/dl_mk_scale.h | 1 - src/nlsat/nlsat_explain.cpp | 3 -- src/nlsat/nlsat_interval_set.cpp | 3 -- src/nlsat/nlsat_interval_set.h | 1 - src/opt/opt_solver.cpp | 3 -- src/opt/opt_solver.h | 1 - src/opt/pb_sls.cpp | 3 -- src/parsers/util/simple_parser.cpp | 3 -- src/parsers/util/simple_parser.h | 2 +- src/sat/sat_local_search.cpp | 7 ----- src/sat/sat_local_search.h | 4 --- src/sat/sat_model_converter.cpp | 7 ----- src/sat/sat_model_converter.h | 6 ++-- src/sat/smt/euf_proof_checker.cpp | 3 -- src/sat/smt/euf_proof_checker.h | 1 - src/sat/smt/q_mam.cpp | 3 -- src/sat/smt/specrel_solver.cpp | 3 -- src/sat/smt/specrel_solver.h | 1 - src/smt/mam.cpp | 3 -- src/smt/qi_queue.cpp | 3 -- src/smt/qi_queue.h | 1 - src/smt/smt_conflict_resolution.cpp | 3 -- src/smt/smt_conflict_resolution.h | 2 +- src/smt/smt_theory.cpp | 3 -- src/smt/smt_theory.h | 2 +- src/smt/theory_arith.h | 1 - src/smt/theory_arith_core.h | 4 --- src/smt/theory_bv.cpp | 3 -- src/smt/theory_bv.h | 1 - src/smt/theory_datatype.cpp | 3 +- src/solver/assertions/asserted_formulas.cpp | 4 --- src/solver/assertions/asserted_formulas.h | 1 - src/solver/check_sat_result.cpp | 3 -- src/solver/check_sat_result.h | 1 - src/tactic/core/injectivity_tactic.cpp | 3 -- src/tactic/core/simplify_tactic.cpp | 3 -- src/util/hwf.cpp | 4 --- src/util/hwf.h | 1 - src/util/map.h | 29 +++++-------------- src/util/obj_hashtable.h | 2 +- src/util/ref.h | 12 ++++---- 95 files changed, 25 insertions(+), 259 deletions(-) diff --git a/src/ast/arith_decl_plugin.cpp b/src/ast/arith_decl_plugin.cpp index 67a605869..8e2cbef82 100644 --- a/src/ast/arith_decl_plugin.cpp +++ b/src/ast/arith_decl_plugin.cpp @@ -34,9 +34,6 @@ struct arith_decl_plugin::algebraic_numbers_wrapper { m_nums(m_amanager) { } - ~algebraic_numbers_wrapper() { - } - unsigned mk_id(algebraic_numbers::anum const & val) { SASSERT(!m_amanager.is_rational(val)); unsigned idx = m_id_gen.mk(); diff --git a/src/ast/ast_trail.h b/src/ast/ast_trail.h index 5a76dd537..18c8961e6 100644 --- a/src/ast/ast_trail.h +++ b/src/ast/ast_trail.h @@ -33,8 +33,7 @@ class ast2ast_trailmap { public: ast2ast_trailmap(ast_manager& m): m_domain(m), - m_range(m), - m_map() + m_range(m) {} bool find(S* s, T*& t) { diff --git a/src/ast/datatype_decl_plugin.cpp b/src/ast/datatype_decl_plugin.cpp index cc5c6eb75..e5ab4a806 100644 --- a/src/ast/datatype_decl_plugin.cpp +++ b/src/ast/datatype_decl_plugin.cpp @@ -1040,11 +1040,6 @@ namespace datatype { return m_family_id; } - - util::~util() { - - } - ptr_vector const * util::get_datatype_constructors(sort * ty) { SASSERT(is_datatype(ty)); ptr_vector * r = nullptr; diff --git a/src/ast/datatype_decl_plugin.h b/src/ast/datatype_decl_plugin.h index ca33b48c1..dcca78970 100644 --- a/src/ast/datatype_decl_plugin.h +++ b/src/ast/datatype_decl_plugin.h @@ -338,7 +338,6 @@ namespace datatype { public: util(ast_manager & m); - ~util(); ast_manager & get_manager() const { return m; } // sort * mk_datatype_sort(symbol const& name, unsigned n, sort* const* params); bool is_datatype(sort const* s) const { return is_sort_of(s, fid(), DATATYPE_SORT); } diff --git a/src/ast/expr2polynomial.cpp b/src/ast/expr2polynomial.cpp index a69d5b436..3bcd7367a 100644 --- a/src/ast/expr2polynomial.cpp +++ b/src/ast/expr2polynomial.cpp @@ -504,9 +504,6 @@ default_expr2polynomial::default_expr2polynomial(ast_manager & am, polynomial::m expr2polynomial(am, pm, nullptr) { } -default_expr2polynomial::~default_expr2polynomial() { -} - bool default_expr2polynomial::is_int(polynomial::var x) const { return m_is_int[x]; } diff --git a/src/ast/expr2polynomial.h b/src/ast/expr2polynomial.h index 1d89587c4..b3356e9e0 100644 --- a/src/ast/expr2polynomial.h +++ b/src/ast/expr2polynomial.h @@ -102,7 +102,6 @@ class default_expr2polynomial : public expr2polynomial { bool_vector m_is_int; public: default_expr2polynomial(ast_manager & am, polynomial::manager & pm); - ~default_expr2polynomial() override; bool is_int(polynomial::var x) const override; protected: polynomial::var mk_var(bool is_int) override; diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index 42467c219..f68de5e32 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -36,9 +36,6 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p); - ~fpa2bv_rewriter_cfg() { - } - void cleanup_buffers() { m_out.finalize(); } diff --git a/src/ast/fpa_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp index 76e44278d..3bdc19d5e 100644 --- a/src/ast/fpa_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -47,9 +47,6 @@ void fpa_decl_plugin::set_manager(ast_manager * m, family_id id) { m_bv_plugin = static_cast(m_manager->get_plugin(m_bv_fid)); } -fpa_decl_plugin::~fpa_decl_plugin() { -} - unsigned fpa_decl_plugin::mk_id(mpf const & v) { unsigned new_id = m_id_gen.mk(); m_values.reserve(new_id+1); @@ -961,9 +958,6 @@ fpa_util::fpa_util(ast_manager & m): m_plugin = static_cast(m.get_plugin(m_fid)); } -fpa_util::~fpa_util() { -} - sort * fpa_util::mk_float_sort(unsigned ebits, unsigned sbits) { parameter ps[2] = { parameter(ebits), parameter(sbits) }; return m().mk_sort(m_fid, FLOATING_POINT_SORT, 2, ps); diff --git a/src/ast/fpa_decl_plugin.h b/src/ast/fpa_decl_plugin.h index 0357efa47..39b3fc33c 100644 --- a/src/ast/fpa_decl_plugin.h +++ b/src/ast/fpa_decl_plugin.h @@ -175,7 +175,6 @@ public: bool is_float_sort(sort * s) const { return is_sort_of(s, m_family_id, FLOATING_POINT_SORT); } bool is_rm_sort(sort * s) const { return is_sort_of(s, m_family_id, ROUNDING_MODE_SORT); } - ~fpa_decl_plugin() override; void finalize() override; decl_plugin * mk_fresh() override; @@ -216,7 +215,6 @@ class fpa_util { public: fpa_util(ast_manager & m); - ~fpa_util(); ast_manager & m() const { return m_manager; } mpf_manager & fm() const { return m_plugin->fm(); } diff --git a/src/ast/macros/cond_macro.h b/src/ast/macros/cond_macro.h index 7e8064ac6..0dc3c1e0b 100644 --- a/src/ast/macros/cond_macro.h +++ b/src/ast/macros/cond_macro.h @@ -39,10 +39,7 @@ public: m_weight(weight) { SASSERT(!m_hint || !m_cond); } - - ~cond_macro() { - } - + func_decl * get_f() const { return m_f; } expr * get_def() const { return m_def; } diff --git a/src/ast/macros/macro_finder.cpp b/src/ast/macros/macro_finder.cpp index bc63aae8e..3006e383c 100644 --- a/src/ast/macros/macro_finder.cpp +++ b/src/ast/macros/macro_finder.cpp @@ -269,9 +269,6 @@ macro_finder::macro_finder(ast_manager & m, macro_manager & mm): m_autil(m) { } -macro_finder::~macro_finder() { -} - bool macro_finder::expand_macros(expr_ref_vector const& exprs, proof_ref_vector const& prs, expr_dependency_ref_vector const& deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) { TRACE("macro_finder", tout << "starting expand_macros:\n"; m_macro_manager.display(tout);); diff --git a/src/ast/macros/macro_finder.h b/src/ast/macros/macro_finder.h index 91e5deeb9..fe2722172 100644 --- a/src/ast/macros/macro_finder.h +++ b/src/ast/macros/macro_finder.h @@ -43,7 +43,6 @@ class macro_finder { public: macro_finder(ast_manager & m, macro_manager & mm); - ~macro_finder(); void operator()(expr_ref_vector const& exprs, proof_ref_vector const& prs, expr_dependency_ref_vector const& deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps); void operator()(unsigned n, justified_expr const* fmls, vector& new_fmls); }; diff --git a/src/ast/macros/macro_manager.cpp b/src/ast/macros/macro_manager.cpp index b7c94b1b5..824573d46 100644 --- a/src/ast/macros/macro_manager.cpp +++ b/src/ast/macros/macro_manager.cpp @@ -41,9 +41,6 @@ macro_manager::macro_manager(ast_manager & m): m_util.set_forbidden_set(&m_forbidden_set); } -macro_manager::~macro_manager() { -} - void macro_manager::push_scope() { m_scopes.push_back(scope()); scope & s = m_scopes.back(); diff --git a/src/ast/macros/macro_manager.h b/src/ast/macros/macro_manager.h index 758e3c1a7..9d8831c30 100644 --- a/src/ast/macros/macro_manager.h +++ b/src/ast/macros/macro_manager.h @@ -64,7 +64,6 @@ class macro_manager { public: macro_manager(ast_manager & m); - ~macro_manager(); void copy_to(macro_manager& dst); ast_manager & get_manager() const { return m; } macro_util & get_util() { return m_util; } diff --git a/src/ast/macros/quasi_macros.cpp b/src/ast/macros/quasi_macros.cpp index dff36278d..b65daf063 100644 --- a/src/ast/macros/quasi_macros.cpp +++ b/src/ast/macros/quasi_macros.cpp @@ -31,9 +31,6 @@ quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm) : m_new_qsorts(m) { } -quasi_macros::~quasi_macros() { -} - void quasi_macros::find_occurrences(expr * e) { unsigned j; m_todo.reset(); diff --git a/src/ast/macros/quasi_macros.h b/src/ast/macros/quasi_macros.h index 4441f432e..2b5350cf0 100644 --- a/src/ast/macros/quasi_macros.h +++ b/src/ast/macros/quasi_macros.h @@ -60,7 +60,6 @@ class quasi_macros { public: quasi_macros(ast_manager & m, macro_manager & mm); - ~quasi_macros(); /** \brief Find pure function macros and apply them. diff --git a/src/ast/normal_forms/defined_names.cpp b/src/ast/normal_forms/defined_names.cpp index c931c6fad..4e9ee6263 100644 --- a/src/ast/normal_forms/defined_names.cpp +++ b/src/ast/normal_forms/defined_names.cpp @@ -57,7 +57,7 @@ struct defined_names::impl { unsigned_vector m_lims; //!< Backtracking support. impl(ast_manager & m, char const * prefix); - virtual ~impl(); + virtual ~impl() = default; app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer & var_names); void cache_new_name(expr * e, app * name); @@ -90,9 +90,6 @@ defined_names::impl::impl(ast_manager & m, char const * prefix): m_z3name = prefix; } -defined_names::impl::~impl() { -} - /** \brief Given an expression \c e that may contain free variables, return an application (sk x_1 ... x_n), where sk is a fresh variable name, and x_i's are the free variables of \c e. diff --git a/src/ast/pattern/expr_pattern_match.cpp b/src/ast/pattern/expr_pattern_match.cpp index 8ae0dcbf2..2fbd99bdf 100644 --- a/src/ast/pattern/expr_pattern_match.cpp +++ b/src/ast/pattern/expr_pattern_match.cpp @@ -41,9 +41,6 @@ expr_pattern_match::expr_pattern_match(ast_manager & manager): m_manager(manager), m_precompiled(manager) { } -expr_pattern_match::~expr_pattern_match() { -} - bool expr_pattern_match::match_quantifier(quantifier* qf, app_ref_vector& patterns, unsigned& weight) { if (m_regs.empty()) { diff --git a/src/ast/pattern/expr_pattern_match.h b/src/ast/pattern/expr_pattern_match.h index 2fd0b4b73..11939e1de 100644 --- a/src/ast/pattern/expr_pattern_match.h +++ b/src/ast/pattern/expr_pattern_match.h @@ -116,7 +116,6 @@ class expr_pattern_match { public: expr_pattern_match(ast_manager & manager); - ~expr_pattern_match(); bool match_quantifier(quantifier * qf, app_ref_vector & patterns, unsigned & weight); bool match_quantifier_index(quantifier* qf, app_ref_vector & patterns, unsigned& index); unsigned initialize(quantifier* qf); diff --git a/src/ast/recfun_decl_plugin.cpp b/src/ast/recfun_decl_plugin.cpp index 5f2534a51..cba1932be 100644 --- a/src/ast/recfun_decl_plugin.cpp +++ b/src/ast/recfun_decl_plugin.cpp @@ -366,9 +366,6 @@ namespace recfun { m_plugin(dynamic_cast(m.get_plugin(m_fid))) { } - util::~util() { - } - def * util::decl_fun(symbol const& name, unsigned n, sort *const * domain, sort * range, bool is_generated) { return alloc(def, m(), m_fid, name, n, domain, range, is_generated); } diff --git a/src/ast/recfun_decl_plugin.h b/src/ast/recfun_decl_plugin.h index 73e2b5244..d9fe07dcf 100644 --- a/src/ast/recfun_decl_plugin.h +++ b/src/ast/recfun_decl_plugin.h @@ -237,7 +237,6 @@ namespace recfun { public: util(ast_manager &m); - ~util(); ast_manager & m() { return m_manager; } family_id get_family_id() const { return m_fid; } diff --git a/src/ast/sls/bvsls_opt_engine.cpp b/src/ast/sls/bvsls_opt_engine.cpp index 7dc71cd8c..2f006dc9f 100644 --- a/src/ast/sls/bvsls_opt_engine.cpp +++ b/src/ast/sls/bvsls_opt_engine.cpp @@ -28,10 +28,6 @@ bvsls_opt_engine::bvsls_opt_engine(ast_manager & m, params_ref const & p) : m_best_model = alloc(model, m); } -bvsls_opt_engine::~bvsls_opt_engine() -{ -} - bvsls_opt_engine::optimization_result bvsls_opt_engine::optimize( expr_ref const & objective, model_ref initial_model, diff --git a/src/ast/sls/bvsls_opt_engine.h b/src/ast/sls/bvsls_opt_engine.h index 435fa3af4..25182c156 100644 --- a/src/ast/sls/bvsls_opt_engine.h +++ b/src/ast/sls/bvsls_opt_engine.h @@ -31,7 +31,6 @@ class bvsls_opt_engine : public sls_engine { public: bvsls_opt_engine(ast_manager & m, params_ref const & p); - ~bvsls_opt_engine(); class optimization_result { public: diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index e9ca5595f..5f5195bb9 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -2464,9 +2464,6 @@ cmd_context::dt_eh::dt_eh(cmd_context & owner): m_dt_util(owner.m()) { } -cmd_context::dt_eh::~dt_eh() { -} - void cmd_context::dt_eh::operator()(sort * dt, pdecl* pd) { TRACE("new_dt_eh", tout << "new datatype: "; m_owner.pm().display(tout, dt); tout << "\n";); for (func_decl * c : *m_dt_util.get_datatype_constructors(dt)) { diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 6dc60c9dd..cd43203a7 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -305,7 +305,6 @@ protected: public: void reset() { m_dt_util.reset(); } dt_eh(cmd_context & owner); - ~dt_eh() override; void operator()(sort * dt, pdecl* pd) override; }; diff --git a/src/cmd_context/tactic_cmds.cpp b/src/cmd_context/tactic_cmds.cpp index a0805110b..b2b858b07 100644 --- a/src/cmd_context/tactic_cmds.cpp +++ b/src/cmd_context/tactic_cmds.cpp @@ -27,7 +27,6 @@ Notes: #include "ast/ast_smt2_pp.h" #include "tactic/tactic.h" #include "tactic/tactical.h" -#include "tactic/probe.h" #include "solver/check_sat_result.h" #include "cmd_context/cmd_context_to_goal.h" #include "cmd_context/echo_tactic.h" @@ -38,9 +37,6 @@ probe_info::probe_info(symbol const & n, char const * d, probe * p): m_probe(p) { } -probe_info::~probe_info() { -} - class declare_tactic_cmd : public cmd { symbol m_name; sexpr * m_decl; diff --git a/src/cmd_context/tactic_cmds.h b/src/cmd_context/tactic_cmds.h index 5096ae962..de5fda0a8 100644 --- a/src/cmd_context/tactic_cmds.h +++ b/src/cmd_context/tactic_cmds.h @@ -18,12 +18,12 @@ Notes: #pragma once #include "ast/ast.h" +#include "tactic/probe.h" #include "util/params.h" #include "util/cmd_context_types.h" #include "util/ref.h" class tactic; -class probe; typedef tactic* (*tactic_factory)(ast_manager&, const params_ref&); @@ -52,7 +52,6 @@ class probe_info { ref m_probe; public: probe_info(symbol const & n, char const * d, probe * p); - ~probe_info(); symbol get_name() const { return m_name; } char const * get_descr() const { return m_descr; } diff --git a/src/math/lp/core_solver_pretty_printer.cpp b/src/math/lp/core_solver_pretty_printer.cpp index 18bef8303..65a9aef97 100644 --- a/src/math/lp/core_solver_pretty_printer.cpp +++ b/src/math/lp/core_solver_pretty_printer.cpp @@ -21,7 +21,5 @@ Revision History: #include "math/lp/core_solver_pretty_printer_def.h" template lp::core_solver_pretty_printer::core_solver_pretty_printer(const lp::lp_core_solver_base &, std::ostream & out); template void lp::core_solver_pretty_printer::print(); -template lp::core_solver_pretty_printer::~core_solver_pretty_printer(); template lp::core_solver_pretty_printer >::core_solver_pretty_printer(const lp::lp_core_solver_base > &, std::ostream & out); -template lp::core_solver_pretty_printer >::~core_solver_pretty_printer(); template void lp::core_solver_pretty_printer >::print(); diff --git a/src/math/lp/core_solver_pretty_printer.h b/src/math/lp/core_solver_pretty_printer.h index 5bf29d511..c9ab99760 100644 --- a/src/math/lp/core_solver_pretty_printer.h +++ b/src/math/lp/core_solver_pretty_printer.h @@ -66,7 +66,6 @@ public: void init_costs(); - ~core_solver_pretty_printer(); void init_rs_width(); T current_column_norm(); diff --git a/src/math/lp/core_solver_pretty_printer_def.h b/src/math/lp/core_solver_pretty_printer_def.h index cbe67ea36..6d35273af 100644 --- a/src/math/lp/core_solver_pretty_printer_def.h +++ b/src/math/lp/core_solver_pretty_printer_def.h @@ -67,8 +67,6 @@ template void core_solver_pretty_printer::init_co } -template core_solver_pretty_printer::~core_solver_pretty_printer() { -} template void core_solver_pretty_printer::init_rs_width() { m_rs_width = static_cast(T_to_string(m_core_solver.get_cost()).size()); for (unsigned i = 0; i < nrows(); i++) { diff --git a/src/math/polynomial/algebraic_numbers.cpp b/src/math/polynomial/algebraic_numbers.cpp index b546df706..6cdd735a1 100644 --- a/src/math/polynomial/algebraic_numbers.cpp +++ b/src/math/polynomial/algebraic_numbers.cpp @@ -121,9 +121,6 @@ namespace algebraic_numbers { m_y = pm().mk_var(); } - ~imp() { - } - bool acell_inv(algebraic_cell const& c) { auto s = upm().eval_sign_at(c.m_p_sz, c.m_p, lower(&c)); return s == sign_zero || c.m_sign_lower == (s == sign_neg); diff --git a/src/math/realclosure/mpz_matrix.cpp b/src/math/realclosure/mpz_matrix.cpp index 3bbd387c6..701b3b26d 100644 --- a/src/math/realclosure/mpz_matrix.cpp +++ b/src/math/realclosure/mpz_matrix.cpp @@ -36,9 +36,6 @@ mpz_matrix_manager::mpz_matrix_manager(unsynch_mpz_manager & nm, small_object_al m_allocator(a) { } -mpz_matrix_manager::~mpz_matrix_manager() { -} - void mpz_matrix_manager::mk(unsigned m, unsigned n, mpz_matrix & A) { SASSERT(m > 0 && n > 0); del(A); diff --git a/src/math/realclosure/mpz_matrix.h b/src/math/realclosure/mpz_matrix.h index 91fe22681..9eb051ed2 100644 --- a/src/math/realclosure/mpz_matrix.h +++ b/src/math/realclosure/mpz_matrix.h @@ -63,7 +63,6 @@ class mpz_matrix_manager { bool solve_core(mpz_matrix const & A, mpz * b, bool int_solver); public: mpz_matrix_manager(unsynch_mpz_manager & nm, small_object_allocator & a); - ~mpz_matrix_manager(); unsynch_mpz_manager & nm() const { return m_nm; } void mk(unsigned m, unsigned n, mpz_matrix & A); void del(mpz_matrix & r); diff --git a/src/math/realclosure/realclosure.cpp b/src/math/realclosure/realclosure.cpp index ecea560a5..561d6a6d7 100644 --- a/src/math/realclosure/realclosure.cpp +++ b/src/math/realclosure/realclosure.cpp @@ -410,8 +410,6 @@ namespace realclosure { sbuffer m_szs; // size of each polynomial in the sequence public: scoped_polynomial_seq(imp & m):m_seq_coeffs(m) {} - ~scoped_polynomial_seq() { - } /** \brief Add a new polynomial to the sequence. diff --git a/src/model/numeral_factory.cpp b/src/model/numeral_factory.cpp index ba19ec941..6f7aeeb2c 100644 --- a/src/model/numeral_factory.cpp +++ b/src/model/numeral_factory.cpp @@ -28,9 +28,6 @@ arith_factory::arith_factory(ast_manager & m): 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()); } @@ -40,9 +37,6 @@ bv_factory::bv_factory(ast_manager & m): 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); } diff --git a/src/model/numeral_factory.h b/src/model/numeral_factory.h index 174ea8757..ca917d927 100644 --- a/src/model/numeral_factory.h +++ b/src/model/numeral_factory.h @@ -34,7 +34,6 @@ class arith_factory : public numeral_factory { public: arith_factory(ast_manager & m); - ~arith_factory() override; app * mk_num_value(rational const & val, bool is_int); }; @@ -46,7 +45,6 @@ class bv_factory : public numeral_factory { public: bv_factory(ast_manager & m); - ~bv_factory() override; app * mk_num_value(rational const & val, unsigned bv_size); }; diff --git a/src/model/value_factory.cpp b/src/model/value_factory.cpp index 30fa82caf..c79919199 100644 --- a/src/model/value_factory.cpp +++ b/src/model/value_factory.cpp @@ -25,9 +25,6 @@ value_factory::value_factory(ast_manager & m, family_id fid): m_fid(fid) { } -value_factory::~value_factory() { -} - basic_factory::basic_factory(ast_manager & m, unsigned seed): value_factory(m, m.get_basic_family_id()), m_rand(seed) { } diff --git a/src/model/value_factory.h b/src/model/value_factory.h index 20c383efe..85515495b 100644 --- a/src/model/value_factory.h +++ b/src/model/value_factory.h @@ -31,7 +31,7 @@ protected: public: value_factory(ast_manager & m, family_id fid); - virtual ~value_factory(); + virtual ~value_factory() = default; /** \brief Return some value of the given sort. The result is always different from zero. diff --git a/src/muz/base/bind_variables.cpp b/src/muz/base/bind_variables.cpp index 5ac41e0bf..d96a49f67 100644 --- a/src/muz/base/bind_variables.cpp +++ b/src/muz/base/bind_variables.cpp @@ -25,9 +25,6 @@ bind_variables::bind_variables(ast_manager & m): m_vars(m), m_pinned(m) {} - -bind_variables::~bind_variables() { -} expr_ref bind_variables::operator()(expr* fml, bool is_forall) { if (m_vars.empty()) { diff --git a/src/muz/base/bind_variables.h b/src/muz/base/bind_variables.h index e231b7039..4c183b507 100644 --- a/src/muz/base/bind_variables.h +++ b/src/muz/base/bind_variables.h @@ -40,7 +40,6 @@ class bind_variables { expr_ref abstract(expr* fml, cache_t& cache, unsigned scope); public: bind_variables(ast_manager & m); - ~bind_variables(); expr_ref operator()(expr* fml, bool is_forall); diff --git a/src/muz/fp/datalog_parser.cpp b/src/muz/fp/datalog_parser.cpp index a15c80609..c6df500d8 100644 --- a/src/muz/fp/datalog_parser.cpp +++ b/src/muz/fp/datalog_parser.cpp @@ -267,9 +267,6 @@ public: next(); } - dlexer() { - } - void set_stream(std::istream* s, char_reader* r) { m_input = s; m_reader = r; diff --git a/src/muz/rel/check_relation.cpp b/src/muz/rel/check_relation.cpp index 24b109f35..454f6d8bc 100644 --- a/src/muz/rel/check_relation.cpp +++ b/src/muz/rel/check_relation.cpp @@ -150,8 +150,6 @@ namespace datalog { m(rm.get_context().get_manager()), m_base(nullptr) { } - check_relation_plugin::~check_relation_plugin() { - } check_relation& check_relation_plugin::get(relation_base& r) { return dynamic_cast(r); } diff --git a/src/muz/rel/check_relation.h b/src/muz/rel/check_relation.h index b0b4a8acc..773b45813 100644 --- a/src/muz/rel/check_relation.h +++ b/src/muz/rel/check_relation.h @@ -89,7 +89,6 @@ namespace datalog { unsigned_vector const& cols1, unsigned_vector const& cols2); public: check_relation_plugin(relation_manager& rm); - ~check_relation_plugin() override; void set_plugin(relation_plugin* p) { m_base = p; } bool can_handle_signature(const relation_signature & s) override; diff --git a/src/muz/rel/dl_external_relation.cpp b/src/muz/rel/dl_external_relation.cpp index a47b0719f..a2e42f640 100644 --- a/src/muz/rel/dl_external_relation.cpp +++ b/src/muz/rel/dl_external_relation.cpp @@ -34,9 +34,6 @@ namespace datalog { { } - external_relation::~external_relation() { - } - void external_relation::mk_accessor(decl_kind k, func_decl_ref& fn, const relation_fact& f, bool destructive, expr_ref& res) const { ast_manager& m = m_rel.get_manager(); family_id fid = get_plugin().get_family_id(); diff --git a/src/muz/rel/dl_external_relation.h b/src/muz/rel/dl_external_relation.h index 17e9a2364..c8887eeed 100644 --- a/src/muz/rel/dl_external_relation.h +++ b/src/muz/rel/dl_external_relation.h @@ -122,7 +122,6 @@ namespace datalog { void mk_accessor(decl_kind k, func_decl_ref& fn, const relation_fact& f, bool destructive, expr_ref& res) const; external_relation(external_relation_plugin & p, const relation_signature & s, expr* r); - ~external_relation() override; public: external_relation_plugin & get_plugin() const; diff --git a/src/muz/rel/dl_mk_explanations.cpp b/src/muz/rel/dl_mk_explanations.cpp index a4b704597..2d22e34a9 100644 --- a/src/muz/rel/dl_mk_explanations.cpp +++ b/src/muz/rel/dl_mk_explanations.cpp @@ -631,9 +631,6 @@ namespace datalog { ); } - mk_explanations::~mk_explanations() { - } - func_decl * mk_explanations::get_union_decl(context & ctx) { ast_manager & m = ctx.get_manager(); sort_ref s(ctx.get_decl_util().mk_rule_sort(), m); diff --git a/src/muz/rel/dl_mk_explanations.h b/src/muz/rel/dl_mk_explanations.h index 5491918de..33d5cc8ee 100644 --- a/src/muz/rel/dl_mk_explanations.h +++ b/src/muz/rel/dl_mk_explanations.h @@ -65,8 +65,6 @@ namespace datalog { */ mk_explanations(context & ctx); - ~mk_explanations() override; - /** \brief Return explanation predicate that corresponds to \c orig_decl. */ diff --git a/src/muz/transforms/dl_mk_array_blast.cpp b/src/muz/transforms/dl_mk_array_blast.cpp index 30b57f2a4..824b298b4 100644 --- a/src/muz/transforms/dl_mk_array_blast.cpp +++ b/src/muz/transforms/dl_mk_array_blast.cpp @@ -38,9 +38,6 @@ namespace datalog { m_rewriter.updt_params(m_params); } - mk_array_blast::~mk_array_blast() { - } - bool mk_array_blast::is_store_def(expr* e, expr*& x, expr*& y) { if (m.is_eq(e, x, y)) { if (!a.is_store(y)) { diff --git a/src/muz/transforms/dl_mk_array_blast.h b/src/muz/transforms/dl_mk_array_blast.h index 352c8a248..12102af73 100644 --- a/src/muz/transforms/dl_mk_array_blast.h +++ b/src/muz/transforms/dl_mk_array_blast.h @@ -64,8 +64,6 @@ namespace datalog { \brief Create rule transformer that removes array stores and selects by ackermannization. */ mk_array_blast(context & ctx, unsigned priority); - - ~mk_array_blast() override; rule_set * operator()(rule_set const & source) override; diff --git a/src/muz/transforms/dl_mk_quantifier_abstraction.cpp b/src/muz/transforms/dl_mk_quantifier_abstraction.cpp index b8a68a443..6b321bc75 100644 --- a/src/muz/transforms/dl_mk_quantifier_abstraction.cpp +++ b/src/muz/transforms/dl_mk_quantifier_abstraction.cpp @@ -149,9 +149,6 @@ namespace datalog { m_mc(nullptr) { } - mk_quantifier_abstraction::~mk_quantifier_abstraction() { - } - func_decl* mk_quantifier_abstraction::declare_pred(rule_set const& rules, rule_set& dst, func_decl* old_p) { if (rules.is_output_predicate(old_p)) { diff --git a/src/muz/transforms/dl_mk_quantifier_abstraction.h b/src/muz/transforms/dl_mk_quantifier_abstraction.h index 6cf546a50..33c70c08b 100644 --- a/src/muz/transforms/dl_mk_quantifier_abstraction.h +++ b/src/muz/transforms/dl_mk_quantifier_abstraction.h @@ -49,8 +49,6 @@ namespace datalog { public: mk_quantifier_abstraction(context & ctx, unsigned priority); - - ~mk_quantifier_abstraction() override; rule_set * operator()(rule_set const & source) override; }; diff --git a/src/muz/transforms/dl_mk_quantifier_instantiation.cpp b/src/muz/transforms/dl_mk_quantifier_instantiation.cpp index 61c395b4e..d1fb6400c 100644 --- a/src/muz/transforms/dl_mk_quantifier_instantiation.cpp +++ b/src/muz/transforms/dl_mk_quantifier_instantiation.cpp @@ -41,9 +41,6 @@ namespace datalog { m_cnst2var(m) { } - mk_quantifier_instantiation::~mk_quantifier_instantiation() { - } - void mk_quantifier_instantiation::extract_quantifiers(rule& r, expr_ref_vector& conjs, quantifier_ref_vector& qs) { conjs.reset(); qs.reset(); diff --git a/src/muz/transforms/dl_mk_quantifier_instantiation.h b/src/muz/transforms/dl_mk_quantifier_instantiation.h index 5c0c28cd4..716de11f0 100644 --- a/src/muz/transforms/dl_mk_quantifier_instantiation.h +++ b/src/muz/transforms/dl_mk_quantifier_instantiation.h @@ -60,8 +60,6 @@ namespace datalog { public: mk_quantifier_instantiation(context & ctx, unsigned priority); - ~mk_quantifier_instantiation() override; - rule_set * operator()(rule_set const & source) override; }; diff --git a/src/muz/transforms/dl_mk_scale.cpp b/src/muz/transforms/dl_mk_scale.cpp index 38305a04e..54cf22ea8 100644 --- a/src/muz/transforms/dl_mk_scale.cpp +++ b/src/muz/transforms/dl_mk_scale.cpp @@ -110,9 +110,6 @@ namespace datalog { m_eqs(m) { } - mk_scale::~mk_scale() { - } - rule_set * mk_scale::operator()(rule_set const & source) { if (!m_ctx.scale()) { return nullptr; diff --git a/src/muz/transforms/dl_mk_scale.h b/src/muz/transforms/dl_mk_scale.h index a8e42f17e..fcbf4c226 100644 --- a/src/muz/transforms/dl_mk_scale.h +++ b/src/muz/transforms/dl_mk_scale.h @@ -42,7 +42,6 @@ namespace datalog { app_ref mk_constraint(unsigned num_vars, app* q); public: mk_scale(context & ctx, unsigned priority = 33039); - ~mk_scale() override; rule_set * operator()(rule_set const & source) override; }; diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp index a188206b4..cda44bdd4 100644 --- a/src/nlsat/nlsat_explain.cpp +++ b/src/nlsat/nlsat_explain.cpp @@ -156,9 +156,6 @@ namespace nlsat { m_minimize_cores = false; m_signed_project = false; } - - ~imp() { - } std::ostream& display(std::ostream & out, polynomial_ref const & p) const { m_pm.display(out, p, m_solver.display_proc()); diff --git a/src/nlsat/nlsat_interval_set.cpp b/src/nlsat/nlsat_interval_set.cpp index 76a310f00..872266f5f 100644 --- a/src/nlsat/nlsat_interval_set.cpp +++ b/src/nlsat/nlsat_interval_set.cpp @@ -112,9 +112,6 @@ namespace nlsat { m_am(m), m_allocator(a) { } - - interval_set_manager::~interval_set_manager() { - } void interval_set_manager::del(interval_set * s) { if (s == nullptr) diff --git a/src/nlsat/nlsat_interval_set.h b/src/nlsat/nlsat_interval_set.h index 2e74f33c6..297318912 100644 --- a/src/nlsat/nlsat_interval_set.h +++ b/src/nlsat/nlsat_interval_set.h @@ -33,7 +33,6 @@ namespace nlsat { void del(interval_set * s); public: interval_set_manager(anum_manager & m, small_object_allocator & a); - ~interval_set_manager(); void set_seed(unsigned s) { m_rand.set_seed(s); } diff --git a/src/opt/opt_solver.cpp b/src/opt/opt_solver.cpp index aff1301e0..c05949439 100644 --- a/src/opt/opt_solver.cpp +++ b/src/opt/opt_solver.cpp @@ -58,9 +58,6 @@ namespace opt { } unsigned opt_solver::m_dump_count = 0; - - opt_solver::~opt_solver() { - } void opt_solver::updt_params(params_ref const & _p) { opt_params p(_p); diff --git a/src/opt/opt_solver.h b/src/opt/opt_solver.h index 66835df48..e614a54fc 100644 --- a/src/opt/opt_solver.h +++ b/src/opt/opt_solver.h @@ -85,7 +85,6 @@ namespace opt { bool m_was_unknown; public: opt_solver(ast_manager & m, params_ref const & p, generic_model_converter& fm); - ~opt_solver() override; solver* translate(ast_manager& m, params_ref const& p) override; void updt_params(params_ref const& p) override; diff --git a/src/opt/pb_sls.cpp b/src/opt/pb_sls.cpp index 82802819d..e7cdf9476 100644 --- a/src/opt/pb_sls.cpp +++ b/src/opt/pb_sls.cpp @@ -123,9 +123,6 @@ namespace smt { one = mpz(1); } - ~imp() { - } - void reset() { init_max_flips(); m_non_greedy_percent = 30; diff --git a/src/parsers/util/simple_parser.cpp b/src/parsers/util/simple_parser.cpp index 6c3303e5c..c039fd9a1 100644 --- a/src/parsers/util/simple_parser.cpp +++ b/src/parsers/util/simple_parser.cpp @@ -28,9 +28,6 @@ simple_parser::simple_parser(ast_manager & m): m_exprs(m) { } -simple_parser::~simple_parser() { -} - void simple_parser::add_builtin_op(symbol const & s, family_id fid, decl_kind kind) { SASSERT(!m_builtin.contains(s)); SASSERT(!m_vars.contains(s)); diff --git a/src/parsers/util/simple_parser.h b/src/parsers/util/simple_parser.h index b40a0d983..c3cc0712e 100644 --- a/src/parsers/util/simple_parser.h +++ b/src/parsers/util/simple_parser.h @@ -45,7 +45,7 @@ protected: expr * parse_expr(scanner & s); public: simple_parser(ast_manager & m); - virtual ~simple_parser(); + virtual ~simple_parser() = default; void add_builtin_op(symbol const & s, family_id fid, decl_kind kind); void add_builtin_op(char const * str, family_id fid, decl_kind kind); void add_var(symbol const & s, var * v); diff --git a/src/sat/sat_local_search.cpp b/src/sat/sat_local_search.cpp index 6e5d3fae3..92b4f7f5c 100644 --- a/src/sat/sat_local_search.cpp +++ b/src/sat/sat_local_search.cpp @@ -353,9 +353,6 @@ namespace sat { DEBUG_CODE(verify_unsat_stack();); } - local_search::local_search() { - } - void local_search::reinit(solver& s, bool_vector const& phase) { import(s, true); for (unsigned i = phase.size(); i-- > 0; ) @@ -419,10 +416,6 @@ namespace sat { if (_init) init(); } - - local_search::~local_search() { - } - lbool local_search::check() { return check(0, nullptr, nullptr); diff --git a/src/sat/sat_local_search.h b/src/sat/sat_local_search.h index b62234522..e8959478e 100644 --- a/src/sat/sat_local_search.h +++ b/src/sat/sat_local_search.h @@ -227,10 +227,6 @@ namespace sat { unsigned num_vars() const { return m_vars.size() - 1; } // var index from 1 to num_vars public: - - local_search(); - - ~local_search() override; reslimit& rlimit() override { return m_limit; } diff --git a/src/sat/sat_model_converter.cpp b/src/sat/sat_model_converter.cpp index ddb277e9b..fa5720ede 100644 --- a/src/sat/sat_model_converter.cpp +++ b/src/sat/sat_model_converter.cpp @@ -23,13 +23,6 @@ Revision History: namespace sat { - model_converter::model_converter(): m_exposed_lim(0), m_solver(nullptr) { - } - - model_converter::~model_converter() { - } - - model_converter& model_converter::operator=(model_converter const& other) { copy(other); return *this; diff --git a/src/sat/sat_model_converter.h b/src/sat/sat_model_converter.h index 7393dc1bb..170886aa6 100644 --- a/src/sat/sat_model_converter.h +++ b/src/sat/sat_model_converter.h @@ -79,9 +79,9 @@ namespace sat { }; private: vector m_entries; // entries accumulated during SAT search - unsigned m_exposed_lim; // last entry that was exposed to model converter. + unsigned m_exposed_lim = 0; // last entry that was exposed to model converter. bool_vector m_mark; // literals that are used in asserted clauses. - solver const* m_solver; + solver const* m_solver = nullptr; elim_stackv m_elim_stack; void process_stack(model & m, literal_vector const& clause, elim_stackv const& stack) const; @@ -95,8 +95,6 @@ namespace sat { void add_elim_stack(entry & e); public: - model_converter(); - ~model_converter(); void set_solver(solver const* s) { m_solver = s; } void operator()(model & m) const; model_converter& operator=(model_converter const& other); diff --git a/src/sat/smt/euf_proof_checker.cpp b/src/sat/smt/euf_proof_checker.cpp index 42cda4bfb..c001ee90f 100644 --- a/src/sat/smt/euf_proof_checker.cpp +++ b/src/sat/smt/euf_proof_checker.cpp @@ -296,9 +296,6 @@ namespace euf { add_plugin(alloc(bv::theory_checker, m)); } - theory_checker::~theory_checker() { - } - void theory_checker::add_plugin(theory_checker_plugin* p) { m_plugins.push_back(p); p->register_plugins(*this); diff --git a/src/sat/smt/euf_proof_checker.h b/src/sat/smt/euf_proof_checker.h index d84e4d19f..0da57ee9e 100644 --- a/src/sat/smt/euf_proof_checker.h +++ b/src/sat/smt/euf_proof_checker.h @@ -45,7 +45,6 @@ namespace euf { void add_plugin(theory_checker_plugin* p); public: theory_checker(ast_manager& m); - ~theory_checker(); void register_plugin(symbol const& rule, theory_checker_plugin*); bool check(expr* jst); expr_ref_vector clause(expr* jst); diff --git a/src/sat/smt/q_mam.cpp b/src/sat/smt/q_mam.cpp index 1c356f9f2..0fa35cfd4 100644 --- a/src/sat/smt/q_mam.cpp +++ b/src/sat/smt/q_mam.cpp @@ -2000,9 +2000,6 @@ namespace q { m_args.resize(INIT_ARGS_SIZE); } - ~interpreter() { - } - void init(code_tree * t) { TRACE("mam_bug", tout << "preparing to match tree:\n" << *t << "\n";); m_registers.reserve(t->get_num_regs(), nullptr); diff --git a/src/sat/smt/specrel_solver.cpp b/src/sat/smt/specrel_solver.cpp index d59029e6b..064e19904 100644 --- a/src/sat/smt/specrel_solver.cpp +++ b/src/sat/smt/specrel_solver.cpp @@ -32,9 +32,6 @@ namespace specrel { ctx.get_egraph().add_plugin(alloc(euf::specrel_plugin, ctx.get_egraph())); } - solver::~solver() { - } - void solver::asserted(sat::literal l) { } diff --git a/src/sat/smt/specrel_solver.h b/src/sat/smt/specrel_solver.h index 9ebb76916..51e383bad 100644 --- a/src/sat/smt/specrel_solver.h +++ b/src/sat/smt/specrel_solver.h @@ -39,7 +39,6 @@ namespace specrel { public: solver(euf::solver& ctx, theory_id id); - ~solver() override; bool is_external(bool_var v) override { return false; } void get_antecedents(literal l, sat::ext_justification_idx idx, literal_vector& r, bool probing) override {} diff --git a/src/smt/mam.cpp b/src/smt/mam.cpp index a10c243f8..71eeb55cb 100644 --- a/src/smt/mam.cpp +++ b/src/smt/mam.cpp @@ -1995,9 +1995,6 @@ namespace { m_args.resize(INIT_ARGS_SIZE); } - ~interpreter() { - } - void init(code_tree * t) { TRACE("mam_bug", tout << "preparing to match tree:\n" << *t << "\n";); m_registers.reserve(t->get_num_regs(), nullptr); diff --git a/src/smt/qi_queue.cpp b/src/smt/qi_queue.cpp index 52399abb6..81d41eeee 100644 --- a/src/smt/qi_queue.cpp +++ b/src/smt/qi_queue.cpp @@ -43,9 +43,6 @@ namespace smt { m_vals.resize(15, 0.0f); } - qi_queue::~qi_queue() { - } - void qi_queue::setup() { TRACE("qi_cost", tout << "qi_cost: " << m_params.m_qi_cost << "\n";); if (!m_parser.parse_string(m_params.m_qi_cost.c_str(), m_cost_function)) { diff --git a/src/smt/qi_queue.h b/src/smt/qi_queue.h index bdf4bd50e..961dd73e0 100644 --- a/src/smt/qi_queue.h +++ b/src/smt/qi_queue.h @@ -80,7 +80,6 @@ namespace smt { public: qi_queue(quantifier_manager & qm, context & ctx, qi_params & params); - ~qi_queue(); void setup(); /** \brief Insert a new quantifier in the queue, f contains the quantifier and bindings. diff --git a/src/smt/smt_conflict_resolution.cpp b/src/smt/smt_conflict_resolution.cpp index 793243473..90877a963 100644 --- a/src/smt/smt_conflict_resolution.cpp +++ b/src/smt/smt_conflict_resolution.cpp @@ -52,9 +52,6 @@ namespace smt { { } - conflict_resolution::~conflict_resolution() { - } - /** \brief Mark all enodes in a 'proof' tree branch starting at n n -> ... -> root diff --git a/src/smt/smt_conflict_resolution.h b/src/smt/smt_conflict_resolution.h index cf707bd31..87ad19771 100644 --- a/src/smt/smt_conflict_resolution.h +++ b/src/smt/smt_conflict_resolution.h @@ -208,7 +208,7 @@ namespace smt { vector & watches ); - virtual ~conflict_resolution(); + virtual ~conflict_resolution() = default; virtual bool resolve(b_justification conflict, literal not_l); diff --git a/src/smt/smt_theory.cpp b/src/smt/smt_theory.cpp index 0c876e8bc..86f1c1141 100644 --- a/src/smt/smt_theory.cpp +++ b/src/smt/smt_theory.cpp @@ -177,9 +177,6 @@ namespace smt { m_lazy(true) { } - theory::~theory() { - } - smt_params const& theory::get_fparams() const { return ctx.get_fparams(); } diff --git a/src/smt/smt_theory.h b/src/smt/smt_theory.h index 416d626f7..74dfe8aa2 100644 --- a/src/smt/smt_theory.h +++ b/src/smt/smt_theory.h @@ -388,7 +388,7 @@ namespace smt { public: theory(context& ctx, family_id fid); - virtual ~theory(); + virtual ~theory() = default; virtual void setup() {} diff --git a/src/smt/theory_arith.h b/src/smt/theory_arith.h index e68f0f53f..e2bc5e7a4 100644 --- a/src/smt/theory_arith.h +++ b/src/smt/theory_arith.h @@ -1054,7 +1054,6 @@ namespace smt { // ----------------------------------- public: theory_arith(context& ctx); - ~theory_arith() override; theory * mk_fresh(context * new_ctx) override; diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index 8a2d9f3c9..e4f788f60 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -1737,10 +1737,6 @@ namespace smt { m_bound_watch(null_bool_var) { } - template - theory_arith::~theory_arith() { - } - template theory* theory_arith::mk_fresh(context* new_ctx) { return alloc(theory_arith, *new_ctx); diff --git a/src/smt/theory_bv.cpp b/src/smt/theory_bv.cpp index 5740285a2..b1fe47b65 100644 --- a/src/smt/theory_bv.cpp +++ b/src/smt/theory_bv.cpp @@ -1493,9 +1493,6 @@ namespace smt { m_bb.set_flat_and_or(false); } - theory_bv::~theory_bv() { - } - theory* theory_bv::mk_fresh(context* new_ctx) { return alloc(theory_bv, *new_ctx); } diff --git a/src/smt/theory_bv.h b/src/smt/theory_bv.h index 72775c1d3..0a7d4bbb2 100644 --- a/src/smt/theory_bv.h +++ b/src/smt/theory_bv.h @@ -268,7 +268,6 @@ namespace smt { typedef std::pair var_enode_pos; theory_bv(context& ctx); - ~theory_bv() override; theory * mk_fresh(context * new_ctx) override; diff --git a/src/smt/theory_datatype.cpp b/src/smt/theory_datatype.cpp index b794a44b5..3302199a2 100644 --- a/src/smt/theory_datatype.cpp +++ b/src/smt/theory_datatype.cpp @@ -762,8 +762,7 @@ namespace smt { m_util(m), m_autil(m), m_sutil(m), - m_find(*this), - m_trail_stack() { + m_find(*this) { } theory_datatype::~theory_datatype() { diff --git a/src/solver/assertions/asserted_formulas.cpp b/src/solver/assertions/asserted_formulas.cpp index ee94ac355..94a5edc59 100644 --- a/src/solver/assertions/asserted_formulas.cpp +++ b/src/solver/assertions/asserted_formulas.cpp @@ -89,10 +89,6 @@ void asserted_formulas::setup() { m_smt_params.m_relevancy_lemma = false; } - -asserted_formulas::~asserted_formulas() { -} - void asserted_formulas::push_assertion(expr * e, proof * pr, vector& result) { if (inconsistent()) { return; diff --git a/src/solver/assertions/asserted_formulas.h b/src/solver/assertions/asserted_formulas.h index 481af58b7..643cbc046 100644 --- a/src/solver/assertions/asserted_formulas.h +++ b/src/solver/assertions/asserted_formulas.h @@ -254,7 +254,6 @@ class asserted_formulas { public: asserted_formulas(ast_manager & m, smt_params & smtp, params_ref const& p); - ~asserted_formulas(); void finalize(); void updt_params(params_ref const& p); diff --git a/src/solver/check_sat_result.cpp b/src/solver/check_sat_result.cpp index fd7939d95..944f717b9 100644 --- a/src/solver/check_sat_result.cpp +++ b/src/solver/check_sat_result.cpp @@ -58,9 +58,6 @@ simple_check_sat_result::simple_check_sat_result(ast_manager & m): m_proof(m) { } -simple_check_sat_result::~simple_check_sat_result() { -} - void simple_check_sat_result::collect_statistics(statistics & st) const { st.copy(m_stats); } diff --git a/src/solver/check_sat_result.h b/src/solver/check_sat_result.h index 2269a1444..b992d260d 100644 --- a/src/solver/check_sat_result.h +++ b/src/solver/check_sat_result.h @@ -98,7 +98,6 @@ struct simple_check_sat_result : public check_sat_result { std::string m_unknown; simple_check_sat_result(ast_manager & m); - ~simple_check_sat_result() override; ast_manager& get_manager() const override { return m_proof.get_manager(); } void collect_statistics(statistics & st) const override; void get_unsat_core(expr_ref_vector & r) override; diff --git a/src/tactic/core/injectivity_tactic.cpp b/src/tactic/core/injectivity_tactic.cpp index e4071628c..640c41277 100644 --- a/src/tactic/core/injectivity_tactic.cpp +++ b/src/tactic/core/injectivity_tactic.cpp @@ -162,9 +162,6 @@ class injectivity_tactic : public tactic { rewriter_eq_cfg(ast_manager & m, InjHelper & map, params_ref const & p) : m_manager(m), inj_map(map) { } - ~rewriter_eq_cfg() { - } - void cleanup_buffers() { } diff --git a/src/tactic/core/simplify_tactic.cpp b/src/tactic/core/simplify_tactic.cpp index ee5cd0f73..6e2068e26 100644 --- a/src/tactic/core/simplify_tactic.cpp +++ b/src/tactic/core/simplify_tactic.cpp @@ -31,9 +31,6 @@ struct simplify_tactic::imp { m_num_steps(0) { } - ~imp() { - } - ast_manager & m() const { return m_manager; } diff --git a/src/util/hwf.cpp b/src/util/hwf.cpp index 8c20a4cda..e48934b5b 100644 --- a/src/util/hwf.cpp +++ b/src/util/hwf.cpp @@ -89,10 +89,6 @@ hwf_manager::hwf_manager() : // to the precision (not sure about the rounding modes though). } -hwf_manager::~hwf_manager() -{ -} - uint64_t RAW(double X) { uint64_t tmp; memcpy(&tmp, &(X), sizeof(uint64_t)); return tmp; } double DBL(uint64_t X) { double tmp; memcpy(&tmp, &(X), sizeof(double)); return tmp; } diff --git a/src/util/hwf.h b/src/util/hwf.h index 209a8fe77..926963937 100644 --- a/src/util/hwf.h +++ b/src/util/hwf.h @@ -46,7 +46,6 @@ class hwf_manager { public: typedef hwf numeral; hwf_manager(); - ~hwf_manager(); void reset(hwf & o) { set(o, 0); } void set(hwf & o, int value); diff --git a/src/util/map.h b/src/util/map.h index 0068be31b..fb72db01f 100644 --- a/src/util/map.h +++ b/src/util/map.h @@ -24,19 +24,6 @@ template struct _key_data { Key m_key; Value m_value; - _key_data() { - } - _key_data(Key const & k): - m_key(k) { - } - _key_data(Key const & k, Value const & v): - m_key(k), - m_value(v) { - } - _key_data(Key const& k, Value&& v): - m_key(k), - m_value(std::move(v)) { - } }; template @@ -108,27 +95,27 @@ public: } void insert(key const & k, value const & v) { - m_table.insert(key_data(k, v)); + m_table.insert(key_data{k, v}); } void insert(key const& k, value&& v) { - m_table.insert(key_data(k, std::move(v))); + m_table.insert(key_data{k, std::move(v)}); } bool insert_if_not_there_core(key const & k, value const & v, entry *& et) { - return m_table.insert_if_not_there_core(key_data(k,v), et); + return m_table.insert_if_not_there_core(key_data{k,v}, et); } value & insert_if_not_there(key const & k, value const & v) { - return m_table.insert_if_not_there2(key_data(k, v))->get_data().m_value; + return m_table.insert_if_not_there2(key_data{k, v})->get_data().m_value; } entry * insert_if_not_there3(key const & k, value const & v) { - return m_table.insert_if_not_there2(key_data(k, v)); + return m_table.insert_if_not_there2(key_data{k, v}); } entry * find_core(key const & k) const { - return m_table.find_core(key_data(k)); + return m_table.find_core(key_data{k}); } bool find(key const & k, value & v) const { @@ -150,7 +137,7 @@ public: } iterator find_iterator(key const & k) const { - return m_table.find(key_data(k)); + return m_table.find(key_data{k}); } value const & find(key const& k) const { @@ -175,7 +162,7 @@ public: } void remove(key const & k) { - m_table.remove(key_data(k)); + m_table.remove(key_data{k}); } void erase(key const & k) { diff --git a/src/util/obj_hashtable.h b/src/util/obj_hashtable.h index dbb2b776e..2784439a8 100644 --- a/src/util/obj_hashtable.h +++ b/src/util/obj_hashtable.h @@ -60,7 +60,7 @@ public: Value m_value; key_data() = default; key_data(Key * k): - m_key(k), m_value() { + m_key(k) { } key_data(Key * k, Value const & v): m_key(k), diff --git a/src/util/ref.h b/src/util/ref.h index 849e23b38..22e51b783 100644 --- a/src/util/ref.h +++ b/src/util/ref.h @@ -21,7 +21,7 @@ Revision History: template class ref { - T * m_ptr; + T * m_ptr = nullptr; void inc_ref() { if (m_ptr) { @@ -36,9 +36,7 @@ class ref { } public: - ref(): - m_ptr(nullptr) { - } + ref() = default; ref(T * ptr): m_ptr(ptr) { @@ -50,9 +48,9 @@ public: inc_ref(); } - ref (ref && r) noexcept : m_ptr(nullptr) { - std::swap(m_ptr, r.m_ptr); - } + ref(ref && r) noexcept { + std::swap(m_ptr, r.m_ptr); + } ~ref() { dec_ref(); From e58eb9f3029a7055b9070a235aced7241d4ee5c3 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 3 Oct 2024 12:47:08 -0700 Subject: [PATCH 174/187] fix indentation for mbp Signed-off-by: Nikolaj Bjorner --- src/qe/qe_mbp.cpp | 76 +++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/qe/qe_mbp.cpp b/src/qe/qe_mbp.cpp index 00926f3fb..96ae5e85a 100644 --- a/src/qe/qe_mbp.cpp +++ b/src/qe/qe_mbp.cpp @@ -77,50 +77,50 @@ namespace { }; // rewrite all occurrences of (as const arr c) to (as const arr v) where v = m_eval(c) struct app_const_arr_rewriter : public default_rewriter_cfg { - ast_manager &m; - array_util m_arr; - datatype_util m_dt_util; - model_evaluator m_eval; - expr_ref val; - - app_const_arr_rewriter(ast_manager& man, model& mdl): m(man), m_arr(m), m_dt_util(m), m_eval(mdl), val(m) { - m_eval.set_model_completion(false); + ast_manager &m; + array_util m_arr; + datatype_util m_dt_util; + model_evaluator m_eval; + expr_ref val; + + app_const_arr_rewriter(ast_manager& man, model& mdl): m(man), m_arr(m), m_dt_util(m), m_eval(mdl), val(m) { + m_eval.set_model_completion(false); + } + br_status reduce_app(func_decl *f, unsigned num, expr *const *args, + expr_ref &result, proof_ref &result_pr) { + if (m_arr.is_const(f) && !m.is_value(args[0])) { + val = m_eval(args[0]); + SASSERT(m.is_value(val)); + result = m_arr.mk_const_array(f->get_range(), val); + return BR_DONE; } - br_status reduce_app(func_decl *f, unsigned num, expr *const *args, - expr_ref &result, proof_ref &result_pr) { - if (m_arr.is_const(f) && !m.is_value(args[0])) { - val = m_eval(args[0]); - SASSERT(m.is_value(val)); - result = m_arr.mk_const_array(f->get_range(), val); - return BR_DONE; + if (m_dt_util.is_constructor(f)) { + // cons(head(x), tail(x)) --> x + ptr_vector const *accessors = + m_dt_util.get_constructor_accessors(f); + + SASSERT(num == accessors->size()); + // -- all accessors must have exactly one argument + if (any_of(*accessors, [&](const func_decl* acc) { return acc->get_arity() != 1; })) { + return BR_FAILED; } - if (m_dt_util.is_constructor(f)) { - // cons(head(x), tail(x)) --> x - ptr_vector const *accessors = - m_dt_util.get_constructor_accessors(f); - - SASSERT(num == accessors->size()); - // -- all accessors must have exactly one argument - if (any_of(*accessors, [&](const func_decl* acc) { return acc->get_arity() != 1; })) { - return BR_FAILED; + + if (num >= 1 && is_app(args[0]) && to_app(args[0])->get_decl() == accessors->get(0)) { + bool is_all = true; + expr* t = to_app(args[0])->get_arg(0); + for(unsigned i = 1; i < num && is_all; ++i) { + is_all &= (is_app(args[i]) && + to_app(args[i])->get_decl() == accessors->get(i) && + to_app(args[i])->get_arg(0) == t); } - - if (num >= 1 && is_app(args[0]) && to_app(args[0])->get_decl() == accessors->get(0)) { - bool is_all = true; - expr* t = to_app(args[0])->get_arg(0); - for(unsigned i = 1; i < num && is_all; ++i) { - is_all &= (is_app(args[i]) && - to_app(args[i])->get_decl() == accessors->get(i) && - to_app(args[i])->get_arg(0) == t); - } - if (is_all) { - result = t; - return BR_DONE; - } + if (is_all) { + result = t; + return BR_DONE; } } - return BR_FAILED; } + return BR_FAILED; + } }; } From f5db6bf92b88a9648ae73de38d7a9989233a0922 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 3 Oct 2024 12:48:15 -0700 Subject: [PATCH 175/187] install Julia for macos build Signed-off-by: Nikolaj Bjorner --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d12872f07..938f63507 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -245,7 +245,7 @@ jobs: vmImage: "macOS-latest" steps: - script: brew install ninja -# - script: brew install --cask julia + - script: brew install --cask julia - script: | julia -e "using Pkg; Pkg.add(PackageSpec(name=\"libcxxwrap_julia_jll\"))" JlCxxDir=$(julia -e "using libcxxwrap_julia_jll; println(joinpath(dirname(libcxxwrap_julia_jll.libcxxwrap_julia_path), \"cmake\", \"JlCxx\"))") From a98c9250690f82a67e27b5d8ae84d61550ffdfd7 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 3 Oct 2024 18:14:47 -0700 Subject: [PATCH 176/187] optimize var_subst --- src/ast/rewriter/var_subst.cpp | 14 ++++++++++++++ src/cmd_context/cmd_context.cpp | 10 ++++------ src/cmd_context/cmd_context.h | 5 +++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/ast/rewriter/var_subst.cpp b/src/ast/rewriter/var_subst.cpp index ec33bd265..532a49ec5 100644 --- a/src/ast/rewriter/var_subst.cpp +++ b/src/ast/rewriter/var_subst.cpp @@ -52,6 +52,20 @@ expr_ref var_subst::operator()(expr * n, unsigned num_args, expr * const * args) rep(n, result); return result; } + if (is_app(n) && all_of(*to_app(n), [&](expr* arg) { return is_ground(arg) || is_var(arg); })) { + ptr_buffer new_args; + for (auto arg : *to_app(n)) { + if (is_ground(arg)) + new_args.push_back(arg); + else { + unsigned idx = to_var(arg)->get_idx(); + new_args.push_back(m_std_order ? args[idx] : args[num_args - idx - 1]); + } + } + result = m.mk_app(to_app(n)->get_decl(), new_args.size(), new_args.data()); + // verbose_stream() << result << "\n"; + return result; + } SASSERT(is_well_sorted(result.m(), n)); m_reducer.reset(); if (m_std_order) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 5f5195bb9..ca9bbec26 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -33,7 +33,6 @@ Notes: #include "ast/fpa_decl_plugin.h" #include "ast/special_relations_decl_plugin.h" #include "ast/ast_pp.h" -#include "ast/rewriter/var_subst.h" #include "ast/pp.h" #include "ast/ast_smt2_pp.h" #include "ast/ast_ll_pp.h" @@ -406,8 +405,7 @@ void cmd_context::insert_macro(symbol const& s, unsigned arity, sort*const* doma recfun::promise_def d = p.ensure_def(s, arity, domain, t->get_sort(), false); // recursive functions have opposite calling convention from macros! - var_subst sub(m(), true); - expr_ref tt = sub(t, rvars); + expr_ref tt = std_subst()(t, rvars); p.set_definition(replace, d, true, vars.size(), vars.data(), tt); register_fun(s, d.get_def()->get_decl()); } @@ -461,7 +459,6 @@ bool cmd_context::macros_find(symbol const& s, unsigned n, expr*const* args, exp if (eq) { t = d.m_body; t = sub(t); - verbose_stream() << "macro " << t << "\n"; ptr_buffer domain; for (unsigned i = 0; i < n; ++i) domain.push_back(args[i]->get_sort()); @@ -1257,9 +1254,8 @@ bool cmd_context::try_mk_macro_app(symbol const & s, unsigned num_args, expr * c tout << "s: " << s << "\n"; tout << "body:\n" << mk_ismt2_pp(_t, m()) << "\n"; tout << "args:\n"; for (unsigned i = 0; i < num_args; i++) tout << mk_ismt2_pp(args[i], m()) << "\n" << mk_pp(args[i]->get_sort(), m()) << "\n";); - var_subst subst(m(), false); scoped_rlimit no_limit(m().limit(), 0); - result = subst(_t, coerced_args); + result = rev_subst()(_t, coerced_args); if (well_sorted_check_enabled() && !is_well_sorted(m(), result)) throw cmd_exception("invalid macro application, sort mismatch ", s); return true; @@ -1524,6 +1520,8 @@ void cmd_context::reset(bool finalize) { if (m_own_manager) { dealloc(m_manager); m_manager = nullptr; + m_std_subst = nullptr; + m_rev_subst = nullptr; m_manager_initialized = false; } else { diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index cd43203a7..dde1d7962 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -33,6 +33,7 @@ Notes: #include "ast/datatype_decl_plugin.h" #include "ast/recfun_decl_plugin.h" #include "ast/rewriter/seq_rewriter.h" +#include "ast/rewriter/var_subst.h" #include "ast/converters/generic_model_converter.h" #include "solver/solver.h" #include "solver/check_logic.h" @@ -280,6 +281,7 @@ protected: ptr_vector m_assertions; std::vector m_assertion_strings; ptr_vector m_assertion_names; // named assertions are represented using boolean variables. + scoped_ptr m_std_subst, m_rev_subst; struct scope { unsigned m_func_decls_stack_lim; @@ -317,6 +319,9 @@ protected: scoped_ptr m_pp_env; pp_env & get_pp_env() const; + var_subst& std_subst() { if (!m_std_subst) m_std_subst = alloc(var_subst, m(), true); return *m_std_subst; } + var_subst& rev_subst() { if (!m_rev_subst) m_rev_subst = alloc(var_subst, m(), false); return *m_rev_subst; } + void register_builtin_sorts(decl_plugin * p); void register_builtin_ops(decl_plugin * p); void load_plugin(symbol const & name, bool install_names, svector& fids); From 66bb3109662ff2ff1c25de128b5e3ebc270334eb Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 3 Oct 2024 18:19:14 -0700 Subject: [PATCH 177/187] reset before manager is deallocated Signed-off-by: Nikolaj Bjorner --- src/cmd_context/cmd_context.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index ca9bbec26..59de003c8 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -1514,14 +1514,15 @@ void cmd_context::reset(bool finalize) { m_opt = nullptr; m_pp_env = nullptr; m_dt_eh = nullptr; + m_std_subst = nullptr; + m_rev_subst = nullptr; if (m_manager) { dealloc(m_pmanager); m_pmanager = nullptr; if (m_own_manager) { dealloc(m_manager); m_manager = nullptr; - m_std_subst = nullptr; - m_rev_subst = nullptr; + m_manager_initialized = false; } else { From 969511ac00830a97f49be9d9585540f33b8aaa7e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 3 Oct 2024 19:35:16 -0700 Subject: [PATCH 178/187] fixup std-order / inv-order Signed-off-by: Nikolaj Bjorner --- src/ast/has_free_vars.cpp | 3 ++- src/ast/rewriter/var_subst.cpp | 2 +- src/parsers/smt2/smt2parser.cpp | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ast/has_free_vars.cpp b/src/ast/has_free_vars.cpp index b1b74c7da..c5f3db027 100644 --- a/src/ast/has_free_vars.cpp +++ b/src/ast/has_free_vars.cpp @@ -30,7 +30,7 @@ class contains_vars::imp { void visit(expr * n, unsigned delta, bool & visited) { expr_delta_pair e(n, delta); - if (!m_cache.contains(e)) { + if (!is_ground(n) && !m_cache.contains(e)) { m_todo.push_back(e); visited = false; } @@ -74,6 +74,7 @@ public: m_todo.push_back(expr_delta_pair(n, begin)); while (!m_todo.empty()) { expr_delta_pair e = m_todo.back(); + if (visit_children(e.m_node, e.m_delta)) { m_cache.insert(e); m_todo.pop_back(); diff --git a/src/ast/rewriter/var_subst.cpp b/src/ast/rewriter/var_subst.cpp index 532a49ec5..4d4c17865 100644 --- a/src/ast/rewriter/var_subst.cpp +++ b/src/ast/rewriter/var_subst.cpp @@ -59,7 +59,7 @@ expr_ref var_subst::operator()(expr * n, unsigned num_args, expr * const * args) new_args.push_back(arg); else { unsigned idx = to_var(arg)->get_idx(); - new_args.push_back(m_std_order ? args[idx] : args[num_args - idx - 1]); + new_args.push_back(m_std_order ? args[num_args - idx - 1] : args[idx]); } } result = m.mk_app(to_app(n)->get_decl(), new_args.size(), new_args.data()); diff --git a/src/parsers/smt2/smt2parser.cpp b/src/parsers/smt2/smt2parser.cpp index 48c48d0a9..afa361538 100644 --- a/src/parsers/smt2/smt2parser.cpp +++ b/src/parsers/smt2/smt2parser.cpp @@ -116,6 +116,7 @@ namespace smt2 { symbol m_match; symbol m_case; symbol m_underscore; + contains_vars m_has_free_vars; typedef std::pair named_expr; named_expr m_last_named_expr; @@ -1031,7 +1032,7 @@ namespace smt2 { void name_expr(expr * n, symbol const & s) { TRACE("name_expr", tout << "naming: " << s << " ->\n" << mk_pp(n, m()) << "\n";); - if (!is_ground(n) && has_free_vars(n)) + if (!is_ground(n) && m_has_free_vars(n)) throw parser_exception("invalid named expression, expression contains free variables"); m_ctx.insert(s, 0, nullptr, n); m_last_named_expr.first = s; From b60e1a2ed22111fefa328cfcbdc3fa1cdd2b1555 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 3 Oct 2024 20:06:45 -0700 Subject: [PATCH 179/187] fixup variables Signed-off-by: Nikolaj Bjorner --- src/ast/rewriter/var_subst.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ast/rewriter/var_subst.cpp b/src/ast/rewriter/var_subst.cpp index 4d4c17865..711ca2b51 100644 --- a/src/ast/rewriter/var_subst.cpp +++ b/src/ast/rewriter/var_subst.cpp @@ -59,7 +59,10 @@ expr_ref var_subst::operator()(expr * n, unsigned num_args, expr * const * args) new_args.push_back(arg); else { unsigned idx = to_var(arg)->get_idx(); - new_args.push_back(m_std_order ? args[num_args - idx - 1] : args[idx]); + expr* new_arg = m_std_order ? args[num_args - idx - 1] : args[idx]; + if (!new_arg) + new_arg = arg; + new_args.push_back(new_arg); } } result = m.mk_app(to_app(n)->get_decl(), new_args.size(), new_args.data()); From 2ae4ac8d0a24b6542306737501bcc2679e34fcd2 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 4 Oct 2024 08:38:52 -0700 Subject: [PATCH 180/187] fix build Signed-off-by: Nikolaj Bjorner --- src/ast/rewriter/var_subst.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ast/rewriter/var_subst.cpp b/src/ast/rewriter/var_subst.cpp index 711ca2b51..820a235d8 100644 --- a/src/ast/rewriter/var_subst.cpp +++ b/src/ast/rewriter/var_subst.cpp @@ -59,14 +59,15 @@ expr_ref var_subst::operator()(expr * n, unsigned num_args, expr * const * args) new_args.push_back(arg); else { unsigned idx = to_var(arg)->get_idx(); - expr* new_arg = m_std_order ? args[num_args - idx - 1] : args[idx]; + expr* new_arg = nullptr; + if (idx < num_args) + new_arg = m_std_order ? args[num_args - idx - 1] : args[idx]; if (!new_arg) new_arg = arg; new_args.push_back(new_arg); } } result = m.mk_app(to_app(n)->get_decl(), new_args.size(), new_args.data()); - // verbose_stream() << result << "\n"; return result; } SASSERT(is_well_sorted(result.m(), n)); From 24d7b05c0d4e1eb07b2c6b11dd19c0aba4f9a603 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 4 Oct 2024 16:55:00 -0700 Subject: [PATCH 181/187] refactor and optimize git operations for commit messages and failure analysis (#7412) --- .gitignore.genai | 3 +++ genaisrc/gai.genai.mts | 17 +++++++++++++++++ genaisrc/gcm.genai.mts | 30 +++++++++--------------------- genaisrc/genaiscript.d.ts | Bin 73251 -> 78662 bytes 4 files changed, 29 insertions(+), 21 deletions(-) create mode 100644 .gitignore.genai create mode 100644 genaisrc/gai.genai.mts diff --git a/.gitignore.genai b/.gitignore.genai new file mode 100644 index 000000000..254ca5bfe --- /dev/null +++ b/.gitignore.genai @@ -0,0 +1,3 @@ +**/genaiscript.d.ts +**/package-lock.json +**/yarn.lock diff --git a/genaisrc/gai.genai.mts b/genaisrc/gai.genai.mts new file mode 100644 index 000000000..9de3cf11a --- /dev/null +++ b/genaisrc/gai.genai.mts @@ -0,0 +1,17 @@ +script({ + tools: ["agent_fs", "agent_git", "agent_github"], +}) + +const { + workflow = "latest failed", + failure_run_id = "latest", + branch = await git.defaultBranch(), +} = env.vars + +$`Investigate the status of the ${workflow} workflow and identify the root cause of the failure of run ${failure_run_id} in branch ${branch}. + +- Correlate the failure with the relevant commits, pull requests or issues. +- Compare the source code between the failed run commit and the last successful run commit before that run. + +In your report, include html links to the relevant runs, commits, pull requests or issues. +` diff --git a/genaisrc/gcm.genai.mts b/genaisrc/gcm.genai.mts index e1ebd1197..d1f97174f 100644 --- a/genaisrc/gcm.genai.mts +++ b/genaisrc/gcm.genai.mts @@ -6,28 +6,16 @@ script({ description: "Generate a commit message for all staged changes", }) -// TODO: update this diff command to match your workspace -const diffCmd = "git diff --cached -- . :!**/genaiscript.d.ts" - // Check for staged changes and stage all changes if none are staged -let diff = await host.exec(diffCmd) -if (!diff.stdout) { - /** - * Ask user to stage all changes if none are staged - */ - const stage = await host.confirm("No staged changes. Stage all changes?", { - default: true, - }) - if (stage) { - // Stage all changes and recompute diff - await host.exec("git add .") - diff = await host.exec(diffCmd) - } - if (!diff.stdout) cancel("no staged changes") -} +const diff = await git.diff({ + staged: true, + excludedPaths: "**/genaiscript.d.ts", + askStageOnEmpty: true, +}) +if (!diff) cancel("no staged changes") // show diff in the console -console.log(diff.stdout) +console.log(diff) let choice let message @@ -79,9 +67,9 @@ Please generate a concise, one-line commit message for these changes. } // Regenerate message if (choice === "commit" && message) { - console.log((await host.exec("git", ["commit", "-m", message])).stdout) + console.log(await git.exec(["commit", "-m", message])) if (await host.confirm("Push changes?", { default: true })) - console.log((await host.exec("git push")).stdout) + console.log(await git.exec("push")) break } } while (choice !== "commit") diff --git a/genaisrc/genaiscript.d.ts b/genaisrc/genaiscript.d.ts index c0a6426d2c5fa168f0c708d8f185820733d3431f..e11a3edd76e417e0aa88b2dc42a15e63ac4c0898 100644 GIT binary patch delta 4013 zcmbVPU2I%O71k!}^>*DP#?7wn#7-s-Asfd@ji~K(o7(v!p~Z3R)P;8 zvLU)qM{UDtk0DYq=HK;P**8rVTuu~X_tZn=Z*-q~ScTn$#zq+GlIHxS5E4)CSL(Xg z27Cs~i~RE{AO4^2&($E*e8I)GR?2I>>p~&w$uy}<%39^ZO^cz4nV0u)u~q1_elrhy zegjCjpr*j~sAIGIQ%)goIz<&^v!jkiMbZ*dn+?mi$J}hN;8!9?M>B~}zQYAd z(aAHFwa#mfWdVkrZx3yn{R;d=V4DaQA92YtB`bFc$--VKPnP+3a=Hgh z$`#cVd@hONdDpkOoxH?ny1P#`+6c^SgSu9|GEFK*OrkaF(WLRnsu%n+`RXvg^7GzX z&&Dqz$3ULrm<;K}pf=GFwUJjMh-oe@dy)gt=>76HSS$+DnH*X}RL>#ixzsL>!BJ%m zeG>^$^}?l~_?h+I_>;%a&hlLgdy+1}y8QV1Wz*#$&bk%qMrIotvyDVK;v zTx{~ghX%NL`nB~}2V!YHwXct7&rH@o0{_gPH+K=+w`TalYuUj5;&9hq5vtFCR74q0 zmauoyvC1Y9SUxVrsp|S%Uu-n^(L72u(0Jj+gM8wN-NB!}GMLyFVH5%$?85&{@zkxp z3l|?Y!MghM(L1%Bfnx! zN<^4;tDBVNe5t1dtbqj8h-L_<$0cQlQO|KJvPE3t`L3sv!6E)Wxnuci-GMOwF>P4o*eRA_)q7zczVLgvq0-@;$N zzVGB|DyD~(iAD{osj4>FqDI_N$D$LJ2;wm$n3~^tDZ}UeEyo1ciGs7n6f)p0l0zew z1KmN1eyD&M8Iel_z)f`dXQbpef44U-4ERDV!w>G-#((obeCjw;(<4Yr3>v&rFlQn+ zHFA)etb}S&m`P%ly~<(UGci1d+0tXe{G9!HAq0#Hz*hv@3R^Kc@KXk|Wi#uq48;0} zrdu>*RWp5^=<^MW*fhsCcJSIOD9U?OHhzP>R09jgGE}|kR{oRWbZ!)V!jw|HcVheE zhvy_9thYlwpAvB9Mrl*-1C87}OHcY#>G$OnByGQW?{ucL$Wlwiw&=-MMU4g zi=jntAsqXHUpOC0Qq@$7+VCP7z^~UiQ~Aq(qcp^1lX&7DhYWy+7j{j+nX|c zXwBRGA*u6ktWEH(YZ?B>wGa3k$9qnk3W;916pIUm|4X3#;B_LNRuX%NdJ2FQCdMNI zQ@e|VgYS8{pLbQC>3v*~iyB<$C~CtyGZfUSbDQ}GwFjqQ^L?b1j&*0nHXW>shfZv& zk2-}}=*0T4$rJqc)uHV`&uzU81bs)()=t5IK&~Y>EEwj+_N8!uMGEG{mFs##+SG{Znc%;EuMZxH;J42`8spDb(={<K4P%I2rx0?3+krO}oG2;P_Z(=69J7k8A=s`T5xaO+xrl;3klWEbDA4iJ zN=*@e|LFE${Oa5$@mAm0Ax8eKYx^%Fv2eraJPrTUc^iUiQErG0qMC=(=hfk?FwVCI z$mgyN0rmeSljh@B`-5*^`*)l#8@(c;hkRQnu33T27oF2QXGy&NCXih8riTqDMcJl8 zV7n4rzw!EhvES{BO$Wzrf9In7d(-q7zq5IeU%s7qvuA7UNOJw}>DZPOY{;-93SwCQ SUphA4l@ld;Gna||qx=8t<}{oD delta 337 zcmX^1jAij2mJOY(lf~KAPkzj1ws{wO5aVPuPP@rZIkhLV^0-c3%gH&pi6>;UGVfg3 z$$$K~Hd|}=2ux1137cGNt+4r|?F+`u7wiq#HuJg(GHy0>Kg2ru6cg{{a^Izs53`6* zKI Date: Tue, 8 Oct 2024 09:10:02 -0700 Subject: [PATCH 182/187] mico-tuning --- src/ast/normal_forms/nnf.cpp | 5 +++-- src/ast/recfun_decl_plugin.cpp | 16 +++++----------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/ast/normal_forms/nnf.cpp b/src/ast/normal_forms/nnf.cpp index 1f0ce6781..9b4ea1346 100644 --- a/src/ast/normal_forms/nnf.cpp +++ b/src/ast/normal_forms/nnf.cpp @@ -69,6 +69,7 @@ class skolemizer { typedef act_cache cache; ast_manager & m; + var_subst m_subst; symbol m_sk_hack; bool m_sk_hack_enabled; cache m_cache; @@ -128,7 +129,6 @@ class skolemizer { // // (VAR 0) should be in the last position of substitution. // - var_subst s(m); SASSERT(is_well_sorted(m, q->get_expr())); expr_ref tmp(m); expr * body = q->get_expr(); @@ -146,7 +146,7 @@ class skolemizer { } } } - r = s(body, substitution); + r = m_subst(body, substitution); p = nullptr; if (m_proofs_enabled) { if (q->get_kind() == forall_k) @@ -159,6 +159,7 @@ class skolemizer { public: skolemizer(ast_manager & m): m(m), + m_subst(m), m_sk_hack("sk_hack"), m_sk_hack_enabled(false), m_cache(m), diff --git a/src/ast/recfun_decl_plugin.cpp b/src/ast/recfun_decl_plugin.cpp index cba1932be..79c6fa066 100644 --- a/src/ast/recfun_decl_plugin.cpp +++ b/src/ast/recfun_decl_plugin.cpp @@ -240,23 +240,18 @@ namespace recfun { { VERIFY(m_cases.empty() && "cases cannot already be computed"); SASSERT(n_vars == m_domain.size()); - TRACEFN("compute cases " << mk_pp(rhs, m)); - unsigned case_idx = 0; - - std::string name("case-"); - name.append(m_name.str()); - - m_vars.append(n_vars, vars); - m_rhs = rhs; - if (!is_macro) for (expr* e : subterms::all(m_rhs)) if (is_lambda(e)) throw default_exception("recursive definitions with lambdas are not supported"); - + + + unsigned case_idx = 0; expr_ref_vector conditions(m); + m_vars.append(n_vars, vars); + m_rhs = rhs; // is the function a macro (unconditional body)? if (is_macro || n_vars == 0 || !contains_ite(u, rhs)) { @@ -265,7 +260,6 @@ namespace recfun { return; } - // analyze control flow of `rhs`, accumulating guards and // rebuilding a `ite`-free RHS on the fly for each path in `rhs`. From 0fec7efc7ba75de1292b78fe334a87a884a2187f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 8 Oct 2024 09:11:08 -0700 Subject: [PATCH 183/187] micro-tuning --- src/ast/rewriter/th_rewriter.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ast/rewriter/th_rewriter.cpp b/src/ast/rewriter/th_rewriter.cpp index 483e2d5fb..3af887008 100644 --- a/src/ast/rewriter/th_rewriter.cpp +++ b/src/ast/rewriter/th_rewriter.cpp @@ -59,6 +59,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg { bv_util m_bv_util; der m_der; expr_safe_replace m_rep; + unused_vars_eliminator m_elim_unused_vars; expr_ref_vector m_pinned; // substitution support expr_dependency_ref m_used_dependencies; // set of dependencies of used substitutions @@ -829,8 +830,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg { } } SASSERT(old_q->get_sort() == q1->get_sort()); - result = elim_unused_vars(m(), q1, params_ref()); - + result = m_elim_unused_vars(q1); result_pr = nullptr; @@ -887,6 +887,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg { m_bv_util(m), m_der(m), m_rep(m), + m_elim_unused_vars(m, params_ref()), m_pinned(m), m_used_dependencies(m) { updt_local_params(p); From 8a95dd4d65d0a4d9eaf760ebcd5ddf5456a17780 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 8 Oct 2024 09:22:10 -0700 Subject: [PATCH 184/187] A slice solver option for interactive use case A slice solver prunes the set of active assertions based on symbol occurrences in a goal that is tracked as a @query. Ground assertions that have symbols intersecting with the query are included in the solver state, and quantifiers that with patterns that intersect with the slice are included. The slice is the fixedpoint of including symbols from all included assertions. Enable the functionality for command-line use by setting solver.slice=true --- src/params/solver_params.pyg | 1 + src/solver/CMakeLists.txt | 1 + src/solver/slice_solver.cpp | 438 +++++++++++++++++++++++++++++++++++ src/solver/slice_solver.h | 25 ++ 4 files changed, 465 insertions(+) create mode 100644 src/solver/slice_solver.cpp create mode 100644 src/solver/slice_solver.h diff --git a/src/params/solver_params.pyg b/src/params/solver_params.pyg index 0912b4c7f..20e38b471 100644 --- a/src/params/solver_params.pyg +++ b/src/params/solver_params.pyg @@ -8,6 +8,7 @@ def_module_params('solver', ('lemmas2console', BOOL, False, 'print lemmas during search'), ('instantiations2console', BOOL, False, 'print quantifier instantiations to the console'), ('axioms2files', BOOL, False, 'print negated theory axioms to separate files during search'), + ('slice', BOOL, False, 'use slice solver that filters assertions to use symbols occuring in @query formulas'), ('proof.log', SYMBOL, '', 'log clause proof trail into a file'), ('proof.check', BOOL, True, 'check proof logs'), ('proof.check_rup', BOOL, True, 'check proof RUP inference in proof logs'), diff --git a/src/solver/CMakeLists.txt b/src/solver/CMakeLists.txt index 088f2cbb2..4c5f8b428 100644 --- a/src/solver/CMakeLists.txt +++ b/src/solver/CMakeLists.txt @@ -6,6 +6,7 @@ z3_add_component(solver mus.cpp parallel_tactical.cpp simplifier_solver.cpp + slice_solver.cpp smt_logics.cpp solver.cpp solver_na2as.cpp diff --git a/src/solver/slice_solver.cpp b/src/solver/slice_solver.cpp new file mode 100644 index 000000000..1158ef964 --- /dev/null +++ b/src/solver/slice_solver.cpp @@ -0,0 +1,438 @@ +/*++ +Copyright (c) 2023 Microsoft Corporation + +Module Name: + + slice_solver.cpp + +Abstract: + + Implements a solver that slices assertions based on the query. + +Author: + + Nikolaj Bjorner (nbjorner) 2024-10-07 + +--*/ + +#include "solver/solver.h" +#include "solver/slice_solver.h" +#include "ast/for_each_ast.h" +#include "ast/ast_pp.h" +#include "params/solver_params.hpp" + +class slice_solver : public solver { + + struct fml_t { + expr_ref formula; + expr_ref assumption; + bool active; + unsigned level; + }; + ast_manager& m; + solver_ref s; + vector m_assertions; + unsigned_vector m_assertions_lim; + obj_map m_occurs; + ptr_vector m_occurs_trail; + unsigned_vector m_occurs_lim; + obj_hashtable m_used_funs; + ptr_vector m_used_funs_trail; + unsigned_vector m_used_funs_lim; + bool m_has_query = false; + unsigned m_level = 0; + + ast_mark m_mark; + + void add_occurs(unsigned i, expr* e) { + struct visit { + slice_solver& s; + unsigned i; + visit(slice_solver& s, unsigned i):s(s), i(i) {} + + void operator()(func_decl* f) { + if (is_uninterp(f)) { + s.m_occurs.insert_if_not_there(f, unsigned_vector()).push_back(i); + s.m_occurs_trail.push_back(f); + } + } + + void operator()(ast* a) {} + }; + m_mark.reset(); + visit visitor(*this, i); + ptr_buffer args; + + if (m.is_and(e)) + args.append(to_app(e)->get_num_args(), to_app(e)->get_args()); + else + args.push_back(e); + bool has_quantifier = any_of(args, [&](expr* arg) { return is_quantifier(arg); }); + for (expr* arg : args) { + if (is_quantifier(arg)) { + auto q = to_quantifier(arg); + // all symbols in pattern must be present for quantifier to be considered relevant. + for (unsigned j = 0; j < q->get_num_patterns(); ++j) + for_each_ast(visitor, m_mark, q->get_pattern(j)); + } + else if (!has_quantifier) + for_each_ast(visitor, m_mark, arg); + } + } + + void flush() { + for (unsigned idx = 0; idx < m_assertions.size(); ++idx) { + auto& f = m_assertions[idx]; + if (!f.active) { + f.active = true; + m_new_idx.push_back(idx); + } + } + activate_indices(); + m_new_idx.reset(); + } + + unsigned_vector m_new_idx; + void activate(unsigned idx, expr* e) { + struct visit { + slice_solver& s; + visit(slice_solver& s): s(s) {} + void operator()(func_decl* f) { + if (!s.m_used_funs.contains(f)) { + s.m_used_funs_trail.push_back(f); + s.m_used_funs.insert(f); + } + } + void operator()(ast* a) {} + }; + SASSERT(m_new_idx.empty()); + visit visitor(*this); + m_mark.reset(); + for_each_ast(visitor, m_mark, e); + consume_used_funs(); + for (unsigned i = 0; m.inc() && i < m_new_idx.size(); ++i) { + auto& f = m_assertions[m_new_idx[i]]; + expr* e = f.formula; + ptr_buffer args; + if (m.is_and(e)) + args.append(to_app(e)->get_num_args(), to_app(e)->get_args()); + else + args.push_back(e); + + for (expr* arg : args) { + if (is_quantifier(arg)) { + for_each_ast(visitor, m_mark, arg); + consume_used_funs(); + } + } + } + std::sort(m_new_idx.begin(), m_new_idx.end()); + activate_indices(); + m_new_idx.reset(); + + IF_VERBOSE(2, log_active(verbose_stream());); + } + + void log_active(std::ostream& out) { + unsigned num_passive = 0, num_active = 0; + for (auto const& f : m_assertions) + if (f.active) + ++num_active; + else + ++num_passive; + out << "passive " << num_passive << " active " << num_active << "\n"; + } + + unsigned m_qhead = 0; + void consume_used_funs() { + for (; m_qhead < m_used_funs_trail.size(); ++m_qhead) { + func_decl* f = m_used_funs_trail[m_qhead]; + auto* e = m_occurs.find_core(f); + if (!e) + continue; + for (unsigned idx : e->get_data().m_value) { + if (!should_activate(idx)) + continue; + m_new_idx.push_back(idx); + m_assertions[idx].active = true; + } + } + } + + bool should_activate(unsigned idx) { + auto& f = m_assertions[idx]; + return !f.active && should_activate(f.formula.get()); + } + + bool should_activate(expr* f) { + if (is_ground(f)) + return true; + + if (m.is_and(f)) + for (expr* arg : *to_app(f)) + if (is_forall(arg) && should_activate(arg)) + return true; + + if (!is_forall(f)) + return true; + + auto q = to_quantifier(f); + return should_activiate_quantifier(q); + } + + bool should_activiate_quantifier(quantifier* q) { + struct visit { + slice_solver& s; + bool m_all_visited = true; + visit(slice_solver& s) : s(s) {} + void operator()(func_decl* f) { + if (is_uninterp(f)) + m_all_visited &= s.m_used_funs.contains(f); + } + void operator()(ast* a) {} + }; + m_mark.reset(); + visit visitor(*this); + for (unsigned i = 0; i < q->get_num_patterns(); ++i) + for_each_ast(visitor, m_mark, q->get_pattern(i)); + return visitor.m_all_visited; + } + + void assert_expr(fml_t const & f) { + if (f.assumption) + s->assert_expr(f.formula, f.assumption); + else + s->assert_expr(f.formula); + } + + void activate_indices() { + if (m_new_idx.empty()) + return; + unsigned idx = m_new_idx[0]; + auto const& f0 = m_assertions[idx]; + if (f0.level < m_level) { + + // pop to f.level + // add m_new_idx within f.level + // replay push and assertions above f.level + s->pop(m_level - f0.level); + m_level = f0.level; + unsigned last_idx = idx; + for (unsigned idx : m_new_idx) { + // add only new assertions within lowest scope level. + auto const& f = m_assertions[idx]; + if (m_level != f.level) + break; + last_idx = idx; + assert_expr(f); + } + for (unsigned i = last_idx + 1; i < m_assertions.size(); ++i) { + // add all active assertions within other scope levels. + auto const& f = m_assertions[i]; + if (f0.level == f.level) + continue; + while (f.level > m_level) { + s->push(); + ++m_level; + } + if (f.active) + assert_expr(f); + } + } + else { + for (unsigned idx : m_new_idx) { + auto const& f = m_assertions[idx]; + while (f.level > m_level) { + s->push(); + ++m_level; + } + assert_expr(f); + } + } + } + + bool is_query(expr* a) { + return is_uninterp_const(a) && to_app(a)->get_decl()->get_name() == "@query"; + } + +public: + + slice_solver(solver* s) : + solver(s->get_manager()), + m(s->get_manager()), + s(s) { + } + + void assert_expr_core2(expr* t, expr* a) override { + if (!a) + assert_expr_core(t); + else { + unsigned i = m_assertions.size(); + m_assertions.push_back({expr_ref(t, m), expr_ref(a, m), false, m_assertions_lim.size()}); + add_occurs(i, t); + add_occurs(i, a); + if (is_query(a)) { + activate(i, t); + m_has_query = true; + } + } + } + + void assert_expr_core(expr* t) override { + unsigned i = m_assertions.size(); + m_assertions.push_back({expr_ref(t, m), expr_ref(nullptr, m), false, m_assertions_lim.size()}); + add_occurs(i, t); + } + + void push() override { + m_assertions_lim.push_back(m_assertions.size()); + m_occurs_lim.push_back(m_occurs_trail.size()); + m_used_funs_lim.push_back(m_used_funs_trail.size()); + } + + void pop(unsigned n) override { + unsigned old_sz = m_assertions_lim[m_assertions_lim.size() - n]; + for (unsigned i = m_assertions.size(); i-- > old_sz; ) { + auto const& f = m_assertions[i]; + if (f.level < m_level) { + s->pop(m_level - f.level); + m_level = f.level; + } + } + m_assertions_lim.shrink(m_assertions_lim.size() - n); + m_assertions.shrink(old_sz); + old_sz = m_occurs_lim[m_occurs_lim.size() - n]; + for (unsigned i = m_occurs_trail.size(); i-- > old_sz; ) { + auto f = m_occurs_trail[i]; + m_occurs[f].pop_back(); + } + m_occurs_lim.shrink(m_occurs_lim.size() - n); + m_occurs_trail.shrink(old_sz); + + old_sz = m_used_funs_lim[m_used_funs_lim.size() - n]; + for (unsigned i = m_used_funs_trail.size(); i-- > old_sz; ) { + auto f = m_used_funs_trail[i]; + m_used_funs.erase(f); + } + m_used_funs_lim.shrink(m_used_funs_lim.size() - n); + m_used_funs_trail.shrink(old_sz); + m_qhead = 0; + m_has_query = false; + } + + lbool check_sat_core(unsigned num_assumptions, expr* const* assumptions) override { + if (!m_has_query || num_assumptions > 0) + flush(); + return s->check_sat_core(num_assumptions, assumptions); + } + + void collect_statistics(statistics& st) const override { s->collect_statistics(st); } + + void get_model_core(model_ref& mdl) override { s->get_model_core(mdl); } + + proof* get_proof_core() override { return s->get_proof(); } + + solver* translate(ast_manager& m, params_ref const& p) override { + solver* new_s = s->translate(m, p); + solver* new_slice = alloc(slice_solver, new_s); + unsigned level = 0; + ast_translation tr(get_manager(), m); + for (auto & f : m_assertions) { + while (f.level > level) { + new_slice->push(); + ++level; + } + new_slice->assert_expr(tr(f.formula.get()), tr(f.assumption.get())); + } + return new_slice; + } + + void updt_params(params_ref const& p) override { s->updt_params(p); } + + model_converter_ref get_model_converter() const override { return s->get_model_converter(); } + + unsigned get_num_assertions() const override { return s->get_num_assertions(); } + expr* get_assertion(unsigned idx) const override { return s->get_assertion(idx); } + std::string reason_unknown() const override { return s->reason_unknown(); } + void set_reason_unknown(char const* msg) override { s->set_reason_unknown(msg); } + void get_labels(svector& r) override { s->get_labels(r); } + void get_unsat_core(expr_ref_vector& r) override { s->get_unsat_core(r); } + ast_manager& get_manager() const override { return s->get_manager(); } + void reset_params(params_ref const& p) override { s->reset_params(p); } + params_ref const& get_params() const override { return s->get_params(); } + void collect_param_descrs(param_descrs& r) override { s->collect_param_descrs(r); } + void push_params() override { s->push_params(); } + void pop_params() override { s->pop_params(); } + void set_produce_models(bool f) override { s->set_produce_models(f); } + void set_phase(expr* e) override { s->set_phase(e); } + void move_to_front(expr* e) override { s->move_to_front(e); } + phase* get_phase() override { return s->get_phase(); } + void set_phase(phase* p) override { s->set_phase(p); } + unsigned get_num_assumptions() const override { return s->get_num_assumptions(); } + expr* get_assumption(unsigned idx) const override { return s->get_assumption(idx); } + unsigned get_scope_level() const override { return s->get_scope_level(); } + void set_progress_callback(progress_callback* callback) override { s->set_progress_callback(callback); } + + lbool get_consequences(expr_ref_vector const& asms, expr_ref_vector const& vars, expr_ref_vector& consequences) override { + flush(); + return s->get_consequences(asms, vars, consequences); + } + + lbool check_sat_cc(expr_ref_vector const& cube, vector const& clauses) override { + flush(); + return check_sat_cc(cube, clauses); + } + + lbool find_mutexes(expr_ref_vector const& vars, vector& mutexes) override { + flush(); + return s->find_mutexes(vars, mutexes); + } + + lbool preferred_sat(expr_ref_vector const& asms, vector& cores) override { + flush(); + return s->preferred_sat(asms, cores); + } + + expr_ref_vector cube(expr_ref_vector& vars, unsigned backtrack_level) override { + flush(); + return s->cube(vars, backtrack_level); + } + + expr* congruence_root(expr* e) override { return s->congruence_root(e); } + expr* congruence_next(expr* e) override { return s->congruence_next(e); } + std::ostream& display(std::ostream& out, unsigned n, expr* const* assumptions) const override { + return s->display(out, n, assumptions); + } + void get_units_core(expr_ref_vector& units) override { s->get_units_core(units); } + expr_ref_vector get_trail(unsigned max_level) override { return s->get_trail(max_level); } + void get_levels(ptr_vector const& vars, unsigned_vector& depth) override { s->get_levels(vars, depth); } + + void register_on_clause(void* ctx, user_propagator::on_clause_eh_t& on_clause) override { + s->register_on_clause(ctx, on_clause); + } + + void user_propagate_init( + void* ctx, + user_propagator::push_eh_t& push_eh, + user_propagator::pop_eh_t& pop_eh, + user_propagator::fresh_eh_t& fresh_eh) override { + s->user_propagate_init(ctx, push_eh, pop_eh, fresh_eh); + } + void user_propagate_register_fixed(user_propagator::fixed_eh_t& fixed_eh) override { s->user_propagate_register_fixed(fixed_eh); } + void user_propagate_register_final(user_propagator::final_eh_t& final_eh) override { s->user_propagate_register_final(final_eh); } + void user_propagate_register_eq(user_propagator::eq_eh_t& eq_eh) override { s->user_propagate_register_eq(eq_eh); } + void user_propagate_register_diseq(user_propagator::eq_eh_t& diseq_eh) override { s->user_propagate_register_diseq(diseq_eh); } + void user_propagate_register_expr(expr* e) override { s->user_propagate_register_expr(e); } + void user_propagate_register_created(user_propagator::created_eh_t& r) override { s->user_propagate_register_created(r); } + void user_propagate_register_decide(user_propagator::decide_eh_t& r) override { s->user_propagate_register_decide(r); } + void user_propagate_initialize_value(expr* var, expr* value) override { s->user_propagate_initialize_value(var, value); } +}; + +solver * mk_slice_solver(solver * s) { + solver_params sp(s->get_params()); + if (sp.slice()) + return alloc(slice_solver, s); + else + return s; +} + diff --git a/src/solver/slice_solver.h b/src/solver/slice_solver.h new file mode 100644 index 000000000..78386ce15 --- /dev/null +++ b/src/solver/slice_solver.h @@ -0,0 +1,25 @@ +/*++ +Copyright (c) 2023 Microsoft Corporation + +Module Name: + + slice_solver.h + +Abstract: + + Implements a solver that slices assertions based on the query. + +Author: + + Nikolaj Bjorner (nbjorner) 2024-10-07 + +--*/ +#pragma once + +#include "util/params.h" + +class solver; +class solver_factory; + +solver * mk_slice_solver(solver * s); + From cfd00ad672dbe1334976c35867001e3f96f63692 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 8 Oct 2024 09:22:23 -0700 Subject: [PATCH 185/187] add slice solver option to command context --- src/cmd_context/cmd_context.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 59de003c8..577cc95b6 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -51,6 +51,7 @@ Notes: #include "solver/smt_logics.h" #include "cmd_context/basic_cmds.h" #include "cmd_context/cmd_context.h" +#include "solver/slice_solver.h" #include func_decls::func_decls(ast_manager & m, func_decl * f): @@ -2257,6 +2258,7 @@ void cmd_context::mk_solver() { params_ref p; m_params.get_solver_params(p, proofs_enabled, models_enabled, unsat_core_enabled); m_solver = (*m_solver_factory)(m(), p, proofs_enabled, models_enabled, unsat_core_enabled, m_logic); + m_solver = mk_slice_solver(m_solver.get()); } From 6bd46b0922a0c02dbf142c4ac3dd7b9cca6d0b4c Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 8 Oct 2024 19:40:37 -0700 Subject: [PATCH 186/187] fix #7363. Replay relevancy on unit literals that are re-asserted during backtracking. Signed-off-by: Nikolaj Bjorner --- src/smt/mam.cpp | 8 +++++--- src/smt/smt_context.cpp | 17 +++++++---------- src/smt/smt_context.h | 9 +++++++-- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/smt/mam.cpp b/src/smt/mam.cpp index 71eeb55cb..48d243771 100644 --- a/src/smt/mam.cpp +++ b/src/smt/mam.cpp @@ -3940,9 +3940,11 @@ namespace { } return; } - for (unsigned i = 0; i < num_bindings; i++) { - SASSERT(bindings[i]->get_generation() <= max_generation); - } + DEBUG_CODE( + for (unsigned i = 0; i < num_bindings; i++) { + SASSERT(bindings[i]->get_generation() <= max_generation); + }); + #endif unsigned min_gen = 0, max_gen = 0; m_interpreter.get_min_max_top_generation(min_gen, max_gen); diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 722782591..9ceee136f 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -71,7 +71,6 @@ namespace smt { m_l_internalized_stack(m), m_final_check_idx(0), m_cg_table(m), - m_units_to_reassert(m), m_conflict(null_b_justification), m_not_l(null_literal), m_conflict_resolution(mk_conflict_resolution(m, *this, m_dyn_ack_manager, p, m_assigned_literals, m_watches)), @@ -2186,7 +2185,7 @@ namespace smt { unsigned i = s.m_units_to_reassert_lim; unsigned sz = m_units_to_reassert.size(); for (; i < sz; i++) { - expr * unit = m_units_to_reassert.get(i); + expr* unit = m_units_to_reassert[i].m_unit.get(); cache_generation(unit, new_scope_lvl); } } @@ -2377,19 +2376,18 @@ namespace smt { unsigned i = units_to_reassert_lim; unsigned sz = m_units_to_reassert.size(); for (; i < sz; i++) { - expr * unit = m_units_to_reassert.get(i); + auto& [unit, sign, is_relevant] = m_units_to_reassert[i]; bool gate_ctx = true; internalize(unit, gate_ctx); bool_var v = get_bool_var(unit); - bool sign = m_units_to_reassert_sign[i] != 0; literal l(v, sign); assign(l, b_justification::mk_axiom()); + if (is_relevant) + mark_as_relevant(l); TRACE("reassert_units", tout << "reasserting #" << unit->get_id() << " " << sign << " @ " << m_scope_lvl << "\n";); } - if (at_base_level()) { - m_units_to_reassert.reset(); - m_units_to_reassert_sign.reset(); - } + if (at_base_level()) + m_units_to_reassert.reset(); } /** @@ -4310,8 +4308,7 @@ namespace smt { bool unit_sign = lits[0].sign(); while (m.is_not(unit, unit)) unit_sign = !unit_sign; - m_units_to_reassert.push_back(unit); - m_units_to_reassert_sign.push_back(unit_sign); + m_units_to_reassert.push_back({ expr_ref(unit, m), unit_sign, is_relevant(unit) }); TRACE("reassert_units", tout << "asserting " << mk_pp(unit, m) << " #" << unit->get_id() << " " << unit_sign << " @ " << m_scope_lvl << "\n";); } diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index afbfd0e85..715b28f23 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -71,6 +71,12 @@ namespace smt { enode_pp(enode* n, context const& ctx): ctx(ctx), n(n) {} }; + struct replay_unit { + expr_ref m_unit; + bool m_sign; + bool m_relevant; + }; + class context { friend class model_generator; friend class lookahead; @@ -183,8 +189,7 @@ namespace smt { clause_vector m_aux_clauses; clause_vector m_lemmas; vector m_clauses_to_reinit; - expr_ref_vector m_units_to_reassert; - svector m_units_to_reassert_sign; + vector m_units_to_reassert; literal_vector m_assigned_literals; typedef std::pair tmp_clause; vector m_tmp_clauses; From da614c65e58b8e97d6d0c7aaf3a1294bac8e6097 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 8 Oct 2024 19:56:57 -0700 Subject: [PATCH 187/187] remove m_level attribute, use s->get_scope_level directly --- src/solver/slice_solver.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/solver/slice_solver.cpp b/src/solver/slice_solver.cpp index 1158ef964..7c4e1fb82 100644 --- a/src/solver/slice_solver.cpp +++ b/src/solver/slice_solver.cpp @@ -40,7 +40,6 @@ class slice_solver : public solver { ptr_vector m_used_funs_trail; unsigned_vector m_used_funs_lim; bool m_has_query = false; - unsigned m_level = 0; ast_mark m_mark; @@ -210,18 +209,17 @@ class slice_solver : public solver { return; unsigned idx = m_new_idx[0]; auto const& f0 = m_assertions[idx]; - if (f0.level < m_level) { + if (f0.level < s->get_scope_level()) { // pop to f.level // add m_new_idx within f.level // replay push and assertions above f.level - s->pop(m_level - f0.level); - m_level = f0.level; + s->pop(s->get_scope_level() - f0.level); unsigned last_idx = idx; for (unsigned idx : m_new_idx) { // add only new assertions within lowest scope level. auto const& f = m_assertions[idx]; - if (m_level != f.level) + if (s->get_scope_level() != f.level) break; last_idx = idx; assert_expr(f); @@ -231,10 +229,9 @@ class slice_solver : public solver { auto const& f = m_assertions[i]; if (f0.level == f.level) continue; - while (f.level > m_level) { + while (f.level > s->get_scope_level()) s->push(); - ++m_level; - } + if (f.active) assert_expr(f); } @@ -242,10 +239,8 @@ class slice_solver : public solver { else { for (unsigned idx : m_new_idx) { auto const& f = m_assertions[idx]; - while (f.level > m_level) { + while (f.level > s->get_scope_level()) s->push(); - ++m_level; - } assert_expr(f); } } @@ -294,10 +289,8 @@ public: unsigned old_sz = m_assertions_lim[m_assertions_lim.size() - n]; for (unsigned i = m_assertions.size(); i-- > old_sz; ) { auto const& f = m_assertions[i]; - if (f.level < m_level) { - s->pop(m_level - f.level); - m_level = f.level; - } + if (f.level < s->get_scope_level()) + s->pop(s->get_scope_level() - f.level); } m_assertions_lim.shrink(m_assertions_lim.size() - n); m_assertions.shrink(old_sz);