z3-z3-4.13.0.src.math.lp.lp_settings.h Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
Abstract:
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#pragma once
#include "util/vector.h"
#include
#include
#include
#include
#include
#include
#include "util/stopwatch.h"
#include "util/statistics.h"
#include "util/params.h"
#include "math/lp/lp_utils.h"
#include "math/lp/lp_types.h"
namespace lp {
enum class column_type {
free_column = 0,
lower_bound = 1,
upper_bound = 2,
boxed = 3,
fixed = 4
};
inline std::ostream& operator<<(std::ostream& out, column_type const& t) {
switch (t) {
case column_type::free_column: return out << "free";
case column_type::lower_bound: return out << "lower";
case column_type::upper_bound: return out << "upper";
case column_type::boxed: return out << "boxed";
case column_type::fixed: return out << "fixed";
}
}
enum class simplex_strategy_enum {
tableau_rows,
tableau_costs
};
std::string column_type_to_string(column_type t);
enum class lp_status {
UNKNOWN,
INFEASIBLE,
TENTATIVE_UNBOUNDED,
UNBOUNDED,
TENTATIVE_DUAL_UNBOUNDED,
DUAL_UNBOUNDED,
OPTIMAL,
FEASIBLE,
TIME_EXHAUSTED,
EMPTY,
UNSTABLE,
CANCELLED
};
// when the ratio of the vector length to domain size to is greater than the return value we switch to solve_By_for_T_indexed_only
template
unsigned ratio_of_index_size_to_all_size() {
return 10;
}
const char* lp_status_to_string(lp_status status);
inline std::ostream& operator<<(std::ostream& out, lp_status status) {
return out << lp_status_to_string(status);
}
lp_status lp_status_from_string(std::string status);
class lp_resource_limit {
public:
virtual ~lp_resource_limit() = default;
virtual bool get_cancel_flag() = 0;
};
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() { reset(); }
void reset() { memset(this, 0, sizeof(*this)); }
void collect_statistics(::statistics& st) const {
st.update("arith-factorizations", m_num_factorizations);
st.update("arith-make-feasible", m_make_feasible);
st.update("arith-max-columns", m_max_cols);
st.update("arith-max-rows", m_max_rows);
st.update("arith-gcd-calls", m_gcd_calls);
st.update("arith-gcd-conflict", m_gcd_conflicts);
st.update("arith-cube-calls", m_cube_calls);
st.update("arith-cube-success", m_cube_success);
st.update("arith-patches", m_patches);
st.update("arith-patches-success", m_patches_success);
st.update("arith-hnf-calls", m_hnf_cutter_calls);
st.update("arith-hnf-cuts", m_hnf_cuts);
st.update("arith-gomory-cuts", m_gomory_cuts);
st.update("arith-horner-calls", m_horner_calls);
st.update("arith-horner-conflicts", m_horner_conflicts);
st.update("arith-horner-cross-nested-forms", m_cross_nested_forms);
st.update("arith-grobner-calls", m_grobner_calls);
st.update("arith-grobner-conflicts", m_grobner_conflicts);
st.update("arith-offset-eqs", m_offset_eqs);
st.update("arith-fixed-eqs", m_fixed_eqs);
st.update("arith-nla-add-bounds", m_nla_add_bounds);
st.update("arith-nla-propagate-bounds", m_nla_propagate_bounds);
st.update("arith-nla-propagate-eq", m_nla_propagate_eq);
st.update("arith-nla-lemmas", m_nla_lemmas);
st.update("arith-nra-calls", m_nra_calls);
st.update("arith-bounds-improvements", m_nla_bounds_improvements);
}
};
struct lp_settings {
private:
class default_lp_resource_limit : public lp_resource_limit {
lp_settings& m_settings;
stopwatch m_sw;
public:
default_lp_resource_limit(lp_settings& s): m_settings(s) {
m_sw.start();
}
bool get_cancel_flag() override {
return (m_sw.get_current_seconds() > m_settings.time_limit);
}
};
default_lp_resource_limit m_default_resource_limit;
lp_resource_limit* m_resource_limit = nullptr;
// used for debug output
std::ostream* m_debug_out = nullptr;
// used for messages, for example, the computation progress messages
std::ostream* m_message_out = nullptr;
statistics m_stats;
random_gen m_rand;
public:
void updt_params(params_ref const& p);
bool enable_hnf() const { return m_enable_hnf; }
unsigned nlsat_delay() const { return m_nlsat_delay; }
bool int_run_gcd_test() const { return m_int_run_gcd_test; }
bool& int_run_gcd_test() { return m_int_run_gcd_test; }
unsigned reps_in_scaler = 20;
int c_partial_pivoting = 10; // this is the constant c from page 410
unsigned depth_of_rook_search = 4;
bool using_partial_pivoting = true;
unsigned percent_of_entering_to_check = 5; // we try to find a profitable column in a percentage of the columns
bool use_scaling = true;
unsigned max_number_of_iterations_with_no_improvements = 2000000;
double time_limit; // the maximum time limit of the total run time in seconds
// end of dual section
bool m_bound_propagation = true;
bool presolve_with_double_solver_for_lar = true;
simplex_strategy_enum m_simplex_strategy;
int report_frequency = 1000;
bool print_statistics = false;
unsigned column_norms_update_frequency = 12000;
bool scale_with_ratio = true;
unsigned max_row_length_for_bound_propagation = 300;
bool backup_costs = true;
unsigned column_number_threshold_for_using_lu_in_lar_solver = 4000;
unsigned m_int_gomory_cut_period = 4;
unsigned m_int_find_cube_period = 4;
private:
unsigned m_hnf_cut_period = 4;
bool m_int_run_gcd_test = true;
public:
unsigned limit_on_rows_for_hnf_cutter = 75;
unsigned limit_on_columns_for_hnf_cutter = 150;
private:
unsigned m_nlsat_delay;
bool m_enable_hnf = true;
bool m_print_external_var_name = false;
bool m_propagate_eqs = false;
public:
bool print_external_var_name() const { return m_print_external_var_name; }
bool propagate_eqs() const { return m_propagate_eqs;}
unsigned hnf_cut_period() const { return m_hnf_cut_period; }
void set_hnf_cut_period(unsigned period) { m_hnf_cut_period = period; }
unsigned random_next() { return m_rand(); }
unsigned random_next(unsigned u ) { return m_rand(u); }
void set_random_seed(unsigned s) { m_rand.set_seed(s); }
bool bound_progation() const {
return m_bound_propagation;
}
bool& bound_propagation() { return m_bound_propagation; }
lp_settings() : m_default_resource_limit(*this),
m_resource_limit(&m_default_resource_limit),
m_debug_out(&std::cout),
m_message_out(&std::cout),
time_limit ( std::numeric_limits::max()), // the maximum time limit of the total run time in seconds
// dual section
m_simplex_strategy(simplex_strategy_enum::tableau_rows)
{}
void set_resource_limit(lp_resource_limit& lim) { m_resource_limit = &lim; }
bool get_cancel_flag() const { return m_resource_limit->get_cancel_flag(); }
void set_debug_ostream(std::ostream* out) { m_debug_out = out; }
void set_message_ostream(std::ostream* out) { m_message_out = out; }
std::ostream* get_debug_ostream() { return m_debug_out; }
std::ostream* get_message_ostream() { return m_message_out; }
statistics& stats() { return m_stats; }
statistics const& stats() const { return m_stats; }
// the method of lar solver to use
simplex_strategy_enum simplex_strategy() const { return m_simplex_strategy; }
simplex_strategy_enum & simplex_strategy() { return m_simplex_strategy; }
bool use_tableau_rows() const { return m_simplex_strategy == simplex_strategy_enum::tableau_rows; }
#ifdef Z3DEBUG
static unsigned ddd; // used for debugging
#endif
}; // end of lp_settings class
#define LP_OUT(_settings_, _msg_) { if (_settings_.get_debug_ostream()) { *_settings_.get_debug_ostream() << _msg_; } }
template
std::string T_to_string(const T & t) {
std::ostringstream strs;
strs << t;
return strs.str();
}
inline std::string T_to_string(const numeric_pair & t) {
std::ostringstream strs;
double r = (t.x + t.y / mpq(1000)).get_double();
strs << r;
return strs.str();
}
inline std::string T_to_string(const mpq & t) {
std::ostringstream strs;
strs << t;
return strs.str();
}
template
bool vectors_are_equal(T * a, vector &b, unsigned n);
template
bool vectors_are_equal(const vector & a, const buffer &b);
template
bool vectors_are_equal(const vector & a, const vector &b);
template
bool vectors_are_equal_(const T & a, const K &b) {
if (a.size() != b.size())
return false;
for (unsigned i = 0; i < a.size(); i++){
if (a[i] != b[i]) {
return false;
}
}
return true;
}
template
T abs (T const & v) { return v >= zero_of_type() ? v : -v; }
template
X max_abs_in_vector(vector& t){
X r(zero_of_type());
for (auto & v : t)
r = std::max(abs(v) , r);
return r;
}
inline void print_blanks(int n, std::ostream & out) {
while (n--) {out << ' '; }
}
// after a push of the last element we ensure that the vector increases
// we also suppose that before the last push the vector was increasing
inline void ensure_increasing(vector & v) {
lp_assert(v.size() > 0);
unsigned j = v.size() - 1;
for (; j > 0; j-- )
if (v[j] <= v[j - 1]) {
// swap
unsigned t = v[j];
v[j] = v[j-1];
v[j-1] = t;
} else {
break;
}
}
inline static bool is_rational(const impq & n) { return is_zero(n.y); }
inline static mpq fractional_part(const impq & n) {
lp_assert(is_rational(n));
return n.x - floor(n.x);
}
inline static mpq fractional_part(const mpq & n) {
return n - floor(n);
}
#if Z3DEBUG
bool D();
#endif
}