3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 17:15:31 +00:00

convert reduce-args to a simplifier

- convert reduce-args to a simplifier. Currently exposed as reduce-args2 tactic until the old tactic code gets removed.
- bug fixes in model_reconstruction trail
  - allow multiple defs to be added with same pool of removed formulas
  - fix tracking of function symbols instead of expressions to filter replay
- add nla_divisions to track (cheap) divisibility lemmas.
-
This commit is contained in:
Nikolaj Bjorner 2023-01-28 20:12:14 -08:00
parent 246d6f7b77
commit 8ea49eed8e
23 changed files with 740 additions and 92 deletions

View file

@ -34,6 +34,7 @@ z3_add_component(lp
nla_basics_lemmas.cpp
nla_common.cpp
nla_core.cpp
nla_divisions.cpp
nla_grobner.cpp
nla_intervals.cpp
nla_monotone_lemmas.cpp

View file

@ -30,6 +30,7 @@ core::core(lp::lar_solver& s, reslimit & lim) :
m_order(this),
m_monotone(this),
m_powers(*this),
m_divisions(*this),
m_intervals(this, lim),
m_monomial_bounds(this),
m_horner(this),
@ -136,6 +137,11 @@ void core::add_monic(lpvar v, unsigned sz, lpvar const* vs) {
}
m_emons.add(v, m_add_buffer);
}
void core::add_idivision(lpvar r, lpvar x, lpvar y) {
m_divisions.add_idivision(r, x, y);
}
void core::push() {
TRACE("nla_solver_verbose", tout << "\n";);
@ -1519,6 +1525,9 @@ lbool core::check(vector<lemma>& l_vec) {
if (l_vec.empty() && !done())
m_basics.basic_lemma(false);
if (l_vec.empty() && !done())
m_divisions.check(l_vec);
#if 0
if (l_vec.empty() && !done() && !run_horner)
m_horner.horner_lemmas();

View file

@ -20,6 +20,7 @@
#include "math/lp/nla_monotone_lemmas.h"
#include "math/lp/nla_grobner.h"
#include "math/lp/nla_powers.h"
#include "math/lp/nla_divisions.h"
#include "math/lp/emonics.h"
#include "math/lp/nla_settings.h"
#include "math/lp/nex.h"
@ -88,6 +89,7 @@ class core {
order m_order;
monotone m_monotone;
powers m_powers;
divisions m_divisions;
intervals m_intervals;
monomial_bounds m_monomial_bounds;
nla_settings m_nla_settings;
@ -199,8 +201,10 @@ public:
void deregister_monic_from_tables(const monic & m, unsigned i);
void add_monic(lpvar v, unsigned sz, lpvar const* vs);
void add_idivision(lpvar r, lpvar x, lpvar y);
void push();
void pop(unsigned n);
trail_stack& trail() { return m_emons.get_trail_stack(); }
rational mon_value_by_vars(unsigned i) const;
rational product_value(const monic & m) const;

View file

@ -0,0 +1,65 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
nla_divisions.cpp
Author:
Lev Nachmanson (levnach)
Nikolaj Bjorner (nbjorner)
Description:
Check divisions
--*/
#include "math/lp/nla_core.h"
namespace nla {
void divisions::add_idivision(lpvar r, lpvar x, lpvar y) {
m_idivisions.push_back({r, x, y});
m_core.trail().push(push_back_vector(m_idivisions));
}
typedef lp::lar_term term;
// y1 >= y2 > 0 & x1 <= x2 => x1/y1 <= x2/y2
// y2 <= y1 < 0 & x1 >= x2 => x1/y1 <= x2/y2
void divisions::check(vector<lemma>& lemmas) {
core& c = m_core;
if (c.use_nra_model())
return;
for (auto const & [r, x, y] : m_idivisions) {
auto xval = c.val(x);
auto yval = c.val(y);
auto rval = c.val(r);
if (!c.var_is_int(x))
continue;
if (yval == 0)
continue;
// idiv semantics
if (rval == div(xval, yval))
continue;
for (auto const& [r2, x2, y2] : m_idivisions) {
if (r2 == r)
continue;
auto x2val = c.val(x2);
auto y2val = c.val(y2);
auto r2val = c.val(r2);
if (yval >= y2val && y2val > 0 && xval <= x2val && rval > r2val) {
new_lemma lemma(c, "y1 >= y2 > 0 & x1 <= x2 => x1/y1 <= x2/y2");
lemma |= ineq(term(y, rational(-1), y2), llc::LT, rational::zero());
lemma |= ineq(y2, llc::LE, rational::zero());
lemma |= ineq(term(x, rational(-1), x2), llc::GT, rational::zero());
lemma |= ineq(term(r, rational(-1), r2), llc::LE, rational::zero());
return;
}
}
}
}
}

View file

@ -0,0 +1,31 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
nla_divisions.h
Author:
Lev Nachmanson (levnach)
Nikolaj Bjorner (nbjorner)
Description:
Check division constraints.
--*/
#include "math/lp/nla_types.h"
namespace nla {
class core;
class divisions {
core& m_core;
vector<std::tuple<lpvar, lpvar, lpvar>> m_idivisions;
public:
divisions(core& c):m_core(c) {}
void add_idivision(lpvar r, lpvar x, lpvar y);
void check(vector<lemma>&);
};
}

View file

@ -22,6 +22,10 @@ namespace nla {
void solver::add_monic(lpvar v, unsigned sz, lpvar const* vs) {
m_core->add_monic(v, sz, vs);
}
void solver::add_idivision(lpvar r, lpvar x, lpvar y) {
m_core->add_idivision(r, x, y);
}
bool solver::is_monic_var(lpvar v) const {
return m_core->is_monic_var(v);

View file

@ -25,6 +25,7 @@ namespace nla {
core* m_core;
public:
void add_monic(lpvar v, unsigned sz, lpvar const* vs);
void add_idivision(lpvar r, lpvar x, lpvar y);
solver(lp::lar_solver& s, reslimit& limit);
~solver();
nla_settings& settings();

View file

@ -68,8 +68,7 @@ class var_eqs {
T* m_merge_handler;
union_find<var_eqs> m_uf;
lp::incremental_vector<std::pair<signed_var, signed_var>>
m_trail;
lp::incremental_vector<std::pair<signed_var, signed_var>> m_trail;
vector<svector<eq_edge>> m_eqs; // signed_var.index() -> the edges adjacent to signed_var.index()
trail_stack m_stack;