3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-13 12:28:44 +00:00

rp precise

This commit is contained in:
Lev Nachmanson 2023-03-07 08:20:32 -08:00
parent 569f5be91f
commit 9ec82632a3
15 changed files with 48 additions and 350 deletions

View file

@ -88,7 +88,6 @@ template <typename T, typename X> T core_solver_pretty_printer<T, X>::current_co
}
template <typename T, typename X> void core_solver_pretty_printer<T, X>::init_m_A_and_signs() {
if (numeric_traits<T>::precise() ) {
for (unsigned column = 0; column < ncols(); column++) {
vector<T> t(nrows(), zero_of_type<T>());
for (const auto & c : m_core_solver.m_A.m_columns[column]){
@ -115,8 +114,7 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::init_m_
name);
m_rs[row] += t[row] * m_core_solver.m_x[column];
}
}
}
}
}
template <typename T, typename X> void core_solver_pretty_printer<T, X>::init_column_widths() {

View file

@ -281,9 +281,9 @@ namespace lp {
unsigned m = A_r().row_count();
clean_popped_elements(m, m_rows_with_changed_bounds);
clean_inf_set_of_r_solver_after_pop();
lp_assert(m_settings.simplex_strategy() == simplex_strategy_enum::undecided ||
( m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()));
lp_assert(
m_settings.simplex_strategy() == simplex_strategy_enum::undecided ||
m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau());
m_constraints.pop(k);
m_term_count.pop(k);
@ -627,10 +627,6 @@ namespace lp {
m_rows_with_changed_bounds.insert(rid);
}
void lar_solver::detect_rows_of_bound_change_column_for_nbasic_column(unsigned j) {
lp_assert(false);
}
void lar_solver::detect_rows_of_bound_change_column_for_nbasic_column_tableau(unsigned j) {
@ -676,20 +672,16 @@ namespace lp {
}
void lar_solver::change_basic_columns_dependend_on_a_given_nb_column(unsigned j, const numeric_pair<mpq>& delta) {
{
for (const auto& c : A_r().m_columns[j]) {
unsigned bj = m_mpq_lar_core_solver.m_r_basis[c.var()];
if (tableau_with_costs()) {
m_basic_columns_with_changed_cost.insert(bj);
}
m_mpq_lar_core_solver.m_r_solver.add_delta_to_x_and_track_feasibility(bj, -A_r().get_val(c) * delta);
TRACE("change_x_del",
tout << "changed basis column " << bj << ", it is " <<
(m_mpq_lar_core_solver.m_r_solver.column_is_feasible(bj) ? "feas" : "inf") << std::endl;);
}
for (const auto& c : A_r().m_columns[j]) {
unsigned bj = m_mpq_lar_core_solver.m_r_basis[c.var()];
if (tableau_with_costs()) {
m_basic_columns_with_changed_cost.insert(bj);
}
m_mpq_lar_core_solver.m_r_solver.add_delta_to_x_and_track_feasibility(bj, -A_r().get_val(c) * delta);
TRACE("change_x_del",
tout << "changed basis column " << bj << ", it is " <<
(m_mpq_lar_core_solver.m_r_solver.column_is_feasible(bj) ? "feas" : "inf") << std::endl;);
}
}
void lar_solver::update_x_and_inf_costs_for_column_with_changed_bounds(unsigned j) {
@ -819,19 +811,6 @@ namespace lp {
A.set(last_row, basis_j, mpq(1));
}
template <typename U, typename V>
void lar_solver::create_matrix_A(static_matrix<U, V>& matr) {
lp_assert(false); // not implemented
/*
unsigned m = number_or_nontrivial_left_sides();
unsigned n = m_vec_of_canonic_left_sides.size();
if (matr.row_count() == m && matr.column_count() == n)
return;
matr.init_empty_matrix(m, n);
copy_from_mpq_matrix(matr);
*/
}
template <typename U, typename V>
void lar_solver::copy_from_mpq_matrix(static_matrix<U, V>& matr) {
matr.m_rows.resize(A_r().row_count());

View file

@ -205,10 +205,9 @@ class lar_solver : public column_namer {
void set_lower_bound_witness(var_index j, constraint_index ci);
void substitute_terms_in_linear_expression( const vector<std::pair<mpq, var_index>>& left_side_with_terms,
vector<std::pair<mpq, var_index>> &left_side) const;
void detect_rows_of_bound_change_column_for_nbasic_column(unsigned j);
void detect_rows_of_bound_change_column_for_nbasic_column_tableau(unsigned j);
bool use_tableau_costs() const;
void detect_rows_of_column_with_bound_change(unsigned j);
bool tableau_with_costs() const;
bool costs_are_used() const;
void change_basic_columns_dependend_on_a_given_nb_column(unsigned j, const numeric_pair<mpq> & delta);

View file

@ -43,7 +43,6 @@ template bool lp::lp_core_solver_base<double, double>::print_statistics_with_ite
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &);
template void lp::lp_core_solver_base<double, double>::restore_x(unsigned int, double const&);
template void lp::lp_core_solver_base<double, double>::set_non_basic_x_to_correct_bounds();
template void lp::lp_core_solver_base<double, double>::solve_Ax_eq_b();
template void lp::lp_core_solver_base<double, double>::add_delta_to_entering(unsigned int, const double&);
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::basis_heading_is_correct() const ;
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::column_is_dual_feasible(unsigned int) const;
@ -51,7 +50,6 @@ template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::fill_reduced_costs_from
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &);
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::restore_x(unsigned int, lp::mpq const&);
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::set_non_basic_x_to_correct_bounds();
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::solve_Ax_eq_b();
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::add_delta_to_entering(unsigned int, const lp::mpq&);
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::init();
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::init_basis_heading_and_non_basic_columns_vector();
@ -61,7 +59,6 @@ template lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::lp_core_s
const vector<lp::numeric_pair<lp::mpq> >&,
const vector<lp::numeric_pair<lp::mpq> >&);
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::print_statistics_with_cost_and_check_that_the_time_is_over(lp::numeric_pair<lp::mpq>, std::ostream&);
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_Ax_eq_b();
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::add_delta_to_entering(unsigned int, const lp::numeric_pair<lp::mpq>&);
template lp::lp_core_solver_base<lp::mpq, lp::mpq>::lp_core_solver_base(

View file

@ -238,11 +238,11 @@ public:
}
bool below_bound(const X & x, const X & bound) const {
return precise()? x < bound : below_bound_numeric<X>(x, bound, m_settings.primal_feasibility_tolerance);
return x < bound ;
}
bool above_bound(const X & x, const X & bound) const {
return precise()? x > bound : above_bound_numeric<X>(x, bound, m_settings.primal_feasibility_tolerance);
return x > bound ;
}
bool x_below_low_bound(unsigned p) const {
@ -323,9 +323,6 @@ public:
void find_error_in_BxB(vector<X>& rs);
// recalculates the projection of x to B, such that Ax = b, whereab is the right side
void solve_Ax_eq_b();
bool snap_non_basic_x_to_bound() {
bool ret = false;
for (unsigned j : non_basis())
@ -628,8 +625,6 @@ public:
bool pivot_column_tableau(unsigned j, unsigned row_index);
bool divide_row_by_pivot(unsigned pivot_row, unsigned pivot_col);
bool precise() const { return numeric_traits<T>::precise(); }
simplex_strategy_enum simplex_strategy() const { return
m_settings.simplex_strategy();
}

View file

@ -233,18 +233,12 @@ column_is_dual_feasible(unsigned j) const {
}
template <typename T, typename X> bool lp_core_solver_base<T, X>::
d_is_not_negative(unsigned j) const {
if (numeric_traits<T>::precise()) {
return m_d[j] >= numeric_traits<T>::zero();
}
return m_d[j] > -T(0.00001);
return m_d[j] >= numeric_traits<T>::zero();
}
template <typename T, typename X> bool lp_core_solver_base<T, X>::
d_is_not_positive(unsigned j) const {
if (numeric_traits<T>::precise()) {
return m_d[j] <= numeric_traits<T>::zero();
}
return m_d[j] < T(0.00001);
return m_d[j] <= numeric_traits<T>::zero();
}
@ -319,7 +313,6 @@ template <typename T, typename X> bool lp_core_solver_base<T, X>::inf_set_is_cor
template <typename T, typename X> bool lp_core_solver_base<T, X>::
divide_row_by_pivot(unsigned pivot_row, unsigned pivot_col) {
lp_assert(numeric_traits<T>::precise());
int pivot_index = -1;
auto & row = m_A.m_rows[pivot_row];
unsigned size = row.size();
@ -517,13 +510,6 @@ find_error_in_BxB(vector<X>& rs){
}
}
// recalculates the projection of x to B, such that Ax = b
template <typename T, typename X> void lp_core_solver_base<T, X>::
solve_Ax_eq_b() {
lp_assert(false);
}
template <typename T, typename X> non_basic_column_value_position lp_core_solver_base<T, X>::
get_non_basic_column_value_position(unsigned j) const {
switch (m_column_types[j]) {

View file

@ -511,7 +511,6 @@ public:
bool limit_inf_on_bound_m_neg(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
// x gets smaller
lp_assert(m < 0);
if (numeric_traits<T>::precise()) {
if (this->below_bound(x, bound)) return false;
if (this->above_bound(x, bound)) {
limit_theta((bound - x) / m, theta, unlimited);
@ -519,59 +518,30 @@ public:
theta = zero_of_type<X>();
unlimited = false;
}
} else {
const X& eps = harris_eps_for_bound(bound);
if (this->below_bound(x, bound)) return false;
if (this->above_bound(x, bound)) {
limit_theta((bound - x - eps) / m, theta, unlimited);
} else {
theta = zero_of_type<X>();
unlimited = false;
}
}
return true;
}
bool limit_inf_on_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
// x gets larger
lp_assert(m > 0);
if (numeric_traits<T>::precise()) {
if (this->above_bound(x, bound)) return false;
if (this->below_bound(x, bound)) {
limit_theta((bound - x) / m, theta, unlimited);
} else {
theta = zero_of_type<X>();
unlimited = false;
}
if (this->above_bound(x, bound)) return false;
if (this->below_bound(x, bound)) {
limit_theta((bound - x) / m, theta, unlimited);
} else {
const X& eps = harris_eps_for_bound(bound);
if (this->above_bound(x, bound)) return false;
if (this->below_bound(x, bound)) {
limit_theta((bound - x + eps) / m, theta, unlimited);
} else {
theta = zero_of_type<X>();
unlimited = false;
}
theta = zero_of_type<X>();
unlimited = false;
}
return true;
}
void limit_inf_on_lower_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
if (numeric_traits<T>::precise()) {
// x gets larger
lp_assert(m > 0);
if (this->below_bound(x, bound)) {
limit_theta((bound - x) / m, theta, unlimited);
}
}
else {
// x gets larger
lp_assert(m > 0);
const X& eps = harris_eps_for_bound(bound);
if (this->below_bound(x, bound)) {
limit_theta((bound - x + eps) / m, theta, unlimited);
}
}
lp_assert(m > 0);
if (this->below_bound(x, bound)) {
limit_theta((bound - x) / m, theta, unlimited);
}
}
void limit_inf_on_upper_bound_m_neg(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
@ -877,46 +847,13 @@ public:
m_epsilon_of_reduced_cost(T(1)/T(10000000)),
m_bland_mode_threshold(1000) {
if (!(numeric_traits<T>::precise())) {
m_converted_harris_eps = convert_struct<T, double>::convert(this->m_settings.harris_feasibility_tolerance);
} else {
m_converted_harris_eps = zero_of_type<T>();
}
m_converted_harris_eps = zero_of_type<T>();
this->set_status(lp_status::UNKNOWN);
}
// constructor
lp_primal_core_solver(static_matrix<T, X> & A,
vector<X> & b, // the right side vector
vector<X> & x, // the number of elements in x needs to be at least as large as the number of columns in A
vector<unsigned> & basis,
vector<unsigned> & nbasis,
vector<int> & heading,
vector<T> & costs,
const vector<column_type> & column_type_array,
const vector<X> & upper_bound_values,
lp_settings & settings,
const column_namer& column_names):
lp_core_solver_base<T, X>(A, // b,
basis,
nbasis,
heading,
x,
costs,
settings,
column_names,
column_type_array,
m_lower_bounds_dummy,
upper_bound_values),
m_beta(A.row_count()),
m_converted_harris_eps(convert_struct<T, double>::convert(this->m_settings.harris_feasibility_tolerance)) {
lp_assert(initial_x_is_correct());
m_lower_bounds_dummy.resize(A.column_count(), zero_of_type<T>());
m_enter_price_eps = numeric_traits<T>::precise() ? numeric_traits<T>::zero() : T(1e-5);
#ifdef Z3DEBUG
lp_assert(false);
#endif
}
bool initial_x_is_correct() {
std::set<unsigned> basis_set;

View file

@ -33,9 +33,7 @@ namespace lp {
template <typename T, typename X>
void lp_primal_core_solver<T, X>::sort_non_basis_rational() {
lp_assert(numeric_traits<T>::precise());
std::sort(this->m_nbasis.begin(), this->m_nbasis.end(), [this](unsigned a, unsigned b) {
std::sort(this->m_nbasis.begin(), this->m_nbasis.end(), [this](unsigned a, unsigned b) {
unsigned ca = this->m_A.number_of_non_zeroes_in_column(a);
unsigned cb = this->m_A.number_of_non_zeroes_in_column(b);
if (ca == 0 && cb != 0) return false;
@ -54,57 +52,15 @@ void lp_primal_core_solver<T, X>::sort_non_basis_rational() {
template <typename T, typename X>
void lp_primal_core_solver<T, X>::sort_non_basis() {
if (numeric_traits<T>::precise()) {
sort_non_basis_rational();
return;
}
m_non_basis_list.clear();
// reinit m_basis_heading
for (unsigned j = 0; j < this->m_nbasis.size(); j++) {
unsigned col = this->m_nbasis[j];
this->m_basis_heading[col] = - static_cast<int>(j) - 1;
m_non_basis_list.push_back(col);
}
sort_non_basis_rational();
}
template <typename T, typename X>
bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis(unsigned j) const {
if (numeric_traits<T>::precise())
return column_is_benefitial_for_entering_basis_precise(j);
const T& dj = this->m_d[j];
switch (this->m_column_types[j]) {
case column_type::fixed: break;
case column_type::free_column:
if (dj > m_epsilon_of_reduced_cost || dj < -m_epsilon_of_reduced_cost)
return true;
break;
case column_type::lower_bound:
if (dj > m_epsilon_of_reduced_cost) return true;;
break;
case column_type::upper_bound:
if (dj < -m_epsilon_of_reduced_cost) return true;
break;
case column_type::boxed:
if (dj > m_epsilon_of_reduced_cost) {
if (this->m_x[j] < this->m_upper_bounds[j] - this->bound_span(j)/2)
return true;
break;
} else if (dj < - m_epsilon_of_reduced_cost) {
if (this->m_x[j] > this->m_lower_bounds[j] + this->bound_span(j)/2)
return true;
}
break;
default:
lp_unreachable();
break;
}
return false;
return column_is_benefitial_for_entering_basis_precise(j);
}
template <typename T, typename X>
bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precise(unsigned j) const {
lp_assert (numeric_traits<T>::precise());
const T& dj = this->m_d[j];
TRACE("lar_solver", tout << "dj=" << dj << "\n";);
switch (this->m_column_types[j]) {
@ -144,7 +100,6 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precis
template <typename T, typename X>
int lp_primal_core_solver<T, X>::choose_entering_column_presize(unsigned number_of_benefitial_columns_to_go_over) { // at this moment m_y = cB * B(-1)
lp_assert(numeric_traits<T>::precise());
if (number_of_benefitial_columns_to_go_over == 0)
return -1;
if (this->m_basis_sort_counter == 0) {
@ -231,8 +186,6 @@ find_leaving_on_harris_theta(X const & harris_theta, X & t) {
}
if (++k == steps) k = 0;
} while (k != initial_k);
if (!this->precise())
restore_harris_eps();
return leaving;
}
@ -479,47 +432,14 @@ void lp_primal_core_solver<T, X>::update_reduced_costs_from_pivot_row(unsigned e
// return 0 if the reduced cost at entering is close enough to the refreshed
// 1 if it is way off, and 2 if it is unprofitable
template <typename T, typename X> int lp_primal_core_solver<T, X>::refresh_reduced_cost_at_entering_and_check_that_it_is_off(unsigned entering) {
if (numeric_traits<T>::precise()) return 0;
T reduced_at_entering_was = this->m_d[entering]; // can benefit from going over non-zeros of m_ed
lp_assert(abs(reduced_at_entering_was) > m_epsilon_of_reduced_cost);
T refreshed_cost = this->m_costs[entering];
unsigned i = this->m_m();
while (i--) refreshed_cost -= this->m_costs[this->m_basis[i]] * this->m_ed[i];
this->m_d[entering] = refreshed_cost;
T delta = abs(reduced_at_entering_was - refreshed_cost);
if (delta * 2 > abs(reduced_at_entering_was)) {
// this->m_status = UNSTABLE;
if (reduced_at_entering_was > m_epsilon_of_reduced_cost) {
if (refreshed_cost <= zero_of_type<T>())
return 2; // abort entering
} else {
if (refreshed_cost > -m_epsilon_of_reduced_cost)
return 2; // abort entering
}
return 1; // go on with this entering
} else {
if (reduced_at_entering_was > m_epsilon_of_reduced_cost) {
if (refreshed_cost <= zero_of_type<T>())
return 2; // abort entering
} else {
if (refreshed_cost > -m_epsilon_of_reduced_cost)
return 2; // abort entering
}
}
return 0;
}
template <typename T, typename X> void lp_primal_core_solver<T, X>::backup_and_normalize_costs() {
if (this->m_look_for_feasible_solution_only)
return; // no need to backup cost, since we are going to use only feasibility costs
if (numeric_traits<T>::precise() ) {
m_costs_backup = this->m_costs;
} else {
T cost_max = std::max(max_abs_in_vector(this->m_costs), T(1));
lp_assert(m_costs_backup.size() == 0);
for (unsigned j = 0; j < this->m_costs.size(); j++)
m_costs_backup.push_back(this->m_costs[j] /= cost_max);
}
m_costs_backup = this->m_costs;
}
template <typename T, typename X> void lp_primal_core_solver<T, X>::init_run() {
@ -527,10 +447,6 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::init_run(
}
template <typename T, typename X> void lp_primal_core_solver<T, X>::calc_working_vector_beta_for_column_norms(){
lp_assert(false);
}
template <typename T, typename X>
void lp_primal_core_solver<T, X>::advance_on_entering_equal_leaving(int entering, X & t) {
@ -571,63 +487,7 @@ template <typename T, typename X> unsigned lp_primal_core_solver<T, X>::get_num
// returns the number of iterations
template <typename T, typename X> unsigned lp_primal_core_solver<T, X>::solve() {
TRACE("lar_solver", tout << "solve " << this->get_status() << "\n";);
if (numeric_traits<T>::precise())
return solve_with_tableau();
init_run();
if (this->current_x_is_feasible() && this->m_look_for_feasible_solution_only) {
this->set_status(lp_status::FEASIBLE);
return 0;
}
do {
if (this->print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over((this->using_infeas_costs()? "inf" : "feas"), * this->m_settings.get_message_ostream())) {
return this->total_iterations();
}
one_iteration();
TRACE("lar_solver", tout << "one iteration: " << this->get_status() << "\n";);
lp_assert(!this->using_infeas_costs() || this->costs_on_nbasis_are_zeros());
switch (this->get_status()) {
case lp_status::OPTIMAL: // double check that we are at optimum
case lp_status::INFEASIBLE:
if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible())
break;
{ // precise case
}
break;
case lp_status::TENTATIVE_UNBOUNDED:
lp_assert(false);
break;
case lp_status::UNBOUNDED:
lp_assert(false);
break;
case lp_status::UNSTABLE:
lp_assert(false);
break;
default:
break; // do nothing
}
} while (
this->get_status() != lp_status::UNBOUNDED
&&
this->get_status() != lp_status::OPTIMAL
&&
this->get_status() != lp_status::INFEASIBLE
&&
this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements
&&
!(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only));
lp_assert(
this->current_x_is_feasible() == false
||
this->calc_current_x_is_feasible_include_non_basis());
return this->total_iterations();
return solve_with_tableau();
}
// calling it stage1 is too cryptic

View file

@ -43,19 +43,10 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::advance_on_e
}
advance_on_entering_and_leaving_tableau(entering, leaving, t);
}
/*
template <typename T, typename X> int lp_primal_core_solver<T, X>::choose_entering_column_tableau_rows() {
int i = find_inf_row();
if (i == -1)
return -1;
return find_shortest_beneficial_column_in_row(i);
}
*/
template <typename T, typename X> int lp_primal_core_solver<T, X>::choose_entering_column_tableau() {
//this moment m_y = cB * B(-1)
unsigned number_of_benefitial_columns_to_go_over = get_number_of_non_basic_column_to_try_for_enter();
lp_assert(numeric_traits<T>::precise());
if (number_of_benefitial_columns_to_go_over == 0)
return -1;
if (this->m_basis_sort_counter == 0) {
@ -294,7 +285,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::init_run_tab
return;
if (this->m_settings.backup_costs)
backup_and_normalize_costs();
m_epsilon_of_reduced_cost = numeric_traits<X>::precise() ? zero_of_type<T>() : T(1) / T(10000000);
m_epsilon_of_reduced_cost = zero_of_type<T>();
if (this->m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows)
init_tableau_rows();

View file

@ -78,9 +78,8 @@ enum class lp_status {
// 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 <typename X>
unsigned ratio_of_index_size_to_all_size() {
if (numeric_traits<X>::precise())
return 10;
return 120;
}
const char* lp_status_to_string(lp_status status);
@ -274,7 +273,7 @@ public:
statistics const& stats() const { return m_stats; }
template <typename T> static bool is_eps_small_general(const T & t, const double & eps) {
return (!numeric_traits<T>::precise())? is_epsilon_small<T>(t, eps) : numeric_traits<T>::is_zero(t);
return numeric_traits<T>::is_zero(t);
}
template <typename T>
@ -373,9 +372,7 @@ inline std::string T_to_string(const mpq & t) {
template <typename T>
bool val_is_smaller_than_eps(T const & t, double const & eps) {
if (!numeric_traits<T>::precise()) {
return numeric_traits<T>::get_double(t) < eps;
}
return t <= numeric_traits<T>::zero();
}

View file

@ -70,19 +70,12 @@ lp_status lp_status_from_string(std::string status) {
template <typename T>
bool vectors_are_equal(T * a, vector<T> &b, unsigned n) {
if (numeric_traits<T>::precise()) {
for (unsigned i = 0; i < n; i ++){
if (!numeric_traits<T>::is_zero(a[i] - b[i])) {
return false;
}
}
} else {
for (unsigned i = 0; i < n; i ++){
if (std::abs(numeric_traits<T>::get_double(a[i] - b[i])) > 0.000001) {
return false;
}
}
}
return true;
}
@ -91,27 +84,12 @@ template <typename T>
bool vectors_are_equal(const vector<T> & a, const vector<T> &b) {
unsigned n = static_cast<unsigned>(a.size());
if (n != b.size()) return false;
if (numeric_traits<T>::precise()) {
for (unsigned i = 0; i < n; i ++){
if (!numeric_traits<T>::is_zero(a[i] - b[i])) {
return false;
}
}
} else {
for (unsigned i = 0; i < n; i ++){
double da = numeric_traits<T>::get_double(a[i]);
double db = numeric_traits<T>::get_double(b[i]);
double amax = std::max(fabs(da), fabs(db));
if (amax > 1) {
da /= amax;
db /= amax;
}
if (fabs(da - db) > 0.000001) {
return false;
}
}
}
return true;
}
#ifdef Z3DEBUG

View file

@ -153,9 +153,6 @@ template <typename X> inline X ceil_ratio(const X & a, const X & b) { return num
template <typename X> inline X floor_ratio(const X & a, const X & b) { return numeric_traits<X>::floor_ratio(a, b); }
template <typename X> inline bool precise() { return numeric_traits<X>::precise(); }
// returns true if a factor of b
template <typename T>
bool is_proper_factor(const T & a, const T & b) {

View file

@ -32,16 +32,9 @@ bool matrix<T, X>::is_equal(const matrix<T, X>& other) {
for (unsigned j = 0; j < column_count(); j++) {
auto a = get_elem(i, j);
auto b = other.get_elem(i, j);
if (numeric_traits<T>::precise()) {
if (a != b) return false;
} else if (fabs(numeric_traits<T>::get_double(a - b)) > 0.000001) {
// cout << "returning false from operator== of matrix comparison" << endl;
// cout << "this matrix is " << endl;
// print_matrix(*this);
// cout << "other matrix is " << endl;
// print_matrix(other);
return false;
}
if (a != b) return false;
}
}
return true;

View file

@ -45,7 +45,6 @@ template <typename T> class numeric_traits {};
template <> class numeric_traits<unsigned> {
public:
static bool precise() { return true; }
static unsigned zero() { return 0; }
static unsigned one() { return 1; }
static bool is_zero(unsigned v) { return v == 0; }
@ -56,7 +55,6 @@ public:
template <> class numeric_traits<int> {
public:
static bool precise() { return true; }
static int zero() { return 0; }
static int one() { return 1; }
static bool is_zero(int v) { return v == 0; }
@ -71,7 +69,6 @@ public:
template <> class numeric_traits<double> {
public:
static bool precise() { return false; }
static double g_zero;
static double const &zero() { return g_zero; }
static double g_one;
@ -88,7 +85,6 @@ public:
template<>
class numeric_traits<rational> {
public:
static bool precise() { return true; }
static rational const & zero() { return rational::zero(); }
static rational const & one() { return rational::one(); }
static bool is_zero(const rational & v) { return v.is_zero(); }
@ -251,8 +247,6 @@ struct numeric_pair {
return numeric_pair(-x, -y);
}
static bool precize() { return lp::numeric_traits<T>::precize();}
bool is_zero() const { return x.is_zero() && y.is_zero(); }
bool is_pos() const { return x.is_pos() || (x.is_zero() && y.is_pos());}
@ -294,12 +288,10 @@ numeric_pair<T> operator/(const numeric_pair<T> & r, const X & a) {
return numeric_pair<T>(r.x / a, r.y / a);
}
// template <numeric_pair, typename T> bool precise() { return numeric_traits<T>::precise();}
template <typename T> double get_double(const lp::numeric_pair<T> & ) { /* lp_unreachable(); */ return 0;}
template <typename T>
class numeric_traits<lp::numeric_pair<T>> {
public:
static bool precise() { return numeric_traits<T>::precise();}
static lp::numeric_pair<T> zero() { return lp::numeric_pair<T>(numeric_traits<T>::zero(), numeric_traits<T>::zero()); }
static bool is_zero(const lp::numeric_pair<T> & v) { return numeric_traits<T>::is_zero(v.x) && numeric_traits<T>::is_zero(v.y); }
static double get_double(const lp::numeric_pair<T> & v){ return numeric_traits<T>::get_double(v.x); } // just return the double of the first coordinate

View file

@ -344,7 +344,6 @@ public:
void fill_last_row_with_pivoting(const term& row,
unsigned bj, // the index of the basis column
const vector<int> & basis_heading) {
lp_assert(numeric_traits<T>::precise());
lp_assert(row_count() > 0);
m_work_vector.resize(column_count());
T a;