3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-05-02 21:37:02 +00:00
z3/src/math/lp/horner.cpp
Nikolaj Bjorner 5e3df9ee77
Arith min max (#6864)
* prepare for dependencies

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* snapshot

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* more refactoring

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* more refactoring

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* build

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* pass in u_dependency_manager

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* address NYIs

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* more refactoring names

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* eq_explanation update

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* add outline of bounds improvement functionality

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* fix unit tests

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* remove unused structs

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* more bounds

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* more bounds

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* convert more internals to use u_dependency instead of constraint_index

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* convert more internals to use u_dependency instead of constraint_index

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* remember to push/pop scopes

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* use the main function for updating bounds

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* na

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* na

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* remove reset of shared dep manager

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* disable improve-bounds, add statistics

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

---------

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2023-08-19 17:44:09 -07:00

133 lines
3.7 KiB
C++

/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Nikolaj Bjorner (nbjorner)
Lev Nachmanson (levnach)
Revision History:
--*/
#include "math/lp/horner.h"
#include "math/lp/nla_core.h"
#include "math/lp/lp_utils.h"
#include "math/lp/cross_nested.h"
namespace nla {
typedef intervals::interval interv;
horner::horner(core * c) : common(c), m_row_sum(m_nex_creator) {}
template <typename T>
bool horner::row_has_monomial_to_refine(const T& row) const {
for (const auto& p : row) {
if (c().m_to_refine.contains(p.var()))
return true;
}
return false;
}
// Returns true if the row has at least two monomials sharing a variable
template <typename T>
bool horner::row_is_interesting(const T& row) const {
TRACE("nla_solver_details", c().print_row(row, tout););
if (row.size() > c().params().arith_nl_horner_row_length_limit()) {
TRACE("nla_solver_details", tout << "disregard\n";);
return false;
}
SASSERT(row_has_monomial_to_refine(row));
c().clear_active_var_set();
for (const auto& p : row) {
lpvar j = p.var();
if (!c().is_monic_var(j)) {
if (c().active_var_set_contains(j))
return true;
c().insert_to_active_var_set(j);
continue;
}
auto & m = c().emons()[j];
for (lpvar k : m.vars()) {
if (c().active_var_set_contains(k))
return true;
}
for (lpvar k : m.vars()) {
c().insert_to_active_var_set(k);
}
}
return false;
}
bool horner::lemmas_on_expr(cross_nested& cn, nex_sum* e) {
TRACE("nla_horner", tout << "e = " << *e << "\n";);
cn.run(e);
return cn.done();
}
template <typename T>
bool horner::lemmas_on_row(const T& row) {
SASSERT (row_is_interesting(row));
c().clear_active_var_set();
u_dependency* dep = nullptr;
create_sum_from_row(row, m_nex_creator, m_row_sum, dep);
c().set_active_vars_weights(m_nex_creator); // without this call the comparisons will be incorrect
nex* e = m_nex_creator.simplify(m_row_sum.mk());
TRACE("nla_horner", tout << "e = " << * e << "\n";);
if (e->get_degree() < 2)
return false;
if (!e->is_sum())
return false;
cross_nested cn(
[this, dep](const nex* n) { return c().m_intervals.check_nex(n, dep); },
[this](unsigned j) { return c().var_is_fixed(j); },
[this]() { return c().random(); }, m_nex_creator);
bool ret = lemmas_on_expr(cn, to_sum(e));
c().m_intervals.get_dep_intervals().reset(); // clean the memory allocated by the interval bound dependencies
return ret;
}
bool horner::horner_lemmas() {
if (!c().params().arith_nl_horner()) {
TRACE("nla_solver", tout << "not generating horner lemmas\n";);
return false;
}
c().lp_settings().stats().m_horner_calls++;
const auto& matrix = c().lra.A_r();
// choose only rows that depend on m_to_refine variables
std::set<unsigned> rows_to_check;
for (lpvar j : c().m_to_refine) {
for (auto & s : matrix.m_columns[j])
rows_to_check.insert(s.var());
}
c().clear_active_var_set();
svector<unsigned> rows;
for (unsigned i : rows_to_check) {
if (row_is_interesting(matrix.m_rows[i]))
rows.push_back(i);
}
unsigned r = c().random();
unsigned sz = rows.size();
bool conflict = false;
for (unsigned i = 0; i < sz && !conflict; i++) {
m_row_index = rows[(i + r) % sz];
if (lemmas_on_row(matrix.m_rows[m_row_index])) {
c().lp_settings().stats().m_horner_conflicts++;
conflict = true;
}
}
return conflict;
}
}