3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-27 19:05:51 +00:00

outline for monomial bound propagation

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-05-13 10:37:46 -07:00
parent 127ef59ce4
commit bda29ca26a
6 changed files with 148 additions and 0 deletions

View file

@ -30,6 +30,7 @@ z3_add_component(lp
lp_utils.cpp
matrix.cpp
mon_eq.cpp
monomial_bounds.cpp
nex_creator.cpp
nla_basics_lemmas.cpp
nla_common.cpp

View file

@ -0,0 +1,82 @@
/*++
Copyright (c) 2020 Microsoft Corporation
Author:
Nikolaj Bjorner (nbjorner)
Lev Nachmanson (levnach)
--*/
#pragma once
#include "math/lp/monomial_bounds.h"
#include "math/lp/nla_core.h"
#include "math/lp/nla_intervals.h"
namespace nla {
monomial_bounds::monomial_bounds(core* c):common(c) {}
bool monomial_bounds::operator()() {
bool propagated = false;
for (lpvar v : c().m_to_refine) {
monic const& m = c().emons()[v];
if (propagate_up(m))
propagated = true;
}
return propagated;
}
bool monomial_bounds::propagate_up(monic const& m) {
auto & intervals = c().m_intervals;
auto & dep_intervals = intervals.get_dep_intervals();
scoped_dep_interval product(dep_intervals), di(dep_intervals);
lpvar v = m.vars()[0];
var2interval(v, product);
for (unsigned i = 1; i < m.size(); ++i) {
var2interval(m.vars()[i], di);
dep_intervals.mul(product, di, product);
}
if (dep_intervals.is_below(product, c().val(m.var()))) {
lp::explanation ex;
dep_intervals.get_upper_dep(product, ex);
new_lemma lemma(c(), "propagate up - upper bound of product is below value");
lemma &= ex;
auto const& upper = dep_intervals.upper(product);
auto cmp = dep_intervals.upper_is_open(product) ? llc::LT : llc::LE;
lemma |= ineq(m.var(), cmp, upper);
return true;
}
else if (dep_intervals.is_above(product, c().val(m.var()))) {
lp::explanation ex;
dep_intervals.get_lower_dep(product, ex);
new_lemma lemma(c(), "propagate up - lower bound of product is above value");
lemma &= ex;
auto const& lower = dep_intervals.upper(product);
auto cmp = dep_intervals.lower_is_open(product) ? llc::GT : llc::GE;
lemma |= ineq(m.var(), cmp, lower);
return true;
}
else {
return false;
}
}
void monomial_bounds::var2interval(lpvar v, scoped_dep_interval& i) {
auto & intervals = c().m_intervals;
auto & dep_intervals = intervals.get_dep_intervals();
lp::constraint_index ci;
rational bound;
bool is_strict;
if (c().has_lower_bound(v, ci, bound, is_strict)) {
dep_intervals.set_lower_is_open(i, is_strict);
dep_intervals.set_lower(i, bound);
dep_intervals.set_lower_dep(i, dep_intervals.mk_leaf(ci));
}
if (c().has_upper_bound(v, ci, bound, is_strict)) {
dep_intervals.set_upper_is_open(i, is_strict);
dep_intervals.set_upper(i, bound);
dep_intervals.set_upper_dep(i, dep_intervals.mk_leaf(ci));
}
}
}

View file

@ -0,0 +1,27 @@
/*++
Copyright (c) 2020 Microsoft Corporation
Author:
Nikolaj Bjorner (nbjorner)
Lev Nachmanson (levnach)
--*/
#pragma once
#include "math/lp/nla_common.h"
#include "math/lp/nla_intervals.h"
#include "math/lp/nex.h"
#include "math/lp/cross_nested.h"
#include "math/lp/u_set.h"
namespace nla {
class core;
class monomial_bounds : common {
void var2interval(lpvar v, scoped_dep_interval& i);
bool propagate_up(monic const& m);
public:
monomial_bounds(core* core);
bool operator()();
};
}

View file

@ -321,6 +321,13 @@ public:
}
const rational& get_upper_bound(unsigned j) const;
const rational& get_lower_bound(unsigned j) const;
bool has_lower_bound(lp::var_index var, lp::constraint_index& ci, lp::mpq& value, bool& is_strict) const {
return m_lar_solver.has_lower_bound(var, ci, value, is_strict);
}
bool has_upper_bound(lp::var_index var, lp::constraint_index& ci, lp::mpq& value, bool& is_strict) const {
return m_lar_solver.has_upper_bound(var, ci, value, is_strict);
}
bool zero_is_an_inner_point_of_bounds(lpvar j) const;
bool var_is_int(lpvar j) const { return m_lar_solver.column_is_int(j); }