refactor(util/lp): use Lean exception

This commit is contained in:
Leonardo de Moura 2016-01-08 15:59:45 -08:00
parent 8fbf66d01a
commit d9acf90f7b
8 changed files with 235 additions and 259 deletions

View file

@ -261,7 +261,7 @@ class lar_solver {
} }
break; break;
default: default:
throw "unexpected"; lean_unreachable();
} }
} }
@ -338,7 +338,7 @@ class lar_solver {
case at_upper_bound: return upper_bound[j]; case at_upper_bound: return upper_bound[j];
case free_of_bounds: return zero_of_type<V>(); case free_of_bounds: return zero_of_type<V>();
default: default:
throw "unexpected type"; lean_unreachable();
} }
} }
@ -421,10 +421,8 @@ public:
case GE: return left_side_val >= constr.m_right_side; case GE: return left_side_val >= constr.m_right_side;
case GT: return left_side_val >= constr.m_right_side; case GT: return left_side_val >= constr.m_right_side;
case EQ: return left_side_val == constr.m_right_side; case EQ: return left_side_val == constr.m_right_side;
default: default:
throw "unexpected"; lean_unreachable();
return false;
} }
} }
@ -833,8 +831,7 @@ public:
return abs(left_side_val - norm_constr.m_right_side); return abs(left_side_val - norm_constr.m_right_side);
default: default:
throw "unexpected"; lean_unreachable();
return numeric_traits<mpq>::zero();
} }
} }

View file

@ -748,7 +748,7 @@ public:
case upper_bound: case upper_bound:
return at_upper_bound; return at_upper_bound;
default: default:
throw "unexpected column type"; lean_unreachable();
} }
} }
}; };

View file

@ -1159,8 +1159,7 @@ public: // todo : move public lower ; it is for debug only
slope_at_entering += delta; slope_at_entering += delta;
break; break;
default: default:
throw 1; lean_unreachable();
lean_assert(false); // such a type does not exist
} }
} }
@ -1222,9 +1221,7 @@ public: // todo : move public lower ; it is for debug only
return true; return true;
break; break;
default: default:
lean_assert(false); lean_unreachable();
throw "cannot be here";
break;
} }
} }

View file

@ -340,8 +340,7 @@ public:
for (auto it : this->m_columns) { for (auto it : this->m_columns) {
auto sol_it = solution.find(it.second->get_name()); auto sol_it = solution.find(it.second->get_name());
if (sol_it == solution.end()) { if (sol_it == solution.end()) {
std::cout << "cannot find column " << it.first << " in solution " << std::endl; throw exception(sstream() << "cannot find column " << it.first << " in solutio");
throw;
} }
if (!it.second->bounds_hold(sol_it->second)) { if (!it.second->bounds_hold(sol_it->second)) {
@ -356,8 +355,7 @@ public:
T get_row_value(unsigned i, std::unordered_map<std::string, T> const & solution, bool print) { T get_row_value(unsigned i, std::unordered_map<std::string, T> const & solution, bool print) {
auto it = this->m_A_values.find(i); auto it = this->m_A_values.find(i);
if (it == this->m_A_values.end()) { if (it == this->m_A_values.end()) {
std::cout << "cannot find row " << i << std::endl; throw exception(sstream() << "cannot find row " << i);
throw "get_row_value";
} }
T ret = numeric_traits<T>::zero(); T ret = numeric_traits<T>::zero();
for (auto & pair : it->second) { for (auto & pair : it->second) {
@ -414,8 +412,7 @@ public:
} }
return true;; return true;;
} }
std::cout << "throw in row_constraint_holds " << std::endl; lean_unreachable();
throw "wrong case";
} }
bool row_constraints_hold(std::unordered_map<std::string, T> const & solution) { bool row_constraints_hold(std::unordered_map<std::string, T> const & solution) {

View file

@ -35,7 +35,7 @@ inline std::string column_type_to_string(column_type t) {
case free_column: case free_column:
return std::string("free_column"); return std::string("free_column");
default: default:
throw "unexpected"; lean_unreachable();
} }
} }
@ -70,8 +70,7 @@ inline const char* lp_status_to_string(lp_status status) {
case EMPTY: return "EMPTY"; case EMPTY: return "EMPTY";
case UNSTABLE: return "UNSTABLE"; case UNSTABLE: return "UNSTABLE";
default: default:
std::cout << "throwing in lp_status_to_string " << std::endl; lean_unreachable();
throw "lp_status_to_string";
} }
} }
@ -85,8 +84,7 @@ inline lp_status lp_status_from_string(std::string status) {
if (status == "TIME_EXHAUSTED") return lp_status::TIME_EXHAUSTED; if (status == "TIME_EXHAUSTED") return lp_status::TIME_EXHAUSTED;
if (status == "ITERATIONS_EXHAUSTED") return lp_status::ITERATIONS_EXHAUSTED; if (status == "ITERATIONS_EXHAUSTED") return lp_status::ITERATIONS_EXHAUSTED;
if (status == "EMPTY") return lp_status::EMPTY; if (status == "EMPTY") return lp_status::EMPTY;
std::cout << "unexpected status " << status << std::endl; lean_unreachable();
throw "wrong status in a test file";
} }
enum non_basic_column_value_position { at_low_bound, at_upper_bound, at_fixed, free_of_bounds }; enum non_basic_column_value_position { at_low_bound, at_upper_bound, at_fixed, free_of_bounds };

View file

@ -6,15 +6,16 @@
*/ */
#pragma once #pragma once
#include "util/lp/lp_settings.h"
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <algorithm>
#include <vector>
#include "util/exception.h"
#include "util/sstream.h"
#include "util/lp/lp_settings.h"
#include "util/lp/column_info.h" #include "util/lp/column_info.h"
#include "util/lp/static_matrix.h" #include "util/lp/static_matrix.h"
#include <algorithm>
#include "util/lp/lp_core_solver_base.h" #include "util/lp/lp_core_solver_base.h"
#include <vector>
#include "util/lp/scaler.h" #include "util/lp/scaler.h"
namespace lean { namespace lean {
enum lp_relation { enum lp_relation {
@ -109,8 +110,7 @@ public:
T get_column_value_by_name(std::string name) const { T get_column_value_by_name(std::string name) const {
auto it = m_names_to_columns.find(name); auto it = m_names_to_columns.find(name);
if (it == m_names_to_columns.end()) { if (it == m_names_to_columns.end()) {
std::cout << "throwing in get_column_value_by_name" << std::endl; throw exception(sstream() << "get_column_value_by_name " << name);
throw "get_column_value_by_name";
} }
return get_column_value(it -> second); return get_column_value(it -> second);
} }
@ -435,11 +435,9 @@ protected:
case lp_relation::Less_or_equal: case lp_relation::Less_or_equal:
return row_le_is_obsolete(row, row_index); return row_le_is_obsolete(row, row_index);
} }
lean_unreachable();
throw "unexpected relation";
} }
void remove_fixed_or_zero_columns() { void remove_fixed_or_zero_columns() {
for (auto & i_row : m_A_values) { for (auto & i_row : m_A_values) {
remove_fixed_or_zero_columns_from_row(i_row.first, i_row.second); remove_fixed_or_zero_columns_from_row(i_row.first, i_row.second);
@ -515,8 +513,7 @@ protected:
for (auto & row : m_A_values) { for (auto & row : m_A_values) {
for (auto & col : row.second) { for (auto & col : row.second) {
if (col.second == numeric_traits<T>::zero() || m_columns[col.first]->is_fixed()) { if (col.second == numeric_traits<T>::zero() || m_columns[col.first]->is_fixed()) {
std::cout << "found fixed column " << std::endl; throw exception("found fixed column");
throw "map_external_columns_to_core_solver_columns";
} }
unsigned j = col.first; unsigned j = col.first;
auto j_place = m_external_columns_to_core_solver_columns.find(j); auto j_place = m_external_columns_to_core_solver_columns.find(j);
@ -615,7 +612,7 @@ protected:
auto row = this->m_A_values.find(i); auto row = this->m_A_values.find(i);
if (row == this->m_A_values.end()) { if (row == this->m_A_values.end()) {
throw "cannot find row "; throw exception("cannot find row");
} }
for (auto col : row->second) { for (auto col : row->second) {
ret += col.second * this->m_columns[col.first]->get_shift(); ret += col.second * this->m_columns[col.first]->get_shift();

View file

@ -4,7 +4,6 @@
Author: Lev Nachmanson Author: Lev Nachmanson
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include <algorithm> #include <algorithm>
@ -12,228 +11,227 @@
#include "util/numerics/double.h" #include "util/numerics/double.h"
namespace lean { namespace lean {
template <typename T> template <typename T>
std::string T_to_string(const T & t); // forward definition std::string T_to_string(const T & t); // forward definition
template <typename X, typename Y> template <typename X, typename Y>
struct convert_struct { struct convert_struct {
static X convert(const Y & y){ return X(y);} static X convert(const Y & y){ return X(y);}
static bool is_epsilon_small(const X & x, const double & y) { return abs(get_double(x)) < y; } static bool is_epsilon_small(const X & x, const double & y) { return abs(get_double(x)) < y; }
static bool below_bound_numeric(const X &, const X &, const Y &) { throw "don't call";} static bool below_bound_numeric(const X &, const X &, const Y &) { lean_unreachable(); }
static bool above_bound_numeric(const X &, const X &, const Y &) { throw "don't call";} static bool above_bound_numeric(const X &, const X &, const Y &) { lean_unreachable(); }
}; };
template <> template <>
struct convert_struct<double, mpq> { struct convert_struct<double, mpq> {
static double convert(const mpq & q) {return q.get_double();} static double convert(const mpq & q) {return q.get_double();}
}; };
template <typename T> template <typename T>
struct numeric_pair { struct numeric_pair {
T x; T x;
T y; T y;
// empty constructor // empty constructor
numeric_pair() {} numeric_pair() {}
// another constructor // another constructor
numeric_pair(T xp, T yp) : x(xp), y(yp) {} numeric_pair(T xp, T yp) : x(xp), y(yp) {}
template <typename X, typename Y> numeric_pair(X xp, Y yp) : numeric_pair(convert_struct<T, X>::convert(xp), convert_struct<T, Y>::convert(yp)) {} template <typename X, typename Y> numeric_pair(X xp, Y yp) : numeric_pair(convert_struct<T, X>::convert(xp), convert_struct<T, Y>::convert(yp)) {}
bool operator<(const numeric_pair& a) const { bool operator<(const numeric_pair& a) const {
return x < a.x || (x == a.x && y < a.y); return x < a.x || (x == a.x && y < a.y);
}
bool operator>(const numeric_pair& a) const {
return x > a.x || (x == a.x && y > a.y);
}
bool operator==(const numeric_pair& a) const {
return a.x == x && a.y == y;
}
bool operator!=(const numeric_pair& a) const {
return !(*this == a);
}
bool operator<=(const numeric_pair& a) const {
return *this < a || *this == a;
}
bool operator>=(const numeric_pair& a) const {
return *this > a || a == *this;
}
numeric_pair operator*(const T & a) const {
return numeric_pair(a * x, a * y);
}
numeric_pair operator/(const T & a) const {
T a_as_T(a);
return numeric_pair(x / a_as_T, y / a_as_T);
}
numeric_pair operator/(const numeric_pair &) const {
throw "should not be called";
}
numeric_pair operator+(const numeric_pair & a) const {
return numeric_pair(a.x + x, a.y + y);
}
numeric_pair operator*(const numeric_pair & /*a*/) const {
throw "should not be called";
}
numeric_pair& operator+=(const numeric_pair & a) {
x += a.x;
y += a.y;
return *this;
}
numeric_pair& operator-=(const numeric_pair & a) {
x -= a.x;
y -= a.y;
return *this;
}
numeric_pair& operator/=(const T & a) {
x /= a;
y /= a;
return *this;
}
numeric_pair& operator*=(const T & a) {
x *= a;
y *= a;
return *this;
}
numeric_pair operator-(const numeric_pair & a) const {
return numeric_pair(x - a.x, y - a.y);
}
numeric_pair operator-() const {
return numeric_pair(-x, -y);
}
static bool precize() { return numeric_traits<T>::precize();}
std::string to_string() const { return std::string("(") + T_to_string(x) + ", " + T_to_string(y) + ")"; }
};
template <typename T>
std::ostream& operator<<(std::ostream& os, numeric_pair<T> const & obj) {
os << obj.to_string();
return os;
} }
template <typename T, typename X> bool operator>(const numeric_pair& a) const {
numeric_pair<T> operator*(const X & a, const numeric_pair<T> & r) { return x > a.x || (x == a.x && y > a.y);
return numeric_pair<T>(a * r.x, a * r.y);
} }
template <typename T, typename X> bool operator==(const numeric_pair& a) const {
numeric_pair<T> operator*(const numeric_pair<T> & r, const X & a) { return a.x == x && a.y == y;
return numeric_pair<T>(a * r.x, a * r.y); }
bool operator!=(const numeric_pair& a) const {
return !(*this == a);
}
bool operator<=(const numeric_pair& a) const {
return *this < a || *this == a;
}
bool operator>=(const numeric_pair& a) const {
return *this > a || a == *this;
}
numeric_pair operator*(const T & a) const {
return numeric_pair(a * x, a * y);
}
numeric_pair operator/(const T & a) const {
T a_as_T(a);
return numeric_pair(x / a_as_T, y / a_as_T);
}
numeric_pair operator/(const numeric_pair &) const {
lean_unreachable();
} }
numeric_pair operator+(const numeric_pair & a) const {
return numeric_pair(a.x + x, a.y + y);
}
numeric_pair operator*(const numeric_pair & /*a*/) const {
lean_unreachable();
}
numeric_pair& operator+=(const numeric_pair & a) {
x += a.x;
y += a.y;
return *this;
}
numeric_pair& operator-=(const numeric_pair & a) {
x -= a.x;
y -= a.y;
return *this;
}
numeric_pair& operator/=(const T & a) {
x /= a;
y /= a;
return *this;
}
numeric_pair& operator*=(const T & a) {
x *= a;
y *= a;
return *this;
}
numeric_pair operator-(const numeric_pair & a) const {
return numeric_pair(x - a.x, y - a.y);
}
numeric_pair operator-() const {
return numeric_pair(-x, -y);
}
static bool precize() { return numeric_traits<T>::precize();}
std::string to_string() const { return std::string("(") + T_to_string(x) + ", " + T_to_string(y) + ")"; }
};
// template <numeric_pair, typename T> bool precise() { return numeric_traits<T>::precise();} template <typename T>
template <typename T> double get_double(const numeric_pair<T> & ) { throw "do not call"; } std::ostream& operator<<(std::ostream& os, numeric_pair<T> const & obj) {
template <typename T> os << obj.to_string();
class numeric_traits<numeric_pair<T>> { return os;
public: }
static bool precise() { return numeric_traits<T>::precise();}
static numeric_pair<T> zero() { return numeric_pair<T>(numeric_traits<T>::zero(), numeric_traits<T>::zero()); } template <typename T, typename X>
static bool is_zero(const numeric_pair<T> & v) { return numeric_traits<T>::is_zero(v.x) && numeric_traits<T>::is_zero(v.y); } numeric_pair<T> operator*(const X & a, const numeric_pair<T> & r) {
static double get_double(const numeric_pair<T> & v){ return numeric_traits<T>::get_double(v.x); } // just return the double of the first coordinate return numeric_pair<T>(a * r.x, a * r.y);
static double one() { throw "do not call"; } }
};
template <> template <typename T, typename X>
struct convert_struct<double, numeric_pair<double>> { numeric_pair<T> operator*(const numeric_pair<T> & r, const X & a) {
static double convert(const numeric_pair<double> & q) {return q.x;} return numeric_pair<T>(a * r.x, a * r.y);
}; }
template <typename X> bool is_epsilon_small(const X & v, const double& eps); // forward definition { return convert_struct<X, double>::is_epsilon_small(v, eps);}
template <typename T>
struct convert_struct<numeric_pair<T>, double> { // template <numeric_pair, typename T> bool precise() { return numeric_traits<T>::precise();}
static numeric_pair<T> convert(const double & q) { template <typename T> double get_double(const numeric_pair<T> & ) { lean_unreachable(); }
return numeric_pair<T>(convert_struct<T, double>::convert(q), zero_of_type<T>()); template <typename T>
} class numeric_traits<numeric_pair<T>> {
static bool is_epsilon_small(const numeric_pair<T> & p, const double & eps) { public:
return convert_struct<T, double>::is_epsilon_small(p.x, eps) && convert_struct<T, double>::is_epsilon_small(p.y, eps); static bool precise() { return numeric_traits<T>::precise();}
} static numeric_pair<T> zero() { return numeric_pair<T>(numeric_traits<T>::zero(), numeric_traits<T>::zero()); }
static bool below_bound_numeric(const numeric_pair<T> &, const numeric_pair<T> &, const double &) { static bool is_zero(const numeric_pair<T> & v) { return numeric_traits<T>::is_zero(v.x) && numeric_traits<T>::is_zero(v.y); }
throw "do not call"; static double get_double(const numeric_pair<T> & v){ return numeric_traits<T>::get_double(v.x); } // just return the double of the first coordinate
} static double one() { lean_unreachable(); }
static bool above_bound_numeric(const numeric_pair<T> &, const numeric_pair<T> &, const double &) { };
throw "do not call"; template <>
} struct convert_struct<double, numeric_pair<double>> {
}; static double convert(const numeric_pair<double> & q) {return q.x;}
};
template <>
struct convert_struct<numeric_pair<double>, double> { template <typename X> bool is_epsilon_small(const X & v, const double& eps); // forward definition { return convert_struct<X, double>::is_epsilon_small(v, eps);}
static numeric_pair<double> convert(const double & q) {
return numeric_pair<double>(q, 0.0); template <typename T>
} struct convert_struct<numeric_pair<T>, double> {
static bool is_epsilon_small(const numeric_pair<double> & p, const double & eps) { static numeric_pair<T> convert(const double & q) {
return std::abs(p.x) < eps && std::abs(p.y) < eps; return numeric_pair<T>(convert_struct<T, double>::convert(q), zero_of_type<T>());
} }
static bool is_epsilon_small(const numeric_pair<T> & p, const double & eps) {
static int compare_on_coord(const double & x, const double & bound, const double eps) { return convert_struct<T, double>::is_epsilon_small(p.x, eps) && convert_struct<T, double>::is_epsilon_small(p.y, eps);
lean_assert(eps > 0); }
if (bound == 0) return (x < - eps)? -1: (x > eps? 1 : 0); // it is an important special case static bool below_bound_numeric(const numeric_pair<T> &, const numeric_pair<T> &, const double &) {
double relative = (bound > 0)? - eps: eps; lean_unreachable();
return (x < bound * (1.0 + relative) - eps)? -1 : ((x > bound * (1.0 - relative) + eps)? 1 : 0); }
} static bool above_bound_numeric(const numeric_pair<T> &, const numeric_pair<T> &, const double &) {
lean_unreachable();
static bool below_bound_numeric(const numeric_pair<double> & x, const numeric_pair<double> & bound, const double & eps) { }
int r = compare_on_coord(x.x, bound.x, eps); };
if (r == 1) return false;
if (r == -1) return true; template <>
// the first coordinates are almost the same struct convert_struct<numeric_pair<double>, double> {
lean_assert(r == 0); static numeric_pair<double> convert(const double & q) {
return compare_on_coord(x.y, bound.y, eps) == -1; return numeric_pair<double>(q, 0.0);
} }
static bool is_epsilon_small(const numeric_pair<double> & p, const double & eps) {
static bool above_bound_numeric(const numeric_pair<double> & x, const numeric_pair<double> & bound, const double & eps) { return std::abs(p.x) < eps && std::abs(p.y) < eps;
int r = compare_on_coord(x.x, bound.x, eps); }
if (r == -1) return false;
if (r == 1) return true; static int compare_on_coord(const double & x, const double & bound, const double eps) {
// the first coordinates are almost the same lean_assert(eps > 0);
lean_assert(r == 0); if (bound == 0) return (x < - eps)? -1: (x > eps? 1 : 0); // it is an important special case
return compare_on_coord(x.y, bound.y, eps) == 1; double relative = (bound > 0)? - eps: eps;
} return (x < bound * (1.0 + relative) - eps)? -1 : ((x > bound * (1.0 - relative) + eps)? 1 : 0);
}; }
template <> static bool below_bound_numeric(const numeric_pair<double> & x, const numeric_pair<double> & bound, const double & eps) {
struct convert_struct<double, double> { int r = compare_on_coord(x.x, bound.x, eps);
static bool is_epsilon_small(const double& x, const double & eps) { if (r == 1) return false;
return x < eps && x > -eps; if (r == -1) return true;
} // the first coordinates are almost the same
static double convert(const double & y){ return y;} lean_assert(r == 0);
static bool below_bound_numeric(const double & x, const double & bound, const double & eps) { return compare_on_coord(x.y, bound.y, eps) == -1;
lean_assert(eps > 0); }
if (bound == 0) return x < - eps;
double relative = (bound > 0)? - eps: eps; static bool above_bound_numeric(const numeric_pair<double> & x, const numeric_pair<double> & bound, const double & eps) {
return x < bound * (1.0 + relative) - eps; int r = compare_on_coord(x.x, bound.x, eps);
} if (r == -1) return false;
static bool above_bound_numeric(const double & x, const double & bound, const double & eps) { if (r == 1) return true;
lean_assert(eps > 0); // the first coordinates are almost the same
if (bound == 0) return x > eps; lean_assert(r == 0);
double relative = (bound > 0)? eps: - eps; return compare_on_coord(x.y, bound.y, eps) == 1;
return x > bound * (1.0 + relative) + eps; }
} };
};
template <>
template <typename X> bool is_epsilon_small(const X & v, const double &eps) { return convert_struct<X, double>::is_epsilon_small(v, eps);} struct convert_struct<double, double> {
template <typename X> bool below_bound_numeric(const X & x, const X & bound, const double& eps) { return convert_struct<X, double>::below_bound_numeric(x, bound, eps);} static bool is_epsilon_small(const double& x, const double & eps) {
template <typename X> bool above_bound_numeric(const X & x, const X & bound, const double& eps) { return convert_struct<X, double>::above_bound_numeric(x, bound, eps);} return x < eps && x > -eps;
}
static double convert(const double & y){ return y;}
static bool below_bound_numeric(const double & x, const double & bound, const double & eps) {
lean_assert(eps > 0);
if (bound == 0) return x < - eps;
double relative = (bound > 0)? - eps: eps;
return x < bound * (1.0 + relative) - eps;
}
static bool above_bound_numeric(const double & x, const double & bound, const double & eps) {
lean_assert(eps > 0);
if (bound == 0) return x > eps;
double relative = (bound > 0)? eps: - eps;
return x > bound * (1.0 + relative) + eps;
}
};
template <typename X> bool is_epsilon_small(const X & v, const double &eps) { return convert_struct<X, double>::is_epsilon_small(v, eps);}
template <typename X> bool below_bound_numeric(const X & x, const X & bound, const double& eps) { return convert_struct<X, double>::below_bound_numeric(x, bound, eps);}
template <typename X> bool above_bound_numeric(const X & x, const X & bound, const double& eps) { return convert_struct<X, double>::above_bound_numeric(x, bound, eps);}
} }

View file

@ -7,6 +7,9 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <set>
#include <unordered_map>
#include <utility>
#include "util/numerics/numeric_traits.h" #include "util/numerics/numeric_traits.h"
#include "util/numerics/xnumeral.h" #include "util/numerics/xnumeral.h"
#include "util/numerics/mpq.h" #include "util/numerics/mpq.h"
@ -15,10 +18,7 @@
#include "util/numerics/double.h" #include "util/numerics/double.h"
#include "util/numerics/float.h" #include "util/numerics/float.h"
#include "util/numerics/mpfp.h" #include "util/numerics/mpfp.h"
#include <set>
#include "util/lp/sparse_vector.h" #include "util/lp/sparse_vector.h"
#include <unordered_map>
#include <utility>
#include "util/lp/matrix_domain.h" #include "util/lp/matrix_domain.h"
#include "util/lp/indexed_vector.h" #include "util/lp/indexed_vector.h"
@ -48,9 +48,7 @@ private:
T m_value; T m_value;
}; };
// each assignment for this matrix should be issued only once!!!
// each assignment for this matrix should be issued only once!!!
template <typename T, typename X> template <typename T, typename X>
class static_matrix class static_matrix
#ifdef LEAN_DEBUG #ifdef LEAN_DEBUG
@ -461,15 +459,9 @@ public:
virtual void set_number_of_rows(unsigned /*m*/) { } virtual void set_number_of_rows(unsigned /*m*/) { }
virtual void set_number_of_columns(unsigned /*n*/) { } virtual void set_number_of_columns(unsigned /*n*/) { }
#endif #endif
// const T & get_value_of_column_cell(column_cell<T> const & cc) const {
// lean_assert(cc.m_i < m_rows.size());
// lean_assert(cc.m_offset < m_rows[cc.m_i].size());
// return m_rows[cc.m_i][cc.m_offset].get_val();
// }
T get_max_val_in_row(unsigned i) const { T get_max_val_in_row(unsigned i) const {
lean_assert(false); lean_unreachable();
throw 0;// not implemented
} }
T get_balance() const { T get_balance() const {