#pragma once
#include "math/lp/nla_common.h"
#include "math/lp/nla_intervals.h"
#include "util/uint_set.h"
namespace nla {
class core;
class monomial_bounds : common {
dep_intervals& dep;
struct bound_proof {
monic const& product;
lpvar source = UINT_MAX;
lp::lar_term const* term = nullptr;
};
bool tighten_lp_bound(bound_proof const& proof, dep_interval const &range, lpvar v, unsigned p);
bool tighten_lp_upper_bound(bound_proof const& proof, dep_interval const& range, lpvar v, unsigned p);
bool tighten_lp_lower_bound(bound_proof const& proof, dep_interval const& range, lpvar v, unsigned p);
bool tighten_lp_bound(bound_proof const& proof, dep_interval &mi, lpvar v, unsigned power, dep_interval &product);
void propagate_lp_bound(bound_proof const& proof, lpvar v, lp::lconstraint_kind cmp, rational const &q, u_dependency *d);
u_dependency* capture_monomial(monic const& m, lp::evidence_manager::rule kind,
lp::evidence_manager::fact const& conclusion, u_dependency* support, lpvar target,
lpvar source = UINT_MAX, lp::lar_term const* term = nullptr);
bool should_propagate_lower(dep_interval const& range, lpvar v, unsigned p);
bool should_propagate_upper(dep_interval const& range, lpvar v, unsigned p);
void var2interval(lpvar v, scoped_dep_interval& i);
bool is_too_big(mpq const& q) const;
void compute_product(unsigned start, monic const& m, scoped_dep_interval& i);
bool generate_lemma(monic const& m);
bool tighten_lp(monic const& m);
bool propagate_fixed_to_zero(monic const& m, lpvar fixed_to_zero);
bool propagate_fixed(monic const& m, rational const& k);
bool propagate_nonfixed(monic const& m, rational const& k, lpvar w);
u_dependency* explain_fixed(monic const& m, rational const& k);
lp::explanation get_explanation(u_dependency* dep);
bool propagate_shared_factor(monic const& m);
bool propagate_binomial_sign(monic const& m);
void analyze_monomial(monic const& m, unsigned& num_free, lpvar& free_v, unsigned& power) const;
bool is_free(lpvar v) const;
bool is_zero(lpvar v) const;
bool add_lemma();
bool propagate_linear_bound(monic & m);
bool linearize(monic const& m, lpvar w, lpvar fixed_to_zero);
bool is_linear(monic const& m, lpvar& w, lpvar & fixed_to_zero);
rational fixed_var_product(monic const& m, lpvar w);
struct mm_gain {
bool unbounded = true; rational min_gain = rational::minus_one();
lp::impq max_gain;
};
lpvar mm_basic_in_row(unsigned row) const;
bool mm_safe_gain(mm_gain const& g) const;
mm_gain mm_init_gains(lpvar x, bool inc) const;
bool mm_update_gains(bool inc, lpvar x_i, rational const& a_ij, mm_gain& g) const;
bool mm_pick_var_to_leave(lpvar x_j, bool inc, rational& a_ij, mm_gain& g, lpvar& x_i) const;
bool mm_move_to_bound(lpvar x_i, bool inc, unsigned& best_efforts);
void mm_update_value(lpvar j, lp::impq const& delta);
bool mm_optimize(lpvar v, bool maximize, rational& opt_value);
u_dependency* mm_dep_from_row(lpvar v, bool maximize);
public:
monomial_bounds(core* core);
void generate_lemmas();
bool tighten_lp_bounds();
bool propagate_linear_bounds();
bool propagate_changed_bounds();
bool propagate_violated_linear_monomials();
bool optimize_nl_bounds();
u_dependency* improve_bound(lpvar j, bool is_lower, rational& bound);
};
}