diff --git a/src/tests/util/lp/lp.cpp b/src/tests/util/lp/lp.cpp index b8344c7a5..fa18df0c3 100644 --- a/src/tests/util/lp/lp.cpp +++ b/src/tests/util/lp/lp.cpp @@ -4,35 +4,34 @@ Released under Apache 2.0 license as described in the file LICENSE. Author: Lev Nachmanson */ +#include +#include +#include +#include #include #include #include #include -#include "util/lp/lp.h" -#include "util/lp/lp_primal_simplex.h" #include #include - +#include +#include +#include "util/pair.h" +#include "util/lp/lp.h" +#include "util/lp/lp_primal_simplex.h" #include "tests/util/lp/mps_reader.h" #include "tests/util/lp/smt_reader.h" #include "util/numerics/mpq.h" #include "util/lp/binary_heap_priority_queue.h" #include "tests/util/lp/argument_parser.h" #include "tests/util/lp/test_file_reader.h" -#include -#include #include "util/lp/indexed_value.h" -#include #include "tests/util/lp/init_module.h" #include "util/numerics/init_module.h" -#include -#include #include "util/lp/lar_solver.h" #include "util/lp/numeric_pair.h" #include "util/lp/binary_heap_upair_queue.h" -#include using namespace lean; -using namespace std; unsigned seed = 1; #ifdef LEAN_DEBUG unsigned lp_settings::ddd = 0; @@ -136,7 +135,7 @@ void tst1() { float test = m10by9(0, 1); - std::cout << "got " << test << std:: endl; + std::cout << "got " << test << std::endl; m10by9.set(0, 8, 8); @@ -189,39 +188,39 @@ void test_small_lu(lp_settings & settings) { lu l(m, basis, heading, settings, non_basic_columns); lean_assert(l.is_correct()); indexed_vector w(m.row_count()); - cout << "entering 2, leaving 0" << endl; + cout << "entering 2, leaving 0" << std::endl; l.prepare_entering(2, w); // to init vector w l.replace_column(0, 0, w); l.change_basis(2, 0); // #ifdef LEAN_DEBUG - // cout << "we were factoring " << endl; + // cout << "we were factoring " << std::endl; // print_matrix(get_B(l)); // #endif lean_assert(l.is_correct()); - cout << "entering 4, leaving 3" << endl; + cout << "entering 4, leaving 3" << std::endl; l.prepare_entering(4, w); // to init vector w l.replace_column(3, 0, w); l.change_basis(4, 3); - cout << "we were factoring " << endl; + cout << "we were factoring " << std::endl; #ifdef LEAN_DEBUG print_matrix(get_B(l)); #endif lean_assert(l.is_correct()); - cout << "entering 5, leaving 1" << endl; + cout << "entering 5, leaving 1" << std::endl; l.prepare_entering(5, w); // to init vector w l.replace_column(1, 0, w); l.change_basis(5, 1); - cout << "we were factoring " << endl; + cout << "we were factoring " << std::endl; #ifdef LEAN_DEBUG print_matrix(get_B(l)); #endif lean_assert(l.is_correct()); - cout << "entering 3, leaving 2" << endl; + cout << "entering 3, leaving 2" << std::endl; l.prepare_entering(3, w); // to init vector w l.replace_column(2, 0, w); l.change_basis(3, 2); - cout << "we were factoring " << endl; + cout << "we were factoring " << std::endl; #ifdef LEAN_DEBUG print_matrix(get_B(l)); #endif @@ -400,13 +399,13 @@ void test_larger_lu(lp_settings& settings) { dense_matrix left_side = l.get_left_side(); dense_matrix right_side = l.get_right_side(); if (!(left_side == right_side)) { - cout << "left side" << endl; + cout << "left side" << std::endl; print_matrix(left_side); - cout << "right side" << endl; + cout << "right side" << std::endl; print_matrix(right_side); std::cout << "different sides" << std::endl; - cout << "initial factorization is incorrect" << endl; + cout << "initial factorization is incorrect" << std::endl; exit(1); } indexed_vector w(m.row_count()); @@ -532,7 +531,7 @@ void test_lp_primal_core_solver() { #ifdef LEAN_DEBUG template void test_swap_rows_with_permutation(sparse_matrix& m){ - cout << "testing swaps" << endl; + cout << "testing swaps" << std::endl; unsigned dim = m.row_count(); dense_matrix original(m); permutation_matrix q(dim); @@ -542,12 +541,12 @@ void test_swap_rows_with_permutation(sparse_matrix& m){ unsigned row1 = lrand48() % dim; unsigned row2 = lrand48() % dim; if (row1 == row2) continue; - cout << "swap " << row1 << " " << row2 << endl; + cout << "swap " << row1 << " " << row2 << std::endl; m.swap_rows(row1, row2); q.transpose_from_left(row1, row2); lean_assert(original == q * m); print_matrix(m); - cout << endl; + cout << std::endl; } } #endif @@ -579,14 +578,14 @@ void matrix_repro_test() { auto l = d * m.m_column_permutation; l = m.m_row_permutation * l; - cout << "matrix_repro_test" << endl; + cout << "matrix_repro_test" << std::endl; print_matrix(l); lean_assert(l == m); } template void test_swap_cols_with_permutation(sparse_matrix& m){ - cout << "testing swaps" << endl; + cout << "testing swaps" << std::endl; unsigned dim = m.row_count(); dense_matrix original(m); permutation_matrix q(dim); @@ -596,12 +595,12 @@ void test_swap_cols_with_permutation(sparse_matrix& m){ unsigned row1 = lrand48() % dim; unsigned row2 = lrand48() % dim; if (row1 == row2) continue; - cout << "swap " << row1 << " " << row2 << endl; + cout << "swap " << row1 << " " << row2 << std::endl; m.swap_rows(row1, row2); q.transpose_from_right(row1, row2); lean_assert(original == q * m); print_matrix(m); - cout << endl; + cout << std::endl; } } @@ -697,7 +696,7 @@ void test_pivot_like_swaps_and_pivot(){ for (auto & t : row) { cout << t << ","; } - cout << endl; + cout << std::endl; lp_settings settings; m.pivot_row_to_row(pivot_row, alpha, target_row, settings); m.pivot_row_to_row(pivot_row_0, beta, target_row, settings); @@ -963,7 +962,7 @@ void test_conjugate_eta_matrix() { l.set_diagonal_element(10); - cout << "l" << endl; + cout << "l" << std::endl; print_matrix(l); dense_matrix lcopy(l); @@ -972,12 +971,12 @@ void test_conjugate_eta_matrix() { permutation_matrix pr = p.get_inverse(); auto conj = lcopy * pr; - cout << "U*pr" << endl; + cout << "U*pr" << std::endl; print_matrix(conj); conj = p * conj; - cout << "conj " << endl; + cout << "conj " << std::endl; print_matrix(conj); - cout << "l" << endl; + cout << "l" << std::endl; print_matrix(l); lean_assert(conj == l); } @@ -1135,19 +1134,19 @@ void update_settings(argument_parser & args_parser, lp_settings& settings) { if (get_int_from_args_parser("--percent_for_enter", args_parser, n)) settings.percent_of_entering_to_check = n; if (get_int_from_args_parser("--partial_pivot", args_parser, n)) { - cout << "setting partial pivot constant to " << n << endl; + cout << "setting partial pivot constant to " << n << std::endl; settings.c_partial_pivoting = n; } if (get_int_from_args_parser("--density", args_parser, n)) { double density = static_cast(n) / 100.0; - cout << "setting density to " << density << endl; + cout << "setting density to " << density << std::endl; settings.density_threshold = density; } if (get_int_from_args_parser("--maxng", args_parser, n)) settings.max_number_of_iterations_with_no_improvements = n; double d; if (get_double_from_args_parser("--harris_toler", args_parser, d)) { - cout << "setting harris_feasibility_tolerance to " << d << endl; + cout << "setting harris_feasibility_tolerance to " << d << std::endl; settings.harris_feasibility_tolerance = d; } } @@ -1172,7 +1171,7 @@ void print_x(mps_reader & reader, lp_solver * so for (auto name : reader.column_names()) { std::cout << name << "=" << solver->get_column_value_by_name(name) << ' '; } - cout << endl; + cout << std::endl; } void compare_solutions(mps_reader & reader, lp_solver * solver, lp_solver * solver0) { @@ -1180,7 +1179,7 @@ void compare_solutions(mps_reader & reader, lp_solverget_column_value_by_name(name); double b = solver0->get_column_value_by_name(name); if (!values_are_one_percent_close(a, b)) { - cout << "different values for " << name << ":" << a << " and " << b << endl; + cout << "different values for " << name << ":" << a << " and " << b << std::endl; } } } @@ -1197,7 +1196,7 @@ void solve_mps_double(std::string file_name, bool look_for_min, unsigned max_ite setup_solver(max_iterations, time_limit, look_for_min, args_parser, solver); int begin = get_millisecond_count(); if (dual) { - cout << "solving for dual" << endl; + cout << "solving for dual" << std::endl; } solver->find_maximal_solution(); int span = get_millisecond_span(begin); @@ -1212,13 +1211,13 @@ void solve_mps_double(std::string file_name, bool look_for_min, unsigned max_ite } std::cout << "cost = " << cost << std::endl; } - cout << "processed in " << span / 1000.0 << " seconds, running for " << solver->m_total_iterations << " iterations" << endl; + cout << "processed in " << span / 1000.0 << " seconds, running for " << solver->m_total_iterations << " iterations" << std::endl; if (compare_with_primal) { auto * primal_solver = reader.create_solver(false); setup_solver(max_iterations, time_limit, look_for_min, args_parser, primal_solver); primal_solver->find_maximal_solution(); if (solver->get_status() != primal_solver->get_status()) { - cout << "statuses are different: dual " << lp_status_to_string(solver->get_status()) << " primal = " << lp_status_to_string(primal_solver->get_status()) << endl; + cout << "statuses are different: dual " << lp_status_to_string(solver->get_status()) << " primal = " << lp_status_to_string(primal_solver->get_status()) << std::endl; } else { if (solver->get_status() == lp_status::OPTIMAL) { double cost = solver->get_current_cost(); @@ -1229,11 +1228,11 @@ void solve_mps_double(std::string file_name, bool look_for_min, unsigned max_ite if (look_for_min) { primal_cost = -primal_cost; } - cout << "primal cost = " << primal_cost << endl; + cout << "primal cost = " << primal_cost << std::endl; if (!values_are_one_percent_close(cost, primal_cost)) { compare_solutions(reader, primal_solver, solver); print_x(reader, primal_solver); - cout << "dual cost is " << cost << ", but primal cost is " << primal_cost << endl; + cout << "dual cost is " << cost << ", but primal cost is " << primal_cost << std::endl; lean_assert(false); } } @@ -1272,7 +1271,7 @@ void solve_mps_rational(std::string file_name, bool look_for_min, unsigned max_i } std::cout << "cost = " << cost.get_double() << std::endl; } - cout << "processed in " << get_millisecond_span(begin) / 1000.0 << " seconds, running for " << solver->m_total_iterations << " iterations" << endl; + cout << "processed in " << get_millisecond_span(begin) / 1000.0 << " seconds, running for " << solver->m_total_iterations << " iterations" << std::endl; delete solver; } else { std::cout << "cannot process " << file_name << std::endl; @@ -1360,7 +1359,7 @@ void test_binary_priority_queue() { for (unsigned i = 0; i < 10; i++) { unsigned de = q.dequeue(); lean_assert(i == de); - cout << de << endl; + cout << de << std::endl; } q.enqueue(2, 2); q.enqueue(1, 1); @@ -1384,11 +1383,11 @@ void test_binary_priority_queue() { while (q.size() > 0) { unsigned d =q.dequeue(); lean_assert(t++ == d); - cout << d << endl; + cout << d << std::endl; } test_upair_queue(); - cout << " done" << endl; + cout << " done" << std::endl; } bool solution_is_feasible(std::string file_name, const std::unordered_map & solution) { @@ -1411,7 +1410,7 @@ void solve_mps_with_known_solution(std::string file_name, std::unordered_mapfind_maximal_solution(); std::cout << "status is " << lp_status_to_string(solver->get_status()) << std::endl; if (status != solver->get_status()){ - cout << "status should be " << lp_status_to_string(status) << endl; + cout << "status should be " << lp_status_to_string(status) << std::endl; lean_assert(status == solver->get_status()); throw "status is wrong"; } @@ -1430,7 +1429,7 @@ void solve_mps_with_known_solution(std::string file_name, std::unordered_map &file_names, std::set & m void test_out_dir(string out_dir) { DIR *out_dir_p = opendir(out_dir.c_str()); if (out_dir_p == nullptr) { - cout << "creating directory " << out_dir << endl; + cout << "creating directory " << out_dir << std::endl; int res = mkdir(out_dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (res) { - cout << "Cannot open output directory \"" << out_dir << "\"" << endl; + cout << "Cannot open output directory \"" << out_dir << "\"" << std::endl; } return; } @@ -1648,13 +1647,13 @@ void find_dir_and_file_name(string a, string & dir, string& fn) { // todo: make it system independent size_t last_slash_pos = a.find_last_of("/"); if (last_slash_pos >= a.size()) { - cout << "cannot find file name in " << a << endl; + cout << "cannot find file name in " << a << std::endl; throw; } dir = a.substr(0, last_slash_pos); - // cout << "dir = " << dir << endl; + // cout << "dir = " << dir << std::endl; fn = a.substr(last_slash_pos + 1); - // cout << "fn = " << fn << endl; + // cout << "fn = " << fn << std::endl; } void process_test_file(string test_dir, string test_file_name, argument_parser & args_parser, string out_dir, unsigned max_iters, unsigned time_limit, unsigned & successes, unsigned & failures, unsigned & inconclusives); @@ -1689,7 +1688,7 @@ void solve_some_mps(argument_parser & args_parser) { std::cout<< "exception: "<< s << std::endl; } } - cout << "comparing with glpk: successes " << successes << ", failures " << failures << ", inconclusives " << inconclusives << endl; + cout << "comparing with glpk: successes " << successes << ", failures " << failures << ", inconclusives " << inconclusives << std::endl; return; } if (!solve_for_rational) { @@ -1807,7 +1806,7 @@ bool contains(string const & s, char const * pattern) { unordered_map * get_solution_from_glpsol_output(string & file_name) { ifstream file(file_name); if (!file.is_open()){ - cerr << "cannot open " << file_name << endl; + cerr << "cannot open " << file_name << std::endl; return nullptr; } string s; @@ -1815,7 +1814,7 @@ unordered_map * get_solution_from_glpsol_output(string & file_na do { s = read_line(end, file); if (end) { - cerr << "unexpected file end " << file_name << endl; + cerr << "unexpected file end " << file_name << std::endl; return nullptr; } if (contains(s, "Column name")){ @@ -1825,7 +1824,7 @@ unordered_map * get_solution_from_glpsol_output(string & file_na read_line(end, file); if (end) { - cerr << "unexpected file end " << file_name << endl; + cerr << "unexpected file end " << file_name << std::endl; return nullptr; } @@ -1834,7 +1833,7 @@ unordered_map * get_solution_from_glpsol_output(string & file_na do { s = read_line(end, file); if (end) { - cerr << "unexpected file end " << file_name << endl; + cerr << "unexpected file end " << file_name << std::endl; return nullptr; } auto split = string_split(s, " \t", false); @@ -1956,7 +1955,7 @@ void solve_test_flipped(bool dual) { // solving a problem with a constraint xj <= c, a flipped constraint char * home_dir = getenv("HOME"); if (home_dir == nullptr) { - cout << "cannot find home directory" << endl; + cout << "cannot find home directory" << std::endl; return; } string file_name = string(home_dir) + "/projects/lean/src/tests/util/lp/l4.mps"; @@ -1968,7 +1967,7 @@ void solve_test_flipped(bool dual) { solver->find_maximal_solution(); lean_assert(solver->get_status() == OPTIMAL); double x1_val = solver->get_column_value_by_name("X1"); - cout << "X1 = " << x1_val << endl; + cout << "X1 = " << x1_val << std::endl; mps_reader reader_(file_name); reader_.read(); auto solver_ = reader_.create_solver(dual); @@ -1977,7 +1976,7 @@ void solve_test_flipped(bool dual) { solver_-> unset_low_bound(j); solver_->set_upper_bound(j, x1_val + 1); solver_->find_maximal_solution(); - cout << "new X1 = " << solver_->get_column_value_by_name("X1") << endl; + cout << "new X1 = " << solver_->get_column_value_by_name("X1") << std::endl; lean_assert(fabs(x1_val - solver_->get_column_value_by_name("X1")) < 1e-10); delete solver; delete solver_; @@ -1989,7 +1988,7 @@ void print_chunk(T * arr, unsigned len) { for (unsigned i = 0; i < len; i++) { cout << arr[i] << ", "; } - cout << endl; + cout << std::endl; } struct mem_cpy_place_holder { @@ -2043,7 +2042,7 @@ int run_glpk(string file_name, string glpk_out_file_name, bool minimize, unsigne string get_status(string file_name) { std::ifstream f(file_name); if (!f.is_open()) { - cout << "cannot open " << file_name << endl; + cout << "cannot open " << file_name << std::endl; throw 0; } string str; @@ -2051,13 +2050,13 @@ string get_status(string file_name) { if (str.find("Status") != string::npos) { vector tokens = split_and_trim(str); if (tokens.size() != 2) { - cout << "unexpected Status string " << str << endl; + cout << "unexpected Status string " << str << std::endl; throw 0; } return tokens[1]; } } - cout << "cannot find the status line in " << file_name << endl; + cout << "cannot find the status line in " << file_name << std::endl; throw 0; } @@ -2072,7 +2071,7 @@ bool compare_statuses(string glpk_out_file_name, string lp_out_file_name, unsign return false; } else { cout << "glpsol and lp_tst disagree: glpsol status is " << glpk_status; - cout << " but lp_tst status is " << lp_tst_status << endl; + cout << " but lp_tst status is " << lp_tst_status << std::endl; failures++; return false; } @@ -2083,7 +2082,7 @@ bool compare_statuses(string glpk_out_file_name, string lp_out_file_name, unsign double get_glpk_cost(string file_name) { std::ifstream f(file_name); if (!f.is_open()) { - cout << "cannot open " << file_name << endl; + cout << "cannot open " << file_name << std::endl; throw 0; } string str; @@ -2091,20 +2090,20 @@ double get_glpk_cost(string file_name) { if (str.find("Objective") != string::npos) { vector tokens = split_and_trim(str); if (tokens.size() != 5) { - cout << "unexpected Objective string " << str << endl; + cout << "unexpected Objective string " << str << std::endl; throw 0; } return atof(tokens[3].c_str()); } } - cout << "cannot find the Objective line in " << file_name << endl; + cout << "cannot find the Objective line in " << file_name << std::endl; throw 0; } double get_lp_tst_cost(string file_name) { std::ifstream f(file_name); if (!f.is_open()) { - cout << "cannot open " << file_name << endl; + cout << "cannot open " << file_name << std::endl; throw 0; } string str; @@ -2115,13 +2114,13 @@ double get_lp_tst_cost(string file_name) { } } if (cost_string.size() == 0) { - cout << "cannot find the cost line in " << file_name << endl; + cout << "cannot find the cost line in " << file_name << std::endl; throw 0; } vector tokens = split_and_trim(cost_string); if (tokens.size() != 3) { - cout << "unexpected cost string " << cost_string << endl; + cout << "unexpected cost string " << cost_string << std::endl; throw 0; } return atof(tokens[2].c_str()); @@ -2149,7 +2148,7 @@ void compare_costs(string glpk_out_file_name, successes++; } else { failures++; - cout << "glpsol cost is " << a << " lp_tst cost is " << b << endl; + cout << "glpsol cost is " << a << " lp_tst cost is " << b << std::endl; } } @@ -2158,9 +2157,9 @@ void compare_costs(string glpk_out_file_name, void compare_with_glpk(string glpk_out_file_name, string lp_out_file_name, unsigned & successes, unsigned & failures, string lp_file_name) { std::unordered_map * solution_table = get_solution_from_glpsol_output(glpk_out_file_name); if (solution_is_feasible(lp_file_name, *solution_table)) { - cout << "glpk solution is feasible" << endl; + cout << "glpk solution is feasible" << std::endl; } else { - cout << "glpk solution is infeasible" << endl; + cout << "glpk solution is infeasible" << std::endl; } delete solution_table; if (compare_statuses(glpk_out_file_name, lp_out_file_name, successes, failures)) { @@ -2176,14 +2175,14 @@ void process_test_file(string test_dir, string test_file_name, argument_parser & string input_file_name = test_dir + "/" + test_file_name; if (input_file_name[input_file_name.size() - 1] == '~') { - // cout << "ignoring " << input_file_name << endl; + // cout << "ignoring " << input_file_name << std::endl; return; } - cout <<"processing " << input_file_name << endl; + cout <<"processing " << input_file_name << std::endl; std::ofstream out(full_lp_tst_out_name); if (!out.is_open()) { - cout << "cannot open file " << full_lp_tst_out_name << endl; + cout << "cannot open file " << full_lp_tst_out_name << std::endl; throw 0; } std::streambuf *coutbuf = std::cout.rdbuf(); // save old buffer @@ -2196,7 +2195,7 @@ void process_test_file(string test_dir, string test_file_name, argument_parser & solve_mps(input_file_name, minimize, max_iters, time_limit, use_mpq, dual, false, args_parser); } catch(...) { - cout << "catching the failure" << endl; + cout << "catching the failure" << std::endl; failures++; std::cout.rdbuf(coutbuf); // reset to standard output again return; @@ -2207,7 +2206,7 @@ void process_test_file(string test_dir, string test_file_name, argument_parser & string glpk_out_file_name = out_dir + "/" + create_output_file_name_for_glpsol(minimize, string(test_file_name)); int glpk_exit_code = run_glpk(input_file_name, glpk_out_file_name, minimize, time_limit); if (glpk_exit_code != 0) { - cout << "glpk failed" << endl; + cout << "glpk failed" << std::endl; inconclusives++; } else { compare_with_glpk(glpk_out_file_name, full_lp_tst_out_name, successes, failures, input_file_name); @@ -2215,13 +2214,13 @@ void process_test_file(string test_dir, string test_file_name, argument_parser & } } -vector> get_file_list_of_dir(string test_file_dir) { +std::vector> get_file_list_of_dir(std::string test_file_dir) { DIR *dir; if ((dir = opendir(test_file_dir.c_str())) == nullptr) { - cout << "Cannot open directory " << test_file_dir << endl; + std::cout << "Cannot open directory " << test_file_dir << std::endl; throw 0; } - vector> ret; + std::vector> ret; struct dirent entry; struct dirent* result; int return_code; @@ -2231,7 +2230,7 @@ vector> get_file_list_of_dir(string test_file_dir) { DIR *tmp_dp = opendir(entry.d_name); struct stat file_record; if (tmp_dp == nullptr) { - string s = test_file_dir+ "/" + entry.d_name; + std::string s = test_file_dir+ "/" + entry.d_name; int stat_ret = stat(s.c_str(), & file_record); if (stat_ret!= -1) { ret.push_back(make_pair(entry.d_name, file_record.st_size)); @@ -2249,24 +2248,24 @@ vector> get_file_list_of_dir(string test_file_dir) { struct file_size_comp { - unordered_map& m_file_sizes; - file_size_comp(unordered_map& fs) :m_file_sizes(fs) {} - int operator()(string a, string b) { - cout << m_file_sizes.size() << endl; - cout << a << endl; - cout << b << endl; + unordered_map& m_file_sizes; + file_size_comp(unordered_map& fs) :m_file_sizes(fs) {} + int operator()(std::string a, std::string b) { + std::cout << m_file_sizes.size() << std::endl; + std::cout << a << std::endl; + std::cout << b << std::endl; auto ls = m_file_sizes.find(a); - cout << "fa" << endl; + std::cout << "fa" << std::endl; auto rs = m_file_sizes.find(b); - cout << "fb" << endl; + std::cout << "fb" << std::endl; if (ls != m_file_sizes.end() && rs != m_file_sizes.end()) { - cout << "fc " << endl; + std::cout << "fc " << std::endl; int r = (*ls < *rs? -1: (*ls > *rs)? 1 : 0); - cout << "calc r " << endl; + std::cout << "calc r " << std::endl; return r; } else { - cout << "sc " << endl; + std::cout << "sc " << std::endl; return 0; } } @@ -2274,25 +2273,25 @@ struct file_size_comp { struct sort_pred { - bool operator()(const std::pair &left, const std::pair &right) { + bool operator()(const std::pair &left, const std::pair &right) { return left.second < right.second; } }; -void test_files_from_directory(string test_file_dir, argument_parser & args_parser) { - cout << "loading files from directory \"" << test_file_dir << "\"" << endl; - string out_dir = args_parser.get_option_value("--out_dir"); +void test_files_from_directory(std::string test_file_dir, argument_parser & args_parser) { + std::cout << "loading files from directory \"" << test_file_dir << "\"" << std::endl; + std::string out_dir = args_parser.get_option_value("--out_dir"); if (out_dir.size() == 0) { out_dir = "/tmp/test"; } DIR *out_dir_p = opendir(out_dir.c_str()); if (out_dir_p == nullptr) { - cout << "Cannot open output directory \"" << out_dir << "\"" << endl; + std::cout << "Cannot open output directory \"" << out_dir << "\"" << std::endl; return; } closedir(out_dir_p); - vector> files = get_file_list_of_dir(test_file_dir); + std::vector> files = get_file_list_of_dir(test_file_dir); std::sort(files.begin(), files.end(), sort_pred()); unsigned max_iters, time_limit; get_time_limit_and_max_iters_from_parser(args_parser, time_limit, max_iters); @@ -2300,12 +2299,12 @@ void test_files_from_directory(string test_file_dir, argument_parser & args_pars for (auto & t : files) { process_test_file(test_file_dir, t.first, args_parser, out_dir, max_iters, time_limit, successes, failures, inconclusives); } - cout << "comparing with glpk: successes " << successes << ", failures " << failures << ", inconclusives " << inconclusives << endl; + std::cout << "comparing with glpk: successes " << successes << ", failures " << failures << ", inconclusives " << inconclusives << std::endl; } -unordered_map get_solution_map(lp_solver * lps, mps_reader & reader) { - unordered_map ret; +unordered_map get_solution_map(lp_solver * lps, mps_reader & reader) { + unordered_map ret; for (auto it : reader.column_names()) { ret[it] = lps->get_column_value_by_name(it); } @@ -2313,7 +2312,7 @@ unordered_map get_solution_map(lp_solver * lps, mps_reade } void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_reader * reader) { - string maxng = args_parser.get_option_value("--maxng"); + std::string maxng = args_parser.get_option_value("--maxng"); if (maxng.size() > 0) { solver->settings().max_number_of_iterations_with_no_improvements = atoi(maxng.c_str()); } @@ -2323,34 +2322,34 @@ void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_read if (args_parser.option_is_used("--mpq")) { solver->settings().use_double_solver_for_lar = false; } - string iter = args_parser.get_option_value("--max_iters"); + std::string iter = args_parser.get_option_value("--max_iters"); if (iter.size() > 0) { solver->settings().max_total_number_of_iterations = atoi(iter.c_str()); } if (args_parser.option_is_used("--compare_with_primal")){ if (reader == nullptr) { - cout << "cannot compare with primal, the reader is null " << endl; + std::cout << "cannot compare with primal, the reader is null " << std::endl; return; } auto * lps = reader->create_solver(false); lps->find_maximal_solution(); - unordered_map sol = get_solution_map(lps, *reader); + unordered_map sol = get_solution_map(lps, *reader); mpq inf = solver->get_infeasibility_of_solution(sol); - cout << "inf with primal = " << inf << endl; + std::cout << "inf with primal = " << inf << std::endl; return; } int begin = get_millisecond_count(); lp_status status = solver->check(); - cout << "status is " << lp_status_to_string(status) << ", processed for " << get_millisecond_span(begin) / 1000.0 <<" seconds, and " << solver->get_total_iterations() << " iterations" << endl; + std::cout << "status is " << lp_status_to_string(status) << ", processed for " << get_millisecond_span(begin) / 1000.0 <<" seconds, and " << solver->get_total_iterations() << " iterations" << std::endl; if (solver->get_status() == INFEASIBLE) { - buffer> evidence; + buffer> evidence; solver->get_infeasibility_evidence(evidence); } } -void test_lar_on_file(string file_name, argument_parser & args_parser) { +void test_lar_on_file(std::string file_name, argument_parser & args_parser) { lar_solver * solver = nullptr; - cout << "processing " << file_name << endl; + std::cout << "processing " << file_name << std::endl; if (args_parser.option_is_used("--smt")) { smt_reader reader(file_name); reader.read(); @@ -2374,16 +2373,16 @@ void test_lar_on_file(string file_name, argument_parser & args_parser) { delete solver; } -vector get_file_names_from_file_list(string filelist) { +vector get_file_names_from_file_list(std::string filelist) { ifstream file(filelist); if (!file.is_open()) { - cout << "cannot open " << filelist << endl; - return vector(); + std::cout << "cannot open " << filelist << std::endl; + return vector(); } - vector ret; + vector ret; bool end; do { - string s = read_line(end, file); + std::string s = read_line(end, file); if (end) break; if (s.size() == 0) @@ -2394,15 +2393,15 @@ vector get_file_names_from_file_list(string filelist) { } void test_lar_solver(argument_parser & args_parser) { - string file_name = args_parser.get_option_value("--file"); + std::string file_name = args_parser.get_option_value("--file"); if (file_name.size() > 0) { test_lar_on_file(file_name, args_parser); return; } - string file_list = args_parser.get_option_value("--filelist"); + std::string file_list = args_parser.get_option_value("--filelist"); if (file_list.size() > 0) { - for (string fn : get_file_names_from_file_list(file_list)) + for (std::string fn : get_file_names_from_file_list(file_list)) test_lar_on_file(fn, args_parser); return; } @@ -2417,7 +2416,7 @@ void test_numeric_pair() { a -= c; lean_assert (a == b + c); numeric_pair d = a * 2; - cout << a << endl; + std::cout << a << std::endl; lean_assert(b == b); lean_assert(b < a); lean_assert(b <= a); @@ -2429,15 +2428,15 @@ void test_numeric_pair() { lean_assert(b + b > a); lean_assert(mpq(2.1) * b + b > a); lean_assert(-b * mpq(2.1) - b < mpq(0.99) * a); - cout << - b * mpq(2.1) - b << endl; + std::cout << - b * mpq(2.1) - b << std::endl; lean_assert(-b *(mpq(2.1) + 1) == - b * mpq(2.1) - b); } void get_matrix_dimensions(ifstream & f, unsigned & m, unsigned & n) { - string line; + std::string line; getline(f, line); getline(f, line); - vector r = split_and_trim(line); + vector r = split_and_trim(line); m = atoi(r[1].c_str()); getline(f, line); r = split_and_trim(line); @@ -2446,7 +2445,7 @@ void get_matrix_dimensions(ifstream & f, unsigned & m, unsigned & n) { void read_row_cols(unsigned i, static_matrix& A, ifstream & f) { do { - string line; + std::string line; getline(f, line); if (line== "row_end") break; @@ -2459,13 +2458,13 @@ void read_row_cols(unsigned i, static_matrix& A, ifstream & f) { } bool read_row(static_matrix & A, ifstream & f) { - string line; + std::string line; getline(f, line); if (static_cast(line.find("row")) == -1) return false; auto r = split_and_trim(line); if (r[0] != "row") - cout << "wrong row line" << line << endl; + std::cout << "wrong row line" << line << std::endl; unsigned i = atoi(r[1].c_str()); read_row_cols(i, A, f); return true; @@ -2476,8 +2475,8 @@ void read_rows(static_matrix& A, ifstream & f) { } void read_basis(vector & basis, ifstream & f) { - cout << "reading basis" << endl; - string line; + std::cout << "reading basis" << std::endl; + std::string line; getline(f, line); lean_assert(line == "basis_start"); do { @@ -2490,7 +2489,7 @@ void read_basis(vector & basis, ifstream & f) { } void read_indexed_vector(indexed_vector & v, ifstream & f) { - string line; + std::string line; getline(f, line); lean_assert(line == "vector_start"); do { @@ -2500,18 +2499,18 @@ void read_indexed_vector(indexed_vector & v, ifstream & f) { unsigned i = atoi(r[0].c_str()); double val = atof(r[1].c_str()); v.set_value(val, i); - cout << "setting value " << i << " = " << val << endl; + std::cout << "setting value " << i << " = " << val << std::endl; } while (true); } -void check_lu_from_file(string lufile_name) { +void check_lu_from_file(std::string lufile_name) { ifstream f(lufile_name); if (!f.is_open()) { - cout << "cannot open file " << lufile_name << endl; + std::cout << "cannot open file " << lufile_name << std::endl; } unsigned m, n; get_matrix_dimensions(f, m, n); - cout << "init matrix " << m << " by " << n << endl; + std::cout << "init matrix " << m << " by " << n << std::endl; static_matrix A(m, n); read_rows(A, f); vector basis; @@ -2540,7 +2539,7 @@ void check_lu_from_file(string lufile_name) { } void test_square_dense_submatrix() { - cout << "testing square_dense_submatrix" << endl; + std::cout << "testing square_dense_submatrix" << std::endl; unsigned parent_dim = 7; sparse_matrix parent(parent_dim); fill_matrix(parent); @@ -2567,7 +2566,7 @@ void test_square_dense_submatrix() { m[i-index_start][j-index_start] = d[i][j]; print_matrix(m); - cout << endl; + std::cout << std::endl; #endif } @@ -2580,14 +2579,14 @@ int main(int argn, char * const * argv) { setup_args_parser(args_parser); if (!args_parser.parse()) { - cout << args_parser.m_error_message << endl; - cout << args_parser.usage_string(); + std::cout << args_parser.m_error_message << std::endl; + std::cout << args_parser.usage_string(); ret = 1; return finalize(ret); } - cout << "the options are " << endl; + std::cout << "the options are " << std::endl; args_parser.print(); - string lufile = args_parser.get_option_value("--checklu"); + std::string lufile = args_parser.get_option_value("--checklu"); if (lufile.size()) { check_lu_from_file(lufile); return finalize(0); @@ -2607,13 +2606,13 @@ int main(int argn, char * const * argv) { return finalize(0); } if (args_parser.option_is_used("--lar")){ - cout <<"calling test_lar_solver" << endl; + std::cout <<"calling test_lar_solver" << std::endl; test_lar_solver(args_parser); return finalize(0); } - string file_list = args_parser.get_option_value("--filelist"); + std::string file_list = args_parser.get_option_value("--filelist"); if (file_list.size() > 0) { - for (string fn : get_file_names_from_file_list(file_list)) + for (std::string fn : get_file_names_from_file_list(file_list)) solve_mps(fn, args_parser); return finalize(0); } @@ -2658,7 +2657,7 @@ int main(int argn, char * const * argv) { get_time_limit_and_max_iters_from_parser(args_parser, time_limit, max_iters); bool dual = args_parser.option_is_used("--dual"); bool solve_for_rational = args_parser.option_is_used("--mpq"); - string file_name = args_parser.get_option_value("--file"); + std::string file_name = args_parser.get_option_value("--file"); if (file_name.size() > 0) { solve_mps(file_name, args_parser.option_is_used("--min"), max_iters, time_limit, solve_for_rational, dual, args_parser.option_is_used("--compare_with_primal"), args_parser); ret = 0; diff --git a/src/util/lp/binary_heap_priority_queue.h b/src/util/lp/binary_heap_priority_queue.h index 6300820f2..541429c64 100644 --- a/src/util/lp/binary_heap_priority_queue.h +++ b/src/util/lp/binary_heap_priority_queue.h @@ -4,19 +4,17 @@ Author: Lev Nachmanson */ - #pragma once #include namespace lean { -using std::vector; - // the elements with the smallest priority are dequeued first +// the elements with the smallest priority are dequeued first template class binary_heap_priority_queue { - vector m_priorities; + std::vector m_priorities; // indexing for A starts from 1 - vector m_heap; // keeps the elements of the queue - vector m_heap_inverse; // o = m_heap[m_heap_inverse[o]] + std::vector m_heap; // keeps the elements of the queue + std::vector m_heap_inverse; // o = m_heap[m_heap_inverse[o]] unsigned m_heap_size = 0; // is is the child place in heap @@ -33,15 +31,15 @@ class binary_heap_priority_queue { } void decrease_priority(unsigned o, T newPriority) { - m_priorities[o] = newPriority; - int i = m_heap_inverse[o]; - while (i > 1) { - if (m_priorities[m_heap[i]] < m_priorities[m_heap[i >> 1]]) - swap_with_parent(i); - else - break; - i >>= 1; - } + m_priorities[o] = newPriority; + int i = m_heap_inverse[o]; + while (i > 1) { + if (m_priorities[m_heap[i]] < m_priorities[m_heap[i >> 1]]) + swap_with_parent(i); + else + break; + i >>= 1; + } } public: @@ -56,13 +54,13 @@ public: for (int k = 0; k < 2; k++) { if (ch > m_heap_size) break; if (!(m_priorities[m_heap[i]] <= m_priorities[m_heap[ch]])){ - cout << "m_heap_size = " << m_heap_size << endl; - cout << "i = " << i << endl; - cout << "m_heap[i] = " << m_heap[i] << endl; - cout << "ch = " << ch << endl; - cout << "m_heap[ch] = " << m_heap[ch] << endl; - cout << "m_priorities[m_heap[i]] = " << m_priorities[m_heap[i]] << endl; - cout << "m_priorities[m_heap[ch]] = " << m_priorities[m_heap[ch]]<< endl; + std::cout << "m_heap_size = " << m_heap_size << std::endl; + std::cout << "i = " << i << std::endl; + std::cout << "m_heap[i] = " << m_heap[i] << std::endl; + std::cout << "ch = " << ch << std::endl; + std::cout << "m_heap[ch] = " << m_heap[ch] << std::endl; + std::cout << "m_priorities[m_heap[i]] = " << m_priorities[m_heap[i]] << std::endl; + std::cout << "m_priorities[m_heap[ch]] = " << m_priorities[m_heap[ch]]<< std::endl; return false; } ch++; @@ -109,7 +107,7 @@ public: m_priorities(n), m_heap(n + 1), // because the indexing for A starts from 1 m_heap_inverse(n, -1) - { } + { } void clear() { m_heap_size = 0; @@ -127,15 +125,15 @@ public: } void enqueue_new(unsigned o, const T& priority) { - m_heap_size++; - int i = m_heap_size; - lean_assert(o < m_priorities.size()); - m_priorities[o] = priority; - put_at(i, o); - while (i > 1 && m_priorities[m_heap[i >> 1]] > priority) { - swap_with_parent(i); - i >>= 1; - } + m_heap_size++; + int i = m_heap_size; + lean_assert(o < m_priorities.size()); + m_priorities[o] = priority; + put_at(i, o); + while (i > 1 && m_priorities[m_heap[i >> 1]] > priority) { + swap_with_parent(i); + i >>= 1; + } } // This method can work with an element that is already in the queue. // In this case the priority will be changed and the queue adjusted. @@ -168,9 +166,7 @@ public: /// return the first element of the queue and removes it from the queue unsigned dequeue_and_get_priority(T & priority) { - if (m_heap_size == 0) { - throw "invalid size"; - } + lean_assert(m_heap_size != 0); int ret = m_heap[1]; priority = m_priorities[ret]; put_the_last_at_the_top_and_fix_the_heap(); @@ -202,7 +198,7 @@ public: m_heap_size--; } } - /// return the first element of the queue and removes it from the queue + /// return the first element of the queue and removes it from the queue unsigned dequeue() { lean_assert(m_heap_size); int ret = m_heap[1]; @@ -212,16 +208,16 @@ public: } void print() { - vector index; - vector prs; + std::vector index; + std::vector prs; while (size()) { T prior; int j = dequeue_and_get_priority(prior); index.push_back(j); prs.push_back(prior); - cout << "(" << j << ", " << prior << ")"; + std::cout << "(" << j << ", " << prior << ")"; } - cout << endl; + std::cout << std::endl; // restore the queue for (int i = 0; i < index.size(); i++) enqueue(index[i], prs[i]); diff --git a/src/util/lp/binary_heap_upair_queue.h b/src/util/lp/binary_heap_upair_queue.h index 59f0ed941..8e6f44488 100644 --- a/src/util/lp/binary_heap_upair_queue.h +++ b/src/util/lp/binary_heap_upair_queue.h @@ -18,8 +18,8 @@ namespace lean { template class binary_heap_upair_queue { binary_heap_priority_queue m_q; - unordered_map m_pairs_to_index; - vector m_pairs; // inverse to index + std::unordered_map m_pairs_to_index; + std::vector m_pairs; // inverse to index std::vector m_available_spots; public: binary_heap_upair_queue(unsigned size) : m_q(size), m_pairs(size) { @@ -113,7 +113,8 @@ public: unsigned j = p.second; auto it = tmp.find(j); if (it != tmp.end()) { - cout << "for pair (" << p.first.first << ", " << p.first.second << "), the index " << j << " is already inside " << endl; + std::cout << "for pair (" << p.first.first << ", " << p.first.second << "), the index " << j + << " is already inside " << std::endl; lean_assert(false); } else { tmp.insert(j); diff --git a/src/util/lp/canonic_left_side.h b/src/util/lp/canonic_left_side.h index bc898200a..318271164 100644 --- a/src/util/lp/canonic_left_side.h +++ b/src/util/lp/canonic_left_side.h @@ -11,74 +11,74 @@ #include namespace lean { - typedef unsigned var_index; - typedef unsigned constraint_index; - enum lconstraint_kind { - LE = -2, LT = -1 , GE = 2, GT = 1, EQ = 0 - }; +typedef unsigned var_index; +typedef unsigned constraint_index; +enum lconstraint_kind { + LE = -2, LT = -1 , GE = 2, GT = 1, EQ = 0 +}; - class lar_normalized_constraint; // forward definition - bool compare(const pair & a, const pair & b) { - return a.second < b.second; +class lar_normalized_constraint; // forward definition +bool compare(const pair & a, const pair & b) { + return a.second < b.second; +} + +class canonic_left_side { +public: + int m_row_index = -1; + int m_column_index = -1; // this is the column of the left side variable in the matrix + std::vector> m_coeffs; + column_info m_column_info; + lar_normalized_constraint * m_low_bound_witness = nullptr; + lar_normalized_constraint * m_upper_bound_witness = nullptr; + + canonic_left_side(buffer> buffer) { + for (auto it : buffer) { + if (numeric_traits::is_zero(it.first)) continue; + m_coeffs.push_back(it); + } + + std::sort(m_coeffs.begin(), m_coeffs.end(), compare); + normalize(); } - class canonic_left_side { - public: - int m_row_index = -1; - int m_column_index = -1; // this is the column of the left side variable in the matrix - std::vector> m_coeffs; - column_info m_column_info; - lar_normalized_constraint * m_low_bound_witness = nullptr; - lar_normalized_constraint * m_upper_bound_witness = nullptr; + void set_name(std::string name) { + m_column_info.set_name(name); + } - canonic_left_side(buffer> buffer) { - for (auto it : buffer) { - if (numeric_traits::is_zero(it.first)) continue; - m_coeffs.push_back(it); - } + unsigned size() const { return m_coeffs.size(); } - std::sort(m_coeffs.begin(), m_coeffs.end(), compare); - normalize(); + void normalize() { + if (m_coeffs.size() == 0) return; + auto t = m_coeffs[0].first; + for (auto & it : m_coeffs) + it.first /= t; + } + + bool operator==(const canonic_left_side& a) const { + if (m_coeffs.size() != a.m_coeffs.size()) return false; + for (unsigned i = 0; i < m_coeffs.size(); i++) { + if (m_coeffs[i] != a.m_coeffs[i]) + return false; } + return true; + } - void set_name(string name) { - m_column_info.set_name(name); + std::size_t hash_of_ls() const { + std::size_t ret = 0; + std::hash> hash_fun; + for (auto v : m_coeffs) { + ret |= (hash_fun(v) << 2); } + return ret; + } +}; - unsigned size() const { return m_coeffs.size(); } - - void normalize() { - if (m_coeffs.size() == 0) return; - auto t = m_coeffs[0].first; - for (auto & it : m_coeffs) - it.first /= t; - } - - bool operator==(const canonic_left_side& a) const { - if (m_coeffs.size() != a.m_coeffs.size()) return false; - for (unsigned i = 0; i < m_coeffs.size(); i++) { - if (m_coeffs[i] != a.m_coeffs[i]) - return false; - } - return true; - } - - std::size_t hash_of_ls() const { - std::size_t ret = 0; - std::hash> hash_fun; - for (auto v : m_coeffs) { - ret |= (hash_fun(v) << 2); - } - return ret; - } - }; - - struct hash_and_equal_of_canonic_left_side_struct { - std::size_t operator() (const canonic_left_side* ls) const { - return ls->hash_of_ls(); - } - bool operator() (const canonic_left_side* a, const canonic_left_side* b) const { - return (*a) == (*b); - } - }; +struct hash_and_equal_of_canonic_left_side_struct { + std::size_t operator() (const canonic_left_side* ls) const { + return ls->hash_of_ls(); + } + bool operator() (const canonic_left_side* a, const canonic_left_side* b) const { + return (*a) == (*b); + } +}; } diff --git a/src/util/lp/column_info.h b/src/util/lp/column_info.h index 6df23f859..df1697b77 100644 --- a/src/util/lp/column_info.h +++ b/src/util/lp/column_info.h @@ -13,12 +13,9 @@ #include #include namespace lean { -using std::vector; -using std::tuple; - template class column_info { - string m_name; + std::string m_name; bool m_low_bound_is_set = false; bool m_low_bound_is_strict = false; bool m_upper_bound_is_set = false; @@ -124,11 +121,11 @@ public: m_cost = cost; } - void set_name(string const & s) { + void set_name(std::string const & s) { m_name = s; } - string get_name() const { + std::string get_name() const { return m_name; } diff --git a/src/util/lp/core_solver_pretty_printer.h b/src/util/lp/core_solver_pretty_printer.h index be4681f6c..616a6a195 100644 --- a/src/util/lp/core_solver_pretty_printer.h +++ b/src/util/lp/core_solver_pretty_printer.h @@ -13,6 +13,8 @@ template class lp_core_solver_base; // forward definiti template class core_solver_pretty_printer { + template using vector = std::vector; + typedef std::string string; lp_core_solver_base & m_core_solver; vector m_column_widths; vector> m_A; @@ -207,7 +209,7 @@ public: } int blanks = m_title_width + 1 - m_x_title.size(); - cout << m_x_title; + std::cout << m_x_title; print_blanks(blanks); auto bh = m_core_solver.m_x; @@ -215,9 +217,9 @@ public: string s = T_to_string(bh[i]); int blanks = m_column_widths[i] - s.size(); print_blanks(blanks); - cout << s << " "; // the column interval + std::cout << s << " "; // the column interval } - cout << endl; + std::cout << std::endl; } std::string get_low_bound_string(unsigned j) { @@ -228,7 +230,7 @@ public: if (m_core_solver.low_bounds_are_set()) return T_to_string(m_core_solver.low_bound_value(j)); else - return string("0"); + return std::string("0"); break; default: return std::string(); @@ -253,16 +255,16 @@ public: return; } int blanks = m_title_width + 1 - m_low_bounds_title.size(); - cout << m_low_bounds_title; + std::cout << m_low_bounds_title; print_blanks(blanks); for (unsigned i = 0; i < ncols(); i++) { string s = get_low_bound_string(i); int blanks = m_column_widths[i] - s.size(); print_blanks(blanks); - cout << s << " "; // the column interval + std::cout << s << " "; // the column interval } - cout << endl; + std::cout << std::endl; } void print_upps() { @@ -270,16 +272,16 @@ public: return; } int blanks = m_title_width + 1 - m_upp_bounds_title.size(); - cout << m_upp_bounds_title; + std::cout << m_upp_bounds_title; print_blanks(blanks); for (unsigned i = 0; i < ncols(); i++) { string s = get_upp_bound_string(i); int blanks = m_column_widths[i] - s.size(); print_blanks(blanks); - cout << s << " "; // the column interval + std::cout << s << " "; // the column interval } - cout << endl; + std::cout << std::endl; } string get_exact_column_norm_string(unsigned col) { @@ -288,28 +290,28 @@ public: void print_exact_norms() { int blanks = m_title_width + 1 - m_exact_norm_title.size(); - cout << m_exact_norm_title; + std::cout << m_exact_norm_title; print_blanks(blanks); for (unsigned i = 0; i < ncols(); i++) { string s = get_exact_column_norm_string(i); int blanks = m_column_widths[i] - s.size(); print_blanks(blanks); - cout << s << " "; + std::cout << s << " "; } - cout << endl; + std::cout << std::endl; } void print_approx_norms() { int blanks = m_title_width + 1 - m_approx_norm_title.size(); - cout << m_approx_norm_title; + std::cout << m_approx_norm_title; print_blanks(blanks); for (unsigned i = 0; i < ncols(); i++) { string s = T_to_string(m_core_solver.m_column_norms[i]); int blanks = m_column_widths[i] - s.size(); print_blanks(blanks); - cout << s << " "; + std::cout << s << " "; } - cout << endl; + std::cout << std::endl; } void print() { @@ -324,12 +326,12 @@ public: print_upps(); print_exact_norms(); print_approx_norms(); - cout << endl; + std::cout << std::endl; } void print_basis_heading() { int blanks = m_title_width + 1 - m_basis_heading_title.size(); - cout << m_basis_heading_title; + std::cout << m_basis_heading_title; print_blanks(blanks); if (ncols() == 0) { @@ -340,9 +342,9 @@ public: string s = T_to_string(bh[i]); int blanks = m_column_widths[i] - s.size(); print_blanks(blanks); - cout << s << " "; // the column interval + std::cout << s << " "; // the column interval } - cout << endl; + std::cout << std::endl; } void print_bottom_line() { @@ -351,7 +353,7 @@ public: void print_cost() { int blanks = m_title_width + 1 - m_cost_title.size(); - cout << m_cost_title; + std::cout << m_cost_title; print_blanks(blanks); print_given_rows(m_costs, m_cost_signs, m_core_solver.get_cost()); } @@ -363,18 +365,18 @@ public: int number_of_blanks = width - s.size(); lean_assert(number_of_blanks >= 0); print_blanks(number_of_blanks); - cout << s << ' '; + std::cout << s << ' '; if (col < row.size() - 1) { - cout << signs[col + 1] << ' '; + std::cout << signs[col + 1] << ' '; } } - cout << '='; + std::cout << '='; string rs = T_to_string(rst); int nb = m_rs_width - rs.size(); lean_assert(nb >= 0); print_blanks(nb + 1); - cout << rs << std::endl; + std::cout << rs << std::endl; } void print_row(unsigned i){ diff --git a/src/util/lp/eta_matrix.h b/src/util/lp/eta_matrix.h index 4477fe892..034bdb1a4 100644 --- a/src/util/lp/eta_matrix.h +++ b/src/util/lp/eta_matrix.h @@ -8,172 +8,147 @@ #pragma once namespace lean { - // This is the sum of a unit matrix and a one-column matrix - template - class eta_matrix - : public tail_matrix { +// This is the sum of a unit matrix and a one-column matrix +template +class eta_matrix + : public tail_matrix { #ifdef LEAN_DEBUG - unsigned m_length; + unsigned m_length; #endif - unsigned m_column_index; - sparse_vector m_column_vector; - T m_diagonal_element; - public: + unsigned m_column_index; + sparse_vector m_column_vector; + T m_diagonal_element; +public: #ifdef LEAN_DEBUG - eta_matrix(unsigned column_index, unsigned length): + eta_matrix(unsigned column_index, unsigned length): #else - eta_matrix(unsigned column_index): + eta_matrix(unsigned column_index): #endif #ifdef LEAN_DEBUG - m_length(length), + m_length(length), #endif - m_column_index(column_index) { + m_column_index(column_index) { + } + + void print() { + print_matrix(*this); + } + + bool is_unit() { + return m_column_vector.size() == 0 && m_diagonal_element == 1; + } + + void set_diagonal_element(T const & diagonal_element) { + lean_assert(!lp_settings::is_eps_small_general(diagonal_element, 1e-12)); + m_diagonal_element = diagonal_element; + } + + const T & get_diagonal_element() const { + return m_diagonal_element; + } + + void apply_from_left(std::vector & w, lp_settings & ) { + auto w_at_column_index = w[m_column_index]; + w[m_column_index] /= m_diagonal_element; + for (auto it = sparse_vector_iterator(m_column_vector); !it.done(); it.move()) { + w[it.index()] += w_at_column_index * it.value(); + } + } + + template + void apply_from_left_local(indexed_vector & w, lp_settings & settings) { + const L w_at_column_index = w[m_column_index]; + if (is_zero(w_at_column_index)) return; + + if (settings.abs_val_is_smaller_than_drop_tolerance(w[m_column_index] /= m_diagonal_element)) { + w[m_column_index] = zero_of_type(); + w.erase_from_index(m_column_index); } - - // T & get_column_element(unsigned j) { - // return m_column[j]; - // } - - void print() { - print_matrix(*this); - } - - bool is_unit() { - return m_column_vector.size() == 0 && m_diagonal_element == 1; - } - - void set_diagonal_element(T const & diagonal_element) { - lean_assert(!lp_settings::is_eps_small_general(diagonal_element, 1e-12)); - m_diagonal_element = diagonal_element; - } - - const T & get_diagonal_element() const { - return m_diagonal_element; - } - - void apply_from_left(vector & w, lp_settings & ) { - auto w_at_column_index = w[m_column_index]; - w[m_column_index] /= m_diagonal_element; - for (auto it = sparse_vector_iterator(m_column_vector); !it.done(); it.move()) { - w[it.index()] += w_at_column_index * it.value(); - } - } - - template - void apply_from_left_local(indexed_vector & w, lp_settings & settings) { - const L w_at_column_index = w[m_column_index]; - if (is_zero(w_at_column_index)) return; - - if (settings.abs_val_is_smaller_than_drop_tolerance(w[m_column_index] /= m_diagonal_element)) { - w[m_column_index] = zero_of_type(); - w.erase_from_index(m_column_index); - } - - for (auto it = sparse_vector_iterator(m_column_vector); !it.done(); it.move()) { - unsigned i = it.index(); - if (is_zero(w[i])) { - L v = w[i] = w_at_column_index * it.value(); - if (settings.abs_val_is_smaller_than_drop_tolerance(v)) { - w[i] = zero_of_type(); - continue; - } - w.m_index.push_back(i); - } else { - L v = w[i] += w_at_column_index * it.value(); // todo indexed_vector - if (settings.abs_val_is_smaller_than_drop_tolerance(v)) { - w[i] = zero_of_type(); - w.erase_from_index(i); - } + for (auto it = sparse_vector_iterator(m_column_vector); !it.done(); it.move()) { + unsigned i = it.index(); + if (is_zero(w[i])) { + L v = w[i] = w_at_column_index * it.value(); + if (settings.abs_val_is_smaller_than_drop_tolerance(v)) { + w[i] = zero_of_type(); + continue; + } + w.m_index.push_back(i); + } else { + L v = w[i] += w_at_column_index * it.value(); // todo indexed_vector + if (settings.abs_val_is_smaller_than_drop_tolerance(v)) { + w[i] = zero_of_type(); + w.erase_from_index(i); } } } + } - void apply_from_left_to_T(indexed_vector & w, lp_settings & settings) { - apply_from_left_local(w, settings); - } + void apply_from_left_to_T(indexed_vector & w, lp_settings & settings) { + apply_from_left_local(w, settings); + } - void push_back(unsigned row_index, T val ) { - lean_assert(row_index != m_column_index); - m_column_vector.push_back(row_index, val); - } + void push_back(unsigned row_index, T val ) { + lean_assert(row_index != m_column_index); + m_column_vector.push_back(row_index, val); + } - void apply_from_right(vector & w) { + void apply_from_right(std::vector & w) { #ifdef LEAN_DEBUG - // dense_matrix deb(*this); - // auto clone_w = clone_vector(w, get_number_of_rows()); - // deb.apply_from_right(clone_w); + // dense_matrix deb(*this); + // auto clone_w = clone_vector(w, get_number_of_rows()); + // deb.apply_from_right(clone_w); #endif - T t = w[m_column_index] / m_diagonal_element; - for (auto it = sparse_vector_iterator(m_column_vector); !it.done(); it.move()) { - t += w[it.index()] * it.value(); + T t = w[m_column_index] / m_diagonal_element; + for (auto it = sparse_vector_iterator(m_column_vector); !it.done(); it.move()) { + t += w[it.index()] * it.value(); + } + w[m_column_index] = t; +#ifdef LEAN_DEBUG + // lean_assert(vectors_are_equal(clone_w, w, get_number_of_rows())); + // delete clone_w; +#endif + } + + T get_elem(unsigned i, unsigned j) const { + if (j == m_column_index){ + if (i == j) { + return 1 / m_diagonal_element; } - w[m_column_index] = t; -#ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(clone_w, w, get_number_of_rows())); - // delete clone_w; -#endif + return m_column_vector[i]; } -// void apply_from_right(indexed_vector & w) { -// #ifdef LEAN_DEBUG -// // dense_matrix deb(*this); -// // auto clone_w = clone_vector(w, get_number_of_rows()); -// // deb.apply_from_right(clone_w); -// #endif -// T t = w[m_column_index] / m_diagonal_element; -// for (auto it = sparse_vector_iterator(m_column_vector); !it.done(); it.move()) { -// t += w[it.index()] * it.value(); -// } -// if (numeric_traits::is_zero(w[m_column_index])) { -// w.m_index.push_back(m_column_index); -// } -// w[m_column_index] = t; // we might get a zero here -// #ifdef LEAN_DEBUG -// // lean_assert(vectors_are_equal(clone_w, w, get_number_of_rows())); -// // delete clone_w; -// #endif -// } + return i == j ? numeric_traits::one() : numeric_traits::zero(); + } +#ifdef LEAN_DEBUG + unsigned row_count() const { return m_length; } + unsigned column_count() const { return m_length; } + void set_number_of_rows(unsigned /*m*/) { } + void set_number_of_columns(unsigned /*n*/) { } +#endif + sparse_vector_iterator get_sparse_vector_iterator() { + return sparse_vector_iterator(m_column_vector); + } - T get_elem(unsigned i, unsigned j) const { - if (j == m_column_index){ - if (i == j) { - return 1 / m_diagonal_element; - } - return m_column_vector[i]; - } - - return i == j ? numeric_traits::one() : numeric_traits::zero(); + void divide_by_diagonal_element() { + m_column_vector.divide(m_diagonal_element); + } + void conjugate_by_permutation(permutation_matrix & p) { + // this = p * this * p(-1) +#ifdef LEAN_DEBUG + // auto rev = p.get_reverse(); + // auto deb = ((*this) * rev); + // deb = p * deb; +#endif + m_column_index = p.get_rev(m_column_index); + for (auto & pair : m_column_vector.m_data) { + pair.first = p.get_rev(pair.first); } #ifdef LEAN_DEBUG - unsigned row_count() const { return m_length; } - unsigned column_count() const { return m_length; } - void set_number_of_rows(unsigned /*m*/) { } - void set_number_of_columns(unsigned /*n*/) { } -#endif - sparse_vector_iterator get_sparse_vector_iterator() { - return sparse_vector_iterator(m_column_vector); - } - - void divide_by_diagonal_element() { - m_column_vector.divide(m_diagonal_element); - } - void conjugate_by_permutation(permutation_matrix & p) { - // this = p * this * p(-1) -#ifdef LEAN_DEBUG - // auto rev = p.get_reverse(); - // auto deb = ((*this) * rev); - // deb = p * deb; -#endif - m_column_index = p.get_rev(m_column_index); - for (auto & pair : m_column_vector.m_data) { - pair.first = p.get_rev(pair.first); - } -#ifdef LEAN_DEBUG - // lean_assert(deb == *this); + // lean_assert(deb == *this); #endif -} - }; + } +}; } diff --git a/src/util/lp/indexed_value.h b/src/util/lp/indexed_value.h index e5dc62795..2f777a7c8 100644 --- a/src/util/lp/indexed_value.h +++ b/src/util/lp/indexed_value.h @@ -46,13 +46,13 @@ public: m_value = val; } }; - template - bool check_vector_for_small_values(indexed_vector & w, lp_settings & settings) { - for (unsigned i : w.m_index) { - const X & v = w[i]; - if ((!is_zero(v)) && settings.abs_val_is_smaller_than_drop_tolerance(v)) - return false; - } - return true; +template +bool check_vector_for_small_values(indexed_vector & w, lp_settings & settings) { + for (unsigned i : w.m_index) { + const X & v = w[i]; + if ((!is_zero(v)) && settings.abs_val_is_smaller_than_drop_tolerance(v)) + return false; } + return true; +} } diff --git a/src/util/lp/indexed_vector.h b/src/util/lp/indexed_vector.h index 88452347e..5a8a5e372 100644 --- a/src/util/lp/indexed_vector.h +++ b/src/util/lp/indexed_vector.h @@ -20,11 +20,6 @@ #include "util/lp/sparse_vector.h" #include namespace lean { -using std::string; -using std::cout; -using std::endl; -using std::vector; - template void print_vector(const T * t, unsigned l) { for (unsigned i = 0; i < l; i++) @@ -33,7 +28,7 @@ void print_vector(const T * t, unsigned l) { } template -void print_vector(const vector & t) { +void print_vector(const std::vector & t) { for (unsigned i = 0; i < t.size(); i++) std::cout << t[i] << " "; std::cout << std::endl; @@ -47,7 +42,7 @@ void print_vector(const buffer & t) { } template -void print_sparse_vector(const vector & t) { +void print_sparse_vector(const std::vector & t) { for (unsigned i = 0; i < t.size(); i++) { if (is_zero(t[i]))continue; std::cout << "[" << i << "] = " << t[i] << ", "; @@ -55,7 +50,7 @@ void print_sparse_vector(const vector & t) { std::cout << std::endl; } -void print_vector(const vector & t) { +void print_vector(const std::vector & t) { for (unsigned i = 0; i < t.size(); i++) std::cout << t[i].get_double() << std::setprecision(3) << " "; std::cout << std::endl; @@ -66,7 +61,7 @@ class indexed_vector { public: // m_index points to non-zero elements of m_data buffer m_data; - vector m_index; + std::vector m_index; indexed_vector(unsigned data_size) { m_data.resize(data_size, numeric_traits::zero()); } @@ -117,8 +112,6 @@ public: if (it != m_index.end()) m_index.erase(it); } - - #ifdef LEAN_DEBUG bool is_OK() const { int size = 0; @@ -132,11 +125,11 @@ public: return size == m_index.size(); } void print() { - cout << "m_index " << endl; + std::cout << "m_index " << std::endl; for (unsigned i = 0; i < m_index.size(); i++) { - cout << m_index[i] << " "; + std::cout << m_index[i] << " "; } - cout << endl; + std::cout << std::endl; print_vector(m_data); } #endif diff --git a/src/util/lp/lar_constraints.h b/src/util/lp/lar_constraints.h index 9a8bf6154..0f299f350 100644 --- a/src/util/lp/lar_constraints.h +++ b/src/util/lp/lar_constraints.h @@ -16,101 +16,88 @@ #include #include "util/lp/canonic_left_side.h" namespace lean { - lconstraint_kind flip_kind(lconstraint_kind t) { - return static_cast( - static_cast(t)); - } - - std::string lconstraint_kind_string(lconstraint_kind t) { - switch (t) { - case LE: return string("<="); - case LT: return string("<"); - case GE: return string(">="); - case GT: return string(">"); - case EQ: return string("="); - - default: - throw "unexpected"; - } - } - - class lar_base_constraint { - public: - lconstraint_kind m_kind; - mpq m_right_side; - virtual buffer> get_left_side_coefficients() const = 0; - constraint_index m_index; // the index of constraint - lar_base_constraint() {} - lar_base_constraint(lconstraint_kind kind, mpq right_side, constraint_index index) :m_kind(kind), m_right_side(right_side), m_index(index) {} - - virtual unsigned size() const = 0; - virtual ~lar_base_constraint(){} - }; - - class lar_constraint : public lar_base_constraint { - public: - std::unordered_map m_left_side; - lar_constraint() {} - lar_constraint(const buffer> & left_side, lconstraint_kind kind, mpq right_side, constraint_index index) : lar_base_constraint(kind, right_side, index) { - for (auto & it : left_side) { - auto r = m_left_side.find(it.second); - if (r == m_left_side.end()) { - m_left_side[it.second] = it.first; - } else { - r->second += it.first; - } - } - } - - lar_constraint(const lar_base_constraint & c): lar_base_constraint(c.m_kind, c.m_right_side, c.m_index) { - for (auto t : c.get_left_side_coefficients()) - m_left_side.insert(std::make_pair(t.second, t.first)); - } - - unsigned size() const { - return m_left_side.size(); - } - - buffer> get_left_side_coefficients() const { - buffer> ret; - for (auto it : m_left_side) { - ret.push_back(std::make_pair(it.second, it.first)); - } - return ret; - } - }; - - class lar_normalized_constraint : public lar_base_constraint { - public: - canonic_left_side* m_canonic_left_side; - mpq m_ratio_to_original; // by multiplying this constraint by m_ratio_to_original we get the original one - lar_constraint m_origin_constraint; - lar_normalized_constraint(canonic_left_side * ls, mpq ratio, lconstraint_kind kind, mpq right_side, const lar_constraint & origin): - lar_base_constraint(kind, right_side, origin.m_index), - m_canonic_left_side(ls), - m_ratio_to_original(ratio), - m_origin_constraint(origin) { - } - - lar_normalized_constraint() {} - - // lar_normalized_constraint & operator=(lar_normalized_constraint & other) { - // m_canonic_left_side = other.m_canonic_left_side; - // m_origin_constraint = other.m_origin_constraint; - // m_kind = other.m_kind; - // m_right_side = other.m_right_side; - // return *this; - // } - - - - - virtual buffer> get_left_side_coefficients() const { - buffer> ret; - for (auto t : m_canonic_left_side->m_coeffs) ret.push_back(t); - return ret; - } - virtual unsigned size() const { - return m_canonic_left_side->size(); - } - }; +lconstraint_kind flip_kind(lconstraint_kind t) { + return static_cast( - static_cast(t)); +} + +std::string lconstraint_kind_string(lconstraint_kind t) { + switch (t) { + case LE: return std::string("<="); + case LT: return std::string("<"); + case GE: return std::string(">="); + case GT: return std::string(">"); + case EQ: return std::string("="); + } + lean_unreachable(); +} + +class lar_base_constraint { +public: + lconstraint_kind m_kind; + mpq m_right_side; + virtual buffer> get_left_side_coefficients() const = 0; + constraint_index m_index; // the index of constraint + lar_base_constraint() {} + lar_base_constraint(lconstraint_kind kind, mpq right_side, constraint_index index) :m_kind(kind), m_right_side(right_side), m_index(index) {} + + virtual unsigned size() const = 0; + virtual ~lar_base_constraint(){} +}; + +class lar_constraint : public lar_base_constraint { +public: + std::unordered_map m_left_side; + lar_constraint() {} + lar_constraint(const buffer> & left_side, lconstraint_kind kind, mpq right_side, constraint_index index) : lar_base_constraint(kind, right_side, index) { + for (auto & it : left_side) { + auto r = m_left_side.find(it.second); + if (r == m_left_side.end()) { + m_left_side[it.second] = it.first; + } else { + r->second += it.first; + } + } + } + + lar_constraint(const lar_base_constraint & c): lar_base_constraint(c.m_kind, c.m_right_side, c.m_index) { + for (auto t : c.get_left_side_coefficients()) + m_left_side.insert(std::make_pair(t.second, t.first)); + } + + unsigned size() const { + return m_left_side.size(); + } + + buffer> get_left_side_coefficients() const { + buffer> ret; + for (auto it : m_left_side) { + ret.push_back(std::make_pair(it.second, it.first)); + } + return ret; + } +}; + +class lar_normalized_constraint : public lar_base_constraint { +public: + canonic_left_side* m_canonic_left_side; + mpq m_ratio_to_original; // by multiplying this constraint by m_ratio_to_original we get the original one + lar_constraint m_origin_constraint; + lar_normalized_constraint(canonic_left_side * ls, mpq ratio, lconstraint_kind kind, mpq right_side, const lar_constraint & origin): + lar_base_constraint(kind, right_side, origin.m_index), + m_canonic_left_side(ls), + m_ratio_to_original(ratio), + m_origin_constraint(origin) { + } + + lar_normalized_constraint() {} + + virtual buffer> get_left_side_coefficients() const { + buffer> ret; + for (auto t : m_canonic_left_side->m_coeffs) ret.push_back(t); + return ret; + } + virtual unsigned size() const { + return m_canonic_left_side->size(); + } +}; } diff --git a/src/util/lp/lar_core_solver.h b/src/util/lp/lar_core_solver.h index e21c4aeb6..b9a8d0241 100644 --- a/src/util/lp/lar_core_solver.h +++ b/src/util/lp/lar_core_solver.h @@ -14,857 +14,853 @@ #include "util/lp/breakpoint.h" namespace lean { - template - class lar_core_solver : public lp_core_solver_base { - // m_sign_of_entering is set to 1 if the entering variable needs - // to grow and is set to -1 otherwise - int m_sign_of_entering_delta; - X m_infeasibility; - vector m_tight_basic_columns; - vector> m_breakpoints; - binary_heap_priority_queue m_breakpoint_indices_queue; - vector> m_infeasible_row; - int m_infeasible_row_sign = 0; - // with a breakpoint at this delta - public: - lar_core_solver(std::vector & x, std::vector & column_types, - std::vector & low_bounds, std::vector & upper_bounds, - std::vector & basis, - static_matrix & A, - lp_settings & settings, - std::unordered_map & column_names, - vector & right_side, - vector & costs) : // right_side and costs are redundant - lp_core_solver_base(A, - right_side, - basis, - x, - costs, - settings, - column_names, - column_types, - low_bounds, - upper_bounds) { +template +class lar_core_solver : public lp_core_solver_base { + // m_sign_of_entering is set to 1 if the entering variable needs + // to grow and is set to -1 otherwise + int m_sign_of_entering_delta; + X m_infeasibility; + std::vector m_tight_basic_columns; + std::vector> m_breakpoints; + binary_heap_priority_queue m_breakpoint_indices_queue; + std::vector> m_infeasible_row; + int m_infeasible_row_sign = 0; + // with a breakpoint at this delta +public: + lar_core_solver(std::vector & x, std::vector & column_types, + std::vector & low_bounds, std::vector & upper_bounds, + std::vector & basis, + static_matrix & A, + lp_settings & settings, + std::unordered_map & column_names, + std::vector & right_side, + std::vector & costs) : // right_side and costs are redundant + lp_core_solver_base(A, + right_side, + basis, + x, + costs, + settings, + column_names, + column_types, + low_bounds, + upper_bounds) { + } + + int get_infeasible_row_sign() const { + return m_infeasible_row_sign; + } + + const std::vector> & get_infeasibility_info(int & inf_sign) const { + inf_sign = m_infeasible_row_sign; + return m_infeasible_row; + } + + void init_costs() { + lean_assert(this->m_x.size() >= this->m_n); + lean_assert(this->m_column_type.size() >= this->m_n); + X inf = m_infeasibility; + m_infeasibility = zero_of_type(); + for (unsigned j = this->m_n; j--;) + init_cost_for_column(j); + if (!(this->m_total_iterations ==0 || inf >= m_infeasibility)) { + std::cout << "inf was " << T_to_string(inf) << " and now " << T_to_string(m_infeasibility) << std::endl; } + lean_assert(this->m_total_iterations ==0 || inf >= m_infeasibility); + if (inf == m_infeasibility) + this->m_iters_with_no_cost_growing++; + } - int get_infeasible_row_sign() const { - return m_infeasible_row_sign; + + void init_cost_for_column(unsigned j) { + // If j is a breakpoint column, then we set the cost zero. + // When anylyzing an entering column candidate we update the cost of the breakpoints columns to get the left or the right derivative if the infeasibility function + const X & x = this->m_x[j]; + // set zero cost for each non-basis column + if (this->m_basis_heading[j] < 0) { + this->m_costs[j] = numeric_traits::zero(); + return; } - - const vector> & get_infeasibility_info(int & inf_sign) const { - inf_sign = m_infeasible_row_sign; - return m_infeasible_row; - } - - void init_costs() { - lean_assert(this->m_x.size() >= this->m_n); - lean_assert(this->m_column_type.size() >= this->m_n); - X inf = m_infeasibility; - m_infeasibility = zero_of_type(); - for (unsigned j = this->m_n; j--;) - init_cost_for_column(j); - if (!(this->m_total_iterations ==0 || inf >= m_infeasibility)) { - cout << "inf was " << T_to_string(inf) << " and now " << T_to_string(m_infeasibility) << endl; - } - lean_assert(this->m_total_iterations ==0 || inf >= m_infeasibility); - if (inf == m_infeasibility) - this->m_iters_with_no_cost_growing++; - } - - - void init_cost_for_column(unsigned j) { - // If j is a breakpoint column, then we set the cost zero. - // When anylyzing an entering column candidate we update the cost of the breakpoints columns to get the left or the right derivative if the infeasibility function - const X & x = this->m_x[j]; - // set zero cost for each non-basis column - if (this->m_basis_heading[j] < 0) { - this->m_costs[j] = numeric_traits::zero(); - return; - } - // j is a basis column - switch (this->m_column_type[j]) { - case fixed: - case boxed: - if (x > this->m_upper_bound_values[j]) { - this->m_costs[j] = 1; - m_infeasibility += x - this->m_upper_bound_values[j]; - } else if (x < this->m_low_bound_values[j]) { - m_infeasibility += this->m_low_bound_values[j] - x; - this->m_costs[j] = -1; - } else { - this->m_costs[j] = numeric_traits::zero(); - } - break; - case low_bound: - if (x < this->m_low_bound_values[j]) { - this->m_costs[j] = -1; - m_infeasibility += this->m_low_bound_values[j] - x; - } else { - this->m_costs[j] = numeric_traits::zero(); - } - break; - case upper_bound: - if (x > this->m_upper_bound_values[j]) { - this->m_costs[j] = 1; - m_infeasibility += x - this->m_upper_bound_values[j]; - } else { - this->m_costs[j] = numeric_traits::zero(); - } - break; - case free_column: - this->m_costs[j] = numeric_traits::zero(); - break; - default: - lean_assert(false); - break; - } - } - - void init_local() { - this->m_start_time = get_millisecond_count(); - this->m_m = this->m_A.row_count(); - this->m_n = this->m_A.column_count(); - this->m_pivot_row_of_B_1.resize(this->m_m); - this->m_pivot_row.resize(this->m_n); - this->m_b.resize(this->m_m); - this->m_y.resize(this->m_m); - this->m_w.resize(this->m_m); - this->m_d.resize(this->m_n); - this->m_ed.resize(this->m_m); - this->m_costs.resize(this->m_n); - this->m_breakpoint_indices_queue.resize(this->m_n); - this->m_copy_of_xB.resize(this->m_n); - } - - // returns m_sign_of_alpha_r - int column_is_out_of_bounds(unsigned j) { - switch (this->m_column_type[j]) { - case fixed: - case boxed: - if (this->x_below_low_bound(j)) { - return -1; - } - if (this->x_above_upper_bound(j)) { - return 1; - } - return 0; - case low_bound: - if (this->x_below_low_bound(j)) { - return -1; - } - return 0; - case upper_bound: - if (this->x_above_upper_bound(j)) { - return 1; - } - return 0; - default: - return 0; - break; - } - } - - bool can_enter_basis_mpq(unsigned j) { - switch (this->m_column_type[j]) { - case low_bound: - lean_assert(this->x_is_at_low_bound(j)); - return this->m_d[j] < numeric_traits::zero(); - case upper_bound: - lean_assert(this->x_is_at_upper_bound(j)); - return this->m_d[j] > numeric_traits::zero(); - case fixed: - return false; - case boxed: - { - bool low_bound = this->x_is_at_low_bound(j); - lean_assert(low_bound || this->x_is_at_upper_bound(j)); - return (low_bound && this->m_d[j] < numeric_traits::zero()) || ((!low_bound) && this->m_d[j] > numeric_traits::zero()); - } - case free_column: - return !numeric_traits::is_zero(this->m_d[j]); - default: - return false; - } - return false; - } - - - void calculate_pivot_row(unsigned i) { - this->calculate_pivot_row_of_B_1(i); - this->calculate_pivot_row_when_pivot_row_of_B1_is_ready(); - } - - - X get_deb_inf_column(unsigned j) { - const X & x = this->m_x[j]; - switch (this->m_column_type[j]) { - case low_bound: - if (x < this->m_low_bound_values[j]) - return this->m_low_bound_values[j] - x; - return zero_of_type(); - case upper_bound: - if (x > this->m_upper_bound_values[j]) - return x - this->m_upper_bound_values[j]; - return zero_of_type(); - case fixed: - case boxed: - { - if (x < this->m_low_bound_values[j]) - return this->m_low_bound_values[j] - x; - if (x > this->m_upper_bound_values[j]) - return x - this->m_upper_bound_values[j]; - return zero_of_type(); - } - case free_column: - { - return zero_of_type(); - } - default: - lean_assert(false); - return zero_of_type(); - } - } - - X get_deb_inf() { - X ret = zero_of_type(); - for (unsigned j = 0; j < this->m_n; j++) { - X d = get_deb_inf_column(j); - // if (! numeric_traits::is_zero(d)) { - // cout << "column " << j << ", " << this->column_name(j) << " inf is " << d.get_double() << endl; - // } - ret += d; - } - return ret; - } - - bool debug_profit_delta(unsigned j, const T & delta) { - this->update_x(j, delta); - bool ret = m_infeasibility > get_deb_inf(); - if (ret) { - cout << "found profit for " << this->column_name(j) << " and delta = " << delta.get_double() << endl; - cout << "improvement = " << (m_infeasibility - get_deb_inf()).get_double() << endl; - } - return ret; - } - - bool debug_profit(unsigned j) { - if (this->m_column_type[j] == fixed) return false; - T delta = numeric_traits::one() / 10000000; - delta /= 10000000; - return debug_profit_delta(j, -delta) || debug_profit_delta(j, delta); - } - - int choose_column_entering_basis() { - unsigned offset = lrand48() % this->m_non_basic_columns.size(); - unsigned initial_offset_in_non_basis = offset; - do { - unsigned j = this->m_non_basic_columns[offset]; - if (can_enter_basis_mpq(j)) - return j; - offset++; - if (offset == this->m_non_basic_columns.size()) offset = 0; - } while (offset != initial_offset_in_non_basis); - return -1; - } - - void one_iteration() { - this->m_total_iterations++; - lean_assert(this->m_non_basic_columns.size() + this->m_basis.size() == this->m_basis_heading.size()); - if (is_zero(m_infeasibility)) { - this->m_status = OPTIMAL; - return; - } - int entering = choose_column_entering_basis(); - if (entering == -1) { - cout << "cannot choose entering" << endl; - decide_on_status_when_cannot_enter(); + // j is a basis column + switch (this->m_column_type[j]) { + case fixed: + case boxed: + if (x > this->m_upper_bound_values[j]) { + this->m_costs[j] = 1; + m_infeasibility += x - this->m_upper_bound_values[j]; + } else if (x < this->m_low_bound_values[j]) { + m_infeasibility += this->m_low_bound_values[j] - x; + this->m_costs[j] = -1; } else { - advance_on_entering(entering); + this->m_costs[j] = numeric_traits::zero(); } - } - - - void decide_on_status_when_cannot_enter() { - if (!is_zero(m_infeasibility)) - this->m_status = INFEASIBLE; - else - this->m_status = FEASIBLE; - cout << "status is " << lp_status_to_string(this->m_status) << endl; - } - template - bool same_sign_with_entering_delta(const L & a) { - return (a > zero_of_type() && m_sign_of_entering_delta > 0) || (a < zero_of_type() && m_sign_of_entering_delta < 0); - } - - // j is the basic column, x is the value at x[j] - // d is the coefficient before m_entering in the row with j as the basis column - void try_add_breakpoint(unsigned j, const X & x, const T & d, breakpoint_type break_type, const X & break_value) { - X diff = x - break_value; - if (is_zero(diff)) { - switch (break_type) { - case low_break: - if (!same_sign_with_entering_delta(d)) - return; // no breakpoint - break; - case upper_break: - if (same_sign_with_entering_delta(d)) - return; // no breakpoint - break; - default: break; - } - add_breakpoint(j, zero_of_type(), break_type); - return; + break; + case low_bound: + if (x < this->m_low_bound_values[j]) { + this->m_costs[j] = -1; + m_infeasibility += this->m_low_bound_values[j] - x; + } else { + this->m_costs[j] = numeric_traits::zero(); } - auto delta_j = diff / d; - if (same_sign_with_entering_delta(delta_j)) - add_breakpoint(j, delta_j, break_type); - } - - - void add_breakpoint(unsigned j, X delta, breakpoint_type type) { - m_breakpoints.push_back(breakpoint(j, delta, type)); - m_breakpoint_indices_queue.enqueue(m_breakpoint_indices_queue.size(), abs(delta)); - } - - void try_add_breakpoint_in_row(unsigned i) { - lean_assert(i < this->m_m); - const T & d = this->m_ed[i]; // the coefficient before m_entering in the i-th row - if (d == 0) return; // the change of x[m_entering] will not change the corresponding basis x - unsigned j = this->m_basis[i]; - const X & x = this->m_x[j]; - switch (this->m_column_type[j]) { - case fixed: - try_add_breakpoint(j, x, d, fixed_break, this->m_low_bound_values[j]); - break; - case boxed: - try_add_breakpoint(j, x, d, low_break, this->m_low_bound_values[j]); - try_add_breakpoint(j, x, d, upper_break, this->m_upper_bound_values[j]); - break; - case low_bound: - try_add_breakpoint(j, x, d, low_break, this->m_low_bound_values[j]); - break; - case upper_bound: - try_add_breakpoint(j, x, d, upper_break, this->m_upper_bound_values[j]); - break; - case free_column: - break; - default: - lean_assert(false); - break; + break; + case upper_bound: + if (x > this->m_upper_bound_values[j]) { + this->m_costs[j] = 1; + m_infeasibility += x - this->m_upper_bound_values[j]; + } else { + this->m_costs[j] = numeric_traits::zero(); } + break; + case free_column: + this->m_costs[j] = numeric_traits::zero(); + break; + default: + lean_assert(false); + break; } + } - string break_type_to_string(breakpoint_type type) { - switch (type){ - case low_break: return "low_break"; - case upper_break: return "upper_break"; - case fixed_break: return "fixed_break"; - default: - lean_assert(false); - break; + void init_local() { + this->m_start_time = get_millisecond_count(); + this->m_m = this->m_A.row_count(); + this->m_n = this->m_A.column_count(); + this->m_pivot_row_of_B_1.resize(this->m_m); + this->m_pivot_row.resize(this->m_n); + this->m_b.resize(this->m_m); + this->m_y.resize(this->m_m); + this->m_w.resize(this->m_m); + this->m_d.resize(this->m_n); + this->m_ed.resize(this->m_m); + this->m_costs.resize(this->m_n); + this->m_breakpoint_indices_queue.resize(this->m_n); + this->m_copy_of_xB.resize(this->m_n); + } + + // returns m_sign_of_alpha_r + int column_is_out_of_bounds(unsigned j) { + switch (this->m_column_type[j]) { + case fixed: + case boxed: + if (this->x_below_low_bound(j)) { + return -1; } - return "type is not found"; - } - - void print_breakpoint(const breakpoint * b) { - cout << "(" << this->column_name(b->m_j) << "," << break_type_to_string(b->m_type) << "," << T_to_string(b->m_delta) << ")" << endl; - print_bound_info_and_x(b->m_j); - } - - void print_bound_info_and_x(unsigned j) { - cout << "type of " << this->column_name(j) << " is " << column_type_to_string(this->m_column_type[j]) << endl; - cout << "x[" << this->column_name(j) << "] = " << this->m_x[j] << endl; - switch (this->m_column_type[j]) { - case fixed: - case boxed: - cout << "[" << this->m_low_bound_values[j] << "," << this->m_upper_bound_values[j] << "]" << endl; - break; - case low_bound: - cout << "[" << this->m_low_bound_values[j] << ", inf" << endl; - break; - case upper_bound: - cout << "inf ," << this->m_upper_bound_values[j] << "]" << endl; - break; - case free_column: - cout << "inf, inf" << endl; - break; - default: - lean_assert(false); - break; + if (this->x_above_upper_bound(j)) { + return 1; } - } - - void clear_breakpoints() { - m_breakpoints.clear(); - m_breakpoint_indices_queue.clear(); - } - - void fill_breakpoints_array(unsigned entering) { - clear_breakpoints(); - for (unsigned i = this->m_m; i--;) - try_add_breakpoint_in_row(i); - - if (this->m_column_type[entering] == boxed) { - if (m_sign_of_entering_delta < 0) - add_breakpoint(entering, - this->bound_span(entering), low_break); - else - add_breakpoint(entering, this->bound_span(entering), upper_break); + return 0; + case low_bound: + if (this->x_below_low_bound(j)) { + return -1; } - } - - void advance_on_entering(unsigned entering) { - this->solve_Bd(entering); // prepares the entering column to be like the one of the tableau - m_sign_of_entering_delta = this->m_d[entering] < zero_of_type() ? 1 : -1; - - fill_breakpoints_array(entering); - advance_on_sorted_breakpoints(entering); - } - - void print_cost() { - cout << "reduced costs " << endl; - for (unsigned j = 0; j < this->m_n; j++) { - if (numeric_traits::is_zero(this->m_d[j])) continue; - cout << T_to_string(this->m_d[j]) << this->column_name(j) << " "; + return 0; + case upper_bound: + if (this->x_above_upper_bound(j)) { + return 1; } - cout << endl; + return 0; + default: + return 0; + break; } + } - void update_basis_and_x_with_comparison(unsigned entering, unsigned leaving, X delta) { - if (entering != leaving) - this->update_basis_and_x(entering, leaving, delta); - else - this->update_x(entering, delta); + bool can_enter_basis_mpq(unsigned j) { + switch (this->m_column_type[j]) { + case low_bound: + lean_assert(this->x_is_at_low_bound(j)); + return this->m_d[j] < numeric_traits::zero(); + case upper_bound: + lean_assert(this->x_is_at_upper_bound(j)); + return this->m_d[j] > numeric_traits::zero(); + case fixed: + return false; + case boxed: + { + bool low_bound = this->x_is_at_low_bound(j); + lean_assert(low_bound || this->x_is_at_upper_bound(j)); + return (low_bound && this->m_d[j] < numeric_traits::zero()) || ((!low_bound) && this->m_d[j] > numeric_traits::zero()); } - - void advance_on_sorted_breakpoints(unsigned entering) { - T slope_at_entering = this->m_d[entering]; - breakpoint * last_bp = nullptr; - while (m_breakpoint_indices_queue.is_empty() == false) { - unsigned bi = m_breakpoint_indices_queue.dequeue(); - breakpoint *b = &m_breakpoints[bi]; - change_slope_on_breakpoint(entering, b, slope_at_entering); - last_bp = b; - if (slope_at_entering * m_sign_of_entering_delta > 0) { // the slope started to increase infeasibility - break; - } else { - if (numeric_traits::is_zero(slope_at_entering) && lrand48() % 2 == 0) { - // it is not cost benefitial to advance the delta more, so just break to increas the randomness - break; - } - } - } - update_basis_and_x_with_comparison(entering, last_bp->m_j, last_bp->m_delta); + case free_column: + return !numeric_traits::is_zero(this->m_d[j]); + default: + return false; } + return false; + } - void change_slope_on_breakpoint(unsigned entering, breakpoint * b, T & slope_at_entering) { - if (b->m_j == entering) { - lean_assert(b->m_type != fixed_break && (!is_zero(b->m_delta))); - slope_at_entering += m_sign_of_entering_delta; - return; - } - lean_assert(this->m_basis_heading[b->m_j] >= 0); - unsigned i_row = this->m_basis_heading[b->m_j]; - const T & d = - this->m_ed[i_row]; - if (numeric_traits::is_zero(d)) return; + void calculate_pivot_row(unsigned i) { + this->calculate_pivot_row_of_B_1(i); + this->calculate_pivot_row_when_pivot_row_of_B1_is_ready(); + } - T delta = m_sign_of_entering_delta * abs(d); - switch (b->m_type) { - case fixed_break: - if (is_zero(b->m_delta)) { - slope_at_entering += delta; - } else { - slope_at_entering += 2 * delta; - } - break; + + X get_deb_inf_column(unsigned j) { + const X & x = this->m_x[j]; + switch (this->m_column_type[j]) { + case low_bound: + if (x < this->m_low_bound_values[j]) + return this->m_low_bound_values[j] - x; + return zero_of_type(); + case upper_bound: + if (x > this->m_upper_bound_values[j]) + return x - this->m_upper_bound_values[j]; + return zero_of_type(); + case fixed: + case boxed: + { + if (x < this->m_low_bound_values[j]) + return this->m_low_bound_values[j] - x; + if (x > this->m_upper_bound_values[j]) + return x - this->m_upper_bound_values[j]; + return zero_of_type(); + } + case free_column: + { + return zero_of_type(); + } + default: + lean_assert(false); + return zero_of_type(); + } + } + + X get_deb_inf() { + X ret = zero_of_type(); + for (unsigned j = 0; j < this->m_n; j++) { + X d = get_deb_inf_column(j); + // if (! numeric_traits::is_zero(d)) { + // std::cout << "column " << j << ", " << this->column_name(j) << " inf is " << d.get_double() << std::endl; + // } + ret += d; + } + return ret; + } + + bool debug_profit_delta(unsigned j, const T & delta) { + this->update_x(j, delta); + bool ret = m_infeasibility > get_deb_inf(); + if (ret) { + std::cout << "found profit for " << this->column_name(j) << " and delta = " << delta.get_double() << std::endl; + std::cout << "improvement = " << (m_infeasibility - get_deb_inf()).get_double() << std::endl; + } + return ret; + } + + bool debug_profit(unsigned j) { + if (this->m_column_type[j] == fixed) return false; + T delta = numeric_traits::one() / 10000000; + delta /= 10000000; + return debug_profit_delta(j, -delta) || debug_profit_delta(j, delta); + } + + int choose_column_entering_basis() { + unsigned offset = lrand48() % this->m_non_basic_columns.size(); + unsigned initial_offset_in_non_basis = offset; + do { + unsigned j = this->m_non_basic_columns[offset]; + if (can_enter_basis_mpq(j)) + return j; + offset++; + if (offset == this->m_non_basic_columns.size()) offset = 0; + } while (offset != initial_offset_in_non_basis); + return -1; + } + + void one_iteration() { + this->m_total_iterations++; + lean_assert(this->m_non_basic_columns.size() + this->m_basis.size() == this->m_basis_heading.size()); + if (is_zero(m_infeasibility)) { + this->m_status = OPTIMAL; + return; + } + int entering = choose_column_entering_basis(); + if (entering == -1) { + std::cout << "cannot choose entering" << std::endl; + decide_on_status_when_cannot_enter(); + } else { + advance_on_entering(entering); + } + } + + + void decide_on_status_when_cannot_enter() { + if (!is_zero(m_infeasibility)) + this->m_status = INFEASIBLE; + else + this->m_status = FEASIBLE; + std::cout << "status is " << lp_status_to_string(this->m_status) << std::endl; + } + template + bool same_sign_with_entering_delta(const L & a) { + return (a > zero_of_type() && m_sign_of_entering_delta > 0) || (a < zero_of_type() && m_sign_of_entering_delta < 0); + } + + // j is the basic column, x is the value at x[j] + // d is the coefficient before m_entering in the row with j as the basis column + void try_add_breakpoint(unsigned j, const X & x, const T & d, breakpoint_type break_type, const X & break_value) { + X diff = x - break_value; + if (is_zero(diff)) { + switch (break_type) { case low_break: - case upper_break: - slope_at_entering += delta; + if (!same_sign_with_entering_delta(d)) + return; // no breakpoint break; - default: - throw 1; - lean_assert(false); // such a type does not exist + case upper_break: + if (same_sign_with_entering_delta(d)) + return; // no breakpoint + break; + default: break; } + add_breakpoint(j, zero_of_type(), break_type); + return; } + auto delta_j = diff / d; + if (same_sign_with_entering_delta(delta_j)) + add_breakpoint(j, delta_j, break_type); + } - bool row_is_infeasible(unsigned row, int & inf_sign) { - unsigned j = this->m_basis[row]; - inf_sign = get_infeasibility_sign(j); - return inf_sign != 0; + + void add_breakpoint(unsigned j, X delta, breakpoint_type type) { + m_breakpoints.push_back(breakpoint(j, delta, type)); + m_breakpoint_indices_queue.enqueue(m_breakpoint_indices_queue.size(), abs(delta)); + } + + void try_add_breakpoint_in_row(unsigned i) { + lean_assert(i < this->m_m); + const T & d = this->m_ed[i]; // the coefficient before m_entering in the i-th row + if (d == 0) return; // the change of x[m_entering] will not change the corresponding basis x + unsigned j = this->m_basis[i]; + const X & x = this->m_x[j]; + switch (this->m_column_type[j]) { + case fixed: + try_add_breakpoint(j, x, d, fixed_break, this->m_low_bound_values[j]); + break; + case boxed: + try_add_breakpoint(j, x, d, low_break, this->m_low_bound_values[j]); + try_add_breakpoint(j, x, d, upper_break, this->m_upper_bound_values[j]); + break; + case low_bound: + try_add_breakpoint(j, x, d, low_break, this->m_low_bound_values[j]); + break; + case upper_bound: + try_add_breakpoint(j, x, d, upper_break, this->m_upper_bound_values[j]); + break; + case free_column: + break; + default: + lean_assert(false); + break; } + } - bool row_is_evidence(unsigned row, int & inf_sign) { - if (!row_is_infeasible(row, inf_sign)) return false; - calculate_pivot_row(row); - int entering = choose_entering_column_for_row_inf_strategy(inf_sign); - if (entering == -1) { - return true; - } - return false; + std::string break_type_to_string(breakpoint_type type) { + switch (type){ + case low_break: return "low_break"; + case upper_break: return "upper_break"; + case fixed_break: return "fixed_break"; + default: + lean_assert(false); + break; } + return "type is not found"; + } - bool find_evidence_row() { - for (unsigned i = this->m_m; --i;) { - int inf_sign; - if (row_is_evidence(i, inf_sign)) { - fill_evidence(i, inf_sign); - return true; + void print_breakpoint(const breakpoint * b) { + std::cout << "(" << this->column_name(b->m_j) << "," << break_type_to_string(b->m_type) << "," << T_to_string(b->m_delta) << ")" << std::endl; + print_bound_info_and_x(b->m_j); + } + + void print_bound_info_and_x(unsigned j) { + std::cout << "type of " << this->column_name(j) << " is " << column_type_to_string(this->m_column_type[j]) << std::endl; + std::cout << "x[" << this->column_name(j) << "] = " << this->m_x[j] << std::endl; + switch (this->m_column_type[j]) { + case fixed: + case boxed: + std::cout << "[" << this->m_low_bound_values[j] << "," << this->m_upper_bound_values[j] << "]" << std::endl; + break; + case low_bound: + std::cout << "[" << this->m_low_bound_values[j] << ", inf" << std::endl; + break; + case upper_bound: + std::cout << "inf ," << this->m_upper_bound_values[j] << "]" << std::endl; + break; + case free_column: + std::cout << "inf, inf" << std::endl; + break; + default: + lean_assert(false); + break; + } + } + + void clear_breakpoints() { + m_breakpoints.clear(); + m_breakpoint_indices_queue.clear(); + } + + void fill_breakpoints_array(unsigned entering) { + clear_breakpoints(); + for (unsigned i = this->m_m; i--;) + try_add_breakpoint_in_row(i); + + if (this->m_column_type[entering] == boxed) { + if (m_sign_of_entering_delta < 0) + add_breakpoint(entering, - this->bound_span(entering), low_break); + else + add_breakpoint(entering, this->bound_span(entering), upper_break); + } + } + + void advance_on_entering(unsigned entering) { + this->solve_Bd(entering); // prepares the entering column to be like the one of the tableau + m_sign_of_entering_delta = this->m_d[entering] < zero_of_type() ? 1 : -1; + + fill_breakpoints_array(entering); + advance_on_sorted_breakpoints(entering); + } + + void print_cost() { + std::cout << "reduced costs " << std::endl; + for (unsigned j = 0; j < this->m_n; j++) { + if (numeric_traits::is_zero(this->m_d[j])) continue; + std::cout << T_to_string(this->m_d[j]) << this->column_name(j) << " "; + } + std::cout << std::endl; + } + + void update_basis_and_x_with_comparison(unsigned entering, unsigned leaving, X delta) { + if (entering != leaving) + this->update_basis_and_x(entering, leaving, delta); + else + this->update_x(entering, delta); + } + + void advance_on_sorted_breakpoints(unsigned entering) { + T slope_at_entering = this->m_d[entering]; + breakpoint * last_bp = nullptr; + while (m_breakpoint_indices_queue.is_empty() == false) { + unsigned bi = m_breakpoint_indices_queue.dequeue(); + breakpoint *b = &m_breakpoints[bi]; + change_slope_on_breakpoint(entering, b, slope_at_entering); + last_bp = b; + if (slope_at_entering * m_sign_of_entering_delta > 0) { // the slope started to increase infeasibility + break; + } else { + if (numeric_traits::is_zero(slope_at_entering) && lrand48() % 2 == 0) { + // it is not cost benefitial to advance the delta more, so just break to increas the randomness + break; } } - return false; + } + update_basis_and_x_with_comparison(entering, last_bp->m_j, last_bp->m_delta); + } + + void change_slope_on_breakpoint(unsigned entering, breakpoint * b, T & slope_at_entering) { + if (b->m_j == entering) { + lean_assert(b->m_type != fixed_break && (!is_zero(b->m_delta))); + slope_at_entering += m_sign_of_entering_delta; + return; } + lean_assert(this->m_basis_heading[b->m_j] >= 0); + unsigned i_row = this->m_basis_heading[b->m_j]; + const T & d = - this->m_ed[i_row]; + if (numeric_traits::is_zero(d)) return; - bool done() { - if (this->m_status == OPTIMAL) return true; - if (this->m_status == INFEASIBLE) { - if (this->m_settings.row_feasibility == false) { - if (find_evidence_row()) { - cout << "found evidence" << endl; - } else { - cout << "did not find evidence" << endl; - cout << "started feasibility_loop at iteration " << this->m_total_iterations << endl; - unsigned iters = this->m_total_iterations; - this->m_status = FEASIBLE; - row_feasibility_loop(); - cout << "made another " << this->m_total_iterations - iters << ", percentage is " << 100.0 * (this->m_total_iterations - iters) / this->m_total_iterations << endl; - } - } + T delta = m_sign_of_entering_delta * abs(d); + switch (b->m_type) { + case fixed_break: + if (is_zero(b->m_delta)) { + slope_at_entering += delta; + } else { + slope_at_entering += 2 * delta; + } + break; + case low_break: + case upper_break: + slope_at_entering += delta; + break; + default: + lean_unreachable(); + } + } + + bool row_is_infeasible(unsigned row, int & inf_sign) { + unsigned j = this->m_basis[row]; + inf_sign = get_infeasibility_sign(j); + return inf_sign != 0; + } + + bool row_is_evidence(unsigned row, int & inf_sign) { + if (!row_is_infeasible(row, inf_sign)) return false; + calculate_pivot_row(row); + int entering = choose_entering_column_for_row_inf_strategy(inf_sign); + if (entering == -1) { + return true; + } + return false; + } + + bool find_evidence_row() { + for (unsigned i = this->m_m; --i;) { + int inf_sign; + if (row_is_evidence(i, inf_sign)) { + fill_evidence(i, inf_sign); return true; } - - if (this->m_iters_with_no_cost_growing >= this->m_settings.max_number_of_iterations_with_no_improvements) { - cout << "m_iters_with_no_cost_growing = " << this->m_iters_with_no_cost_growing << endl; - this->m_status = ITERATIONS_EXHAUSTED; return true; - } - if (this->m_total_iterations >= this->m_settings.max_total_number_of_iterations) { - cout << "max_total_number_of_iterations " << this->m_total_iterations << " is reached " << endl; - this->m_status = ITERATIONS_EXHAUSTED; return true; - } - return false; } + return false; + } - void move_as_many_as_possible_fixed_columns_to_non_basis() { - unsigned i = 0; // points to basis - auto& bs = this->m_basis; - unsigned j = 0; // points to m_column_types - auto & ct = this->m_column_type; - vector heading(this->m_n, -1); - for (int i = 0; i < bs.size(); i ++) heading[bs[j]] = i; - lean_assert(this->m_basis.size() == this->m_m); - while (i < this->m_m && j < ct.size()) { - unsigned basis_j = bs[i]; - if (ct[basis_j] != fixed) {i++; continue;} - do { - if (heading[j] == -numeric_traits::one() && ct[j] != fixed) - break; - j++; - } while (j < ct.size()); - if (j == ct.size()) break; - bs[i++] = j++; - } - } - bool non_basis_columns_are_set_correctly() { - for (unsigned j : this->m_non_basic_columns) { - if (!this->x_is_at_bound(j)) - return false; + bool done() { + if (this->m_status == OPTIMAL) return true; + if (this->m_status == INFEASIBLE) { + if (this->m_settings.row_feasibility == false) { + if (find_evidence_row()) { + std::cout << "found evidence" << std::endl; + } else { + std::cout << "did not find evidence" << std::endl; + std::cout << "started feasibility_loop at iteration " << this->m_total_iterations << std::endl; + unsigned iters = this->m_total_iterations; + this->m_status = FEASIBLE; + row_feasibility_loop(); + std::cout << "made another " << this->m_total_iterations - iters << ", percentage is " << 100.0 * (this->m_total_iterations - iters) / this->m_total_iterations << std::endl; + } } return true; } - void prefix() { - init_local(); - this->init(); - this->init_basis_heading(); + if (this->m_iters_with_no_cost_growing >= this->m_settings.max_number_of_iterations_with_no_improvements) { + std::cout << "m_iters_with_no_cost_growing = " << this->m_iters_with_no_cost_growing << std::endl; + this->m_status = ITERATIONS_EXHAUSTED; return true; } - - bool is_tiny() const { - return this->m_m < 10 && this->m_n < 20; + if (this->m_total_iterations >= this->m_settings.max_total_number_of_iterations) { + std::cout << "max_total_number_of_iterations " << this->m_total_iterations << " is reached " << std::endl; + this->m_status = ITERATIONS_EXHAUSTED; return true; } + return false; + } - bool is_empty() const { - return this->m_m == 0 || this->m_n == 0; - } - - void feasibility_loop() { - while (true) { - init_costs(); - this->init_reduced_costs_for_one_iteration(); - if (this->print_statistics_with_cost_and_check_that_the_time_is_over(this->m_total_iterations, m_infeasibility)){ - this->m_status = lp_status::TIME_EXHAUSTED; - return; // this->m_total_iterations; - } - one_iteration(); - if (done()) { - break; - } - } - } - - unsigned get_number_of_inf_rows() const { - unsigned r = 0; - for (unsigned k = this->m_m; --k;) { - unsigned j = this->m_basis[k]; - if (get_infeasibility_sign(j)) r++; - } - return r; - } - - - void row_feasibility_loop() { - while (true) { - if (this->print_statistics_with_iterations_and_check_that_the_time_is_over(this->m_total_iterations++)){ - this->m_status = lp_status::TIME_EXHAUSTED; - return; // this->m_total_iterations; - } - int inf_sign; - int i = find_infeasible_row(inf_sign); - if (i == -1) { - this->m_status = OPTIMAL; - break; - } - advance_on_infeasible_row(i, inf_sign); - if (done()) - break; - } - } - - int find_infeasible_row(int & inf_sign) { - unsigned offset = lrand48() % this->m_m; - unsigned initial_offset_in_basis = offset; + void move_as_many_as_possible_fixed_columns_to_non_basis() { + unsigned i = 0; // points to basis + auto& bs = this->m_basis; + unsigned j = 0; // points to m_column_types + auto & ct = this->m_column_type; + std::vector heading(this->m_n, -1); + for (int i = 0; i < bs.size(); i ++) heading[bs[j]] = i; + lean_assert(this->m_basis.size() == this->m_m); + while (i < this->m_m && j < ct.size()) { + unsigned basis_j = bs[i]; + if (ct[basis_j] != fixed) {i++; continue;} do { - unsigned j = this->m_basis[offset]; - inf_sign = get_infeasibility_sign(j); - if (inf_sign) - return offset; - if (++offset == this->m_m) offset = 0; - } while (offset != initial_offset_in_basis); - return -1; + if (heading[j] == -numeric_traits::one() && ct[j] != fixed) + break; + j++; + } while (j < ct.size()); + if (j == ct.size()) break; + bs[i++] = j++; } + } - int get_infeasibility_sign(unsigned j) const { - const auto & x = this->m_x[j]; - switch (this->m_column_type[j]) { - case fixed: - case boxed: - if (x < this->m_low_bound_values[j]) return 1; - if (x > this->m_upper_bound_values[j]) return -1; - return 0; - case low_bound: - return x < this->m_low_bound_values[j] ? 1 : 0; - case upper_bound: - return x > this->m_upper_bound_values[j]? -1 :0; - default: - return 0; - } - } - - - template - int get_sign(const L & v) { - return v > zero_of_type() ? 1 : (v < zero_of_type() ? -1 : 0); - } - - bool improves_pivot_row_inf(unsigned j, int inf_sign) { - lean_assert(this->m_basis_heading[j] < 0); - // we have x[basis[i]] = sum (mj*x[j]), where mj = -m_pivot_row[j] - - switch (this->m_column_type[j]) { - case fixed: + bool non_basis_columns_are_set_correctly() { + for (unsigned j : this->m_non_basic_columns) { + if (!this->x_is_at_bound(j)) return false; - case boxed: - { - lean_assert(this->x_is_at_bound(j)); - int j_sign = - get_sign(this->m_pivot_row[j]) * inf_sign; - if (this->x_is_at_low_bound(j)) - return j_sign > 0; - return j_sign < 0; - } - case low_bound: - { - lean_assert(this->x_is_at_low_bound(j)); - int j_sign = - get_sign(this->m_pivot_row[j]) * inf_sign; - return j_sign > 0; - } - case upper_bound: - { - lean_assert(this->x_is_at_upper_bound(j)); - int j_sign = - get_sign(this->m_pivot_row[j]) * inf_sign; - return j_sign < 0; - } - break; - case free_column: { - return numeric_traits::is_zero(this->m_pivot_row[j]) == false; - } - default: - lean_assert(false); - throw "cannot be here"; + } + return true; + } + + void prefix() { + init_local(); + this->init(); + this->init_basis_heading(); + } + + bool is_tiny() const { + return this->m_m < 10 && this->m_n < 20; + } + + bool is_empty() const { + return this->m_m == 0 || this->m_n == 0; + } + + void feasibility_loop() { + while (true) { + init_costs(); + this->init_reduced_costs_for_one_iteration(); + if (this->print_statistics_with_cost_and_check_that_the_time_is_over(this->m_total_iterations, m_infeasibility)){ + this->m_status = lp_status::TIME_EXHAUSTED; + return; // this->m_total_iterations; + } + one_iteration(); + if (done()) { break; } } + } - int choose_entering_column_for_row_inf_strategy(int inf_sign) { - unsigned offset = lrand48() % this->m_non_basic_columns.size(); - unsigned initial_offset_in_non_basis = offset; - do { - unsigned j = this->m_non_basic_columns[offset]; - if (improves_pivot_row_inf(j, inf_sign)) - return j; - if (++offset == this->m_non_basic_columns.size()) offset = 0; - } while (offset != initial_offset_in_non_basis); - return -1; + unsigned get_number_of_inf_rows() const { + unsigned r = 0; + for (unsigned k = this->m_m; --k;) { + unsigned j = this->m_basis[k]; + if (get_infeasibility_sign(j)) r++; } + return r; + } - void fill_evidence(unsigned row, int inf_sign) { - m_infeasible_row_sign = inf_sign; - m_infeasible_row.push_back(std::make_pair(numeric_traits::one(), this->m_basis[row])); - for (auto j : this->m_non_basic_columns) { - T aj = this->m_pivot_row[j]; - if (!numeric_traits::is_zero(aj)) { - m_infeasible_row.push_back(std::make_pair(aj, j)); - } + + void row_feasibility_loop() { + while (true) { + if (this->print_statistics_with_iterations_and_check_that_the_time_is_over(this->m_total_iterations++)){ + this->m_status = lp_status::TIME_EXHAUSTED; + return; // this->m_total_iterations; } - } - - - void update_delta_of_entering_and_leaving_candidates(X del, X & delta, - vector & leaving_candidates, - unsigned bj) { - if (del < delta) { - leaving_candidates.clear(); - leaving_candidates.push_back(bj); - delta = del; - } else if (del == delta) { - leaving_candidates.push_back(bj); - } - } - - void update_delta_of_entering(int delta_sign, unsigned row, X & delta, - vector & leaving_candidates) { - unsigned bj = this->m_basis[row]; // bj - the basis column for the row - const T & ed = this->m_ed[row]; // this is the coefficent before x[entering] in the sum representing the basis column of this row taken with minus - if (numeric_traits::is_zero(ed)) return; - const X & x = this->m_x[bj]; // the value of the basis column - // adjusted sign - int adj_sign = ed < zero_of_type() ? delta_sign : - delta_sign; - - switch (this->m_column_type[bj]) { - case fixed: - case boxed: - if (adj_sign > 0 && x <= this->m_upper_bound_values[bj]) - update_delta_of_entering_and_leaving_candidates((this->m_upper_bound_values[bj] - x) / abs(ed), delta, leaving_candidates, bj); - else if (adj_sign < 0 && x >= this->m_low_bound_values[bj]) - update_delta_of_entering_and_leaving_candidates((x - this->m_low_bound_values[bj]) / abs(ed), delta, leaving_candidates, bj); - break; - case low_bound: - if (adj_sign < 0 && x >= this->m_low_bound_values[bj]) - update_delta_of_entering_and_leaving_candidates((x - this->m_low_bound_values[bj]) / abs(ed), delta, leaving_candidates, bj); - break; - case upper_bound: - if (adj_sign > 0 && x <= this->m_upper_bound_values[bj]) - update_delta_of_entering_and_leaving_candidates((this->m_upper_bound_values[bj] - x) / abs(ed), delta, leaving_candidates, bj); - break; - default: - break; - } - } - - unsigned find_leaving_for_inf_row_strategy(vector & leaving_candidates) { - lean_assert(leaving_candidates.size()); - return leaving_candidates[lrand48() % leaving_candidates.size()]; // more randomness - } - - X find_initial_delta_and_its_sign(unsigned row, unsigned entering, - int inf_sign, int & entering_delta_sign, - vector & leaving_candidates) { - lean_assert(inf_sign != 0); - unsigned bj = this->m_basis[row]; // this is the infeasible basis column - const X & x = this->m_x[bj]; - entering_delta_sign = - get_sign(this->m_pivot_row[entering]) * inf_sign; - lean_assert(entering_delta_sign != 0); - X delta = (inf_sign > 0? (this->m_low_bound_values[bj] - x) : (x - this->m_upper_bound_values[bj])) / abs(this->m_pivot_row[entering]); - if (this->m_column_type[entering] == boxed) { - X span = this->bound_span(entering); - if (span < delta) { - delta = span; - leaving_candidates.push_back(entering); - } else { - leaving_candidates.push_back(bj); - } - } else { - leaving_candidates.push_back(bj); - } - - return delta; - } - - void advance_on_infeasible_row_and_entering(unsigned inf_row, unsigned entering, int inf_sign) { - this->solve_Bd(entering); // puts the tableau column of entering into this->m_ed - int entering_delta_sign; - vector leaving_candidates; - X delta = find_initial_delta_and_its_sign(inf_row, entering, inf_sign, entering_delta_sign, leaving_candidates); - lean_assert(leaving_candidates.size()); - lean_assert(delta > zero_of_type()); - unsigned row = lrand48() % this->m_m; - unsigned initial_row = row; - do { - if (row != inf_row) - update_delta_of_entering(entering_delta_sign, row, delta, leaving_candidates); - if (++row == this->m_m) row = 0; - } while (row != initial_row); - unsigned leaving = find_leaving_for_inf_row_strategy(leaving_candidates); - update_basis_and_x_with_comparison(entering, leaving, delta * entering_delta_sign); - } - - void advance_on_infeasible_row(unsigned i, int inf_sign) { - calculate_pivot_row(i); - int entering = choose_entering_column_for_row_inf_strategy(inf_sign); - if (entering == -1) { - fill_evidence(i, inf_sign); - this->m_status = INFEASIBLE; - return; - } - advance_on_infeasible_row_and_entering(i, entering, inf_sign); - } - - void solve() { - prefix(); - if (is_empty()) { + int inf_sign; + int i = find_infeasible_row(inf_sign); + if (i == -1) { this->m_status = OPTIMAL; - return; + break; } - this->snap_xN_to_bounds(); // we start with non-basic variables at their bounds - lean_assert(non_basis_columns_are_set_correctly()); + advance_on_infeasible_row(i, inf_sign); + if (done()) + break; + } + } - if (this->m_settings.row_feasibility) { - cout << "optimizing by rows " << endl; - row_feasibility_loop(); + int find_infeasible_row(int & inf_sign) { + unsigned offset = lrand48() % this->m_m; + unsigned initial_offset_in_basis = offset; + do { + unsigned j = this->m_basis[offset]; + inf_sign = get_infeasibility_sign(j); + if (inf_sign) + return offset; + if (++offset == this->m_m) offset = 0; + } while (offset != initial_offset_in_basis); + return -1; + } + + int get_infeasibility_sign(unsigned j) const { + const auto & x = this->m_x[j]; + switch (this->m_column_type[j]) { + case fixed: + case boxed: + if (x < this->m_low_bound_values[j]) return 1; + if (x > this->m_upper_bound_values[j]) return -1; + return 0; + case low_bound: + return x < this->m_low_bound_values[j] ? 1 : 0; + case upper_bound: + return x > this->m_upper_bound_values[j]? -1 :0; + default: + return 0; + } + } + + + template + int get_sign(const L & v) { + return v > zero_of_type() ? 1 : (v < zero_of_type() ? -1 : 0); + } + + bool improves_pivot_row_inf(unsigned j, int inf_sign) { + lean_assert(this->m_basis_heading[j] < 0); + // we have x[basis[i]] = sum (mj*x[j]), where mj = -m_pivot_row[j] + + switch (this->m_column_type[j]) { + case fixed: + return false; + case boxed: + { + lean_assert(this->x_is_at_bound(j)); + int j_sign = - get_sign(this->m_pivot_row[j]) * inf_sign; + if (this->x_is_at_low_bound(j)) + return j_sign > 0; + return j_sign < 0; + } + case low_bound: + { + lean_assert(this->x_is_at_low_bound(j)); + int j_sign = - get_sign(this->m_pivot_row[j]) * inf_sign; + return j_sign > 0; + } + case upper_bound: + { + lean_assert(this->x_is_at_upper_bound(j)); + int j_sign = - get_sign(this->m_pivot_row[j]) * inf_sign; + return j_sign < 0; + } + break; + case free_column: { + return numeric_traits::is_zero(this->m_pivot_row[j]) == false; + } + default: + lean_unreachable(); + } + } + + int choose_entering_column_for_row_inf_strategy(int inf_sign) { + unsigned offset = lrand48() % this->m_non_basic_columns.size(); + unsigned initial_offset_in_non_basis = offset; + do { + unsigned j = this->m_non_basic_columns[offset]; + if (improves_pivot_row_inf(j, inf_sign)) + return j; + if (++offset == this->m_non_basic_columns.size()) offset = 0; + } while (offset != initial_offset_in_non_basis); + return -1; + } + + void fill_evidence(unsigned row, int inf_sign) { + m_infeasible_row_sign = inf_sign; + m_infeasible_row.push_back(std::make_pair(numeric_traits::one(), this->m_basis[row])); + for (auto j : this->m_non_basic_columns) { + T aj = this->m_pivot_row[j]; + if (!numeric_traits::is_zero(aj)) { + m_infeasible_row.push_back(std::make_pair(aj, j)); + } + } + } + + + void update_delta_of_entering_and_leaving_candidates(X del, X & delta, + std::vector & leaving_candidates, + unsigned bj) { + if (del < delta) { + leaving_candidates.clear(); + leaving_candidates.push_back(bj); + delta = del; + } else if (del == delta) { + leaving_candidates.push_back(bj); + } + } + + void update_delta_of_entering(int delta_sign, unsigned row, X & delta, + std::vector & leaving_candidates) { + unsigned bj = this->m_basis[row]; // bj - the basis column for the row + const T & ed = this->m_ed[row]; // this is the coefficent before x[entering] in the sum representing the basis column of this row taken with minus + if (numeric_traits::is_zero(ed)) return; + const X & x = this->m_x[bj]; // the value of the basis column + // adjusted sign + int adj_sign = ed < zero_of_type() ? delta_sign : - delta_sign; + + switch (this->m_column_type[bj]) { + case fixed: + case boxed: + if (adj_sign > 0 && x <= this->m_upper_bound_values[bj]) + update_delta_of_entering_and_leaving_candidates((this->m_upper_bound_values[bj] - x) / abs(ed), delta, leaving_candidates, bj); + else if (adj_sign < 0 && x >= this->m_low_bound_values[bj]) + update_delta_of_entering_and_leaving_candidates((x - this->m_low_bound_values[bj]) / abs(ed), delta, leaving_candidates, bj); + break; + case low_bound: + if (adj_sign < 0 && x >= this->m_low_bound_values[bj]) + update_delta_of_entering_and_leaving_candidates((x - this->m_low_bound_values[bj]) / abs(ed), delta, leaving_candidates, bj); + break; + case upper_bound: + if (adj_sign > 0 && x <= this->m_upper_bound_values[bj]) + update_delta_of_entering_and_leaving_candidates((this->m_upper_bound_values[bj] - x) / abs(ed), delta, leaving_candidates, bj); + break; + default: + break; + } + } + + unsigned find_leaving_for_inf_row_strategy(std::vector & leaving_candidates) { + lean_assert(leaving_candidates.size()); + return leaving_candidates[lrand48() % leaving_candidates.size()]; // more randomness + } + + X find_initial_delta_and_its_sign(unsigned row, unsigned entering, + int inf_sign, int & entering_delta_sign, + std::vector & leaving_candidates) { + lean_assert(inf_sign != 0); + unsigned bj = this->m_basis[row]; // this is the infeasible basis column + const X & x = this->m_x[bj]; + entering_delta_sign = - get_sign(this->m_pivot_row[entering]) * inf_sign; + lean_assert(entering_delta_sign != 0); + X delta = (inf_sign > 0? (this->m_low_bound_values[bj] - x) : (x - this->m_upper_bound_values[bj])) / abs(this->m_pivot_row[entering]); + if (this->m_column_type[entering] == boxed) { + X span = this->bound_span(entering); + if (span < delta) { + delta = span; + leaving_candidates.push_back(entering); } else { - cout << "optimizing total infeasibility" << endl; - feasibility_loop(); + leaving_candidates.push_back(bj); } + } else { + leaving_candidates.push_back(bj); } - bool low_bounds_are_set() const { return true; } + return delta; + } - void print_column_info(unsigned j) { - cout << "type = " << column_type_to_string(this->m_column_type[j]) << endl; - switch (this->m_column_type[j]) { - case fixed: - case boxed: - cout << "(" << this->m_low_bound_values[j] << ", " << this->m_upper_bound_values[j] << ")" << endl; - break; - case low_bound: - cout << this->m_low_bound_values[j] << endl; - break; - case upper_bound: - cout << this->m_upper_bound_values[j] << endl; - break; - default: - lean_assert(false); - break; - } + void advance_on_infeasible_row_and_entering(unsigned inf_row, unsigned entering, int inf_sign) { + this->solve_Bd(entering); // puts the tableau column of entering into this->m_ed + int entering_delta_sign; + std::vector leaving_candidates; + X delta = find_initial_delta_and_its_sign(inf_row, entering, inf_sign, entering_delta_sign, leaving_candidates); + lean_assert(leaving_candidates.size()); + lean_assert(delta > zero_of_type()); + unsigned row = lrand48() % this->m_m; + unsigned initial_row = row; + do { + if (row != inf_row) + update_delta_of_entering(entering_delta_sign, row, delta, leaving_candidates); + if (++row == this->m_m) row = 0; + } while (row != initial_row); + unsigned leaving = find_leaving_for_inf_row_strategy(leaving_candidates); + update_basis_and_x_with_comparison(entering, leaving, delta * entering_delta_sign); + } + + void advance_on_infeasible_row(unsigned i, int inf_sign) { + calculate_pivot_row(i); + int entering = choose_entering_column_for_row_inf_strategy(inf_sign); + if (entering == -1) { + fill_evidence(i, inf_sign); + this->m_status = INFEASIBLE; + return; } - }; + advance_on_infeasible_row_and_entering(i, entering, inf_sign); + } + + void solve() { + prefix(); + if (is_empty()) { + this->m_status = OPTIMAL; + return; + } + this->snap_xN_to_bounds(); // we start with non-basic variables at their bounds + lean_assert(non_basis_columns_are_set_correctly()); + + if (this->m_settings.row_feasibility) { + std::cout << "optimizing by rows " << std::endl; + row_feasibility_loop(); + } else { + std::cout << "optimizing total infeasibility" << std::endl; + feasibility_loop(); + } + } + + bool low_bounds_are_set() const { return true; } + + void print_column_info(unsigned j) { + std::cout << "type = " << column_type_to_string(this->m_column_type[j]) << std::endl; + switch (this->m_column_type[j]) { + case fixed: + case boxed: + std::cout << "(" << this->m_low_bound_values[j] << ", " << this->m_upper_bound_values[j] << ")" << std::endl; + break; + case low_bound: + std::cout << this->m_low_bound_values[j] << std::endl; + break; + case upper_bound: + std::cout << this->m_upper_bound_values[j] << std::endl; + break; + default: + lean_unreachable(); + } + } +}; } diff --git a/src/util/lp/lar_solution_signature.h b/src/util/lp/lar_solution_signature.h index 710892e31..b764cd5e9 100644 --- a/src/util/lp/lar_solution_signature.h +++ b/src/util/lp/lar_solution_signature.h @@ -11,8 +11,8 @@ #include "util/lp/lp_settings.h" #include namespace lean { - struct lar_solution_signature { - std::unordered_map non_basic_column_value_positions; - lp_status status; - }; +struct lar_solution_signature { + std::unordered_map non_basic_column_value_positions; + lp_status status; +}; } diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 4fd125c9f..25b43ca54 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -4,7 +4,6 @@ Author: Lev Nachmanson */ - #pragma once #include #include "util/debug.h" @@ -23,77 +22,68 @@ #include "util/lp/scaler.h" namespace std { - template<> - struct hash { - inline size_t operator()(const lean::mpq & v) const { - return v.hash(); +template<> +struct hash { + inline size_t operator()(const lean::mpq & v) const { + return v.hash(); } }; } namespace lean { - using std::string; - using std::cout; - using std::endl; - using std::vector; - using std::unordered_map; - using std::unordered_set; +template +struct conversion_helper { + static V get_low_bound(const column_info & ci) { + return V(ci.get_low_bound(), ci.low_bound_is_strict()? 1 : 0); + } - template - struct conversion_helper { - static V get_low_bound(const column_info & ci) { - return V(ci.get_low_bound(), ci.low_bound_is_strict()? 1 : 0); - } + static V get_upper_bound(const column_info & ci) { + return V(ci.get_upper_bound(), ci.upper_bound_is_strict()? -1 : 0); + } +}; - static V get_upper_bound(const column_info & ci) { - return V(ci.get_upper_bound(), ci.upper_bound_is_strict()? -1 : 0); - } - }; - - template<> - struct conversion_helper { - static double get_low_bound(const column_info & ci) { - if (!ci.low_bound_is_strict()) - return ci.get_low_bound().get_double(); - double eps = 0.00001; - if (!ci.upper_bound_is_set()) - return ci.get_low_bound().get_double() + eps; - eps = std::min((ci.get_upper_bound() - ci.get_low_bound()).get_double()/1000, eps); +template<> +struct conversion_helper { + static double get_low_bound(const column_info & ci) { + if (!ci.low_bound_is_strict()) + return ci.get_low_bound().get_double(); + double eps = 0.00001; + if (!ci.upper_bound_is_set()) return ci.get_low_bound().get_double() + eps; - } - static double get_upper_bound(const column_info & ci) { - if (!ci.upper_bound_is_strict()) - return ci.get_upper_bound().get_double(); - double eps = 0.00001; - if (!ci.low_bound_is_set()) - return ci.get_upper_bound().get_double() - eps; - eps = std::min((ci.get_upper_bound() - ci.get_low_bound()).get_double()/1000, eps); + eps = std::min((ci.get_upper_bound() - ci.get_low_bound()).get_double()/1000, eps); + return ci.get_low_bound().get_double() + eps; + } + static double get_upper_bound(const column_info & ci) { + if (!ci.upper_bound_is_strict()) + return ci.get_upper_bound().get_double(); + double eps = 0.00001; + if (!ci.low_bound_is_set()) return ci.get_upper_bound().get_double() - eps; - } - }; - - + eps = std::min((ci.get_upper_bound() - ci.get_low_bound()).get_double()/1000, eps); + return ci.get_upper_bound().get_double() - eps; + } +}; class lar_solver { unsigned m_available_var_index = 0; unsigned m_available_constr_index = 0; lp_status m_status = UNKNOWN; - unordered_map m_var_names_to_var_index; - unordered_map m_map_from_var_index_to_left_side; - unordered_set m_canonic_left_sides; - unordered_map m_column_indices_to_canonic_left_sides; - unordered_map m_normalized_constraints; + std::unordered_map m_var_names_to_var_index; + std::unordered_map m_map_from_var_index_to_left_side; + std::unordered_set m_canonic_left_sides; + std::unordered_map m_column_indices_to_canonic_left_sides; + std::unordered_map m_normalized_constraints; static_matrix> m_A; lar_core_solver> m_mpq_core_solver; lp_settings m_settings; - vector m_column_types; // this field is passed to the core solver - vector> m_low_bounds; // passed to the core solver - vector> m_upper_bounds; // passed to the core solver - vector m_basis; - vector> m_x; // the solution - unordered_map m_column_names; - vector> m_right_side_vector; // this vector will be all zeroes, it might change when the optimization with fixed variables will used - vector m_costs; + std::vector m_column_types; // this field is passed to the core solver + std::vector> m_low_bounds; // passed to the core solver + std::vector> m_upper_bounds; // passed to the core solver + std::vector m_basis; + std::vector> m_x; // the solution + std::unordered_map m_column_names; + std::vector> m_right_side_vector; // this vector will be all zeroes, it might change when the optimization with fixed variables will used + std::vector m_costs; canonic_left_side * m_infeasible_canonic_left_side = nullptr; // such can be found at the initialization step canonic_left_side * create_or_fetch_existing_left_side(const buffer>& left_side_par) { auto left_side = new canonic_left_side(left_side_par); @@ -125,7 +115,7 @@ class lar_solver { return it->second; } - void add_canonic_left_side_for_var(var_index i, string var_name) { + void add_canonic_left_side_for_var(var_index i, std::string var_name) { buffer> b; b.push_back(std::make_pair(numeric_traits::one(), i)); auto can_ls = new canonic_left_side(b); @@ -265,11 +255,11 @@ class lar_solver { break; case EQ: - { - set_upper_bound_for_column_info(&norm_constr); - set_low_bound_for_column_info(&norm_constr); - } - break; + { + set_upper_bound_for_column_info(&norm_constr); + set_low_bound_for_column_info(&norm_constr); + } + break; default: throw "unexpected"; } @@ -290,9 +280,9 @@ class lar_solver { auto & ci = t->m_column_info; unsigned j = t->m_column_index; lean_assert(valid_index(j)); - string name = ci.get_name(); + std::string name = ci.get_name(); if (name.size() == 0) - name = string("_s") + T_to_string(j); + name = std::string("_s") + T_to_string(j); m_column_names[j] = name; } } @@ -309,7 +299,7 @@ class lar_solver { } template - void fill_bounds_for_core_solver(vector & lb, vector & ub) { + void fill_bounds_for_core_solver(std::vector & lb, std::vector & ub) { unsigned n = m_canonic_left_sides.size(); // this is the number of columns lb.resize(n); ub.resize(n); @@ -326,14 +316,14 @@ class lar_solver { template - void resize_x_and_init_with_zeros(vector & x, unsigned n) { + void resize_x_and_init_with_zeros(std::vector & x, unsigned n) { x.clear(); x.resize(n, zero_of_type()); // init with zeroes } template - void resize_x_and_init_with_signature(vector & x, vector & low_bound, - vector & upper_bound, const lar_solution_signature & signature) { + void resize_x_and_init_with_signature(std::vector & x, std::vector & low_bound, + std::vector & upper_bound, const lar_solution_signature & signature) { x.clear(); x.resize(low_bound.size()); for (auto & t : signature.non_basic_column_value_positions) { @@ -341,7 +331,7 @@ class lar_solver { } } - template V get_column_val(vector & low_bound, vector & upper_bound, non_basic_column_value_position pos_type, unsigned j) { + template V get_column_val(std::vector & low_bound, std::vector & upper_bound, non_basic_column_value_position pos_type, unsigned j) { switch (pos_type) { case at_low_bound: return low_bound[j]; case at_fixed: @@ -354,7 +344,7 @@ class lar_solver { public: ~lar_solver() { - vector to_delete; + std::vector to_delete; for (auto it : m_canonic_left_sides) to_delete.push_back(it); for (auto t : to_delete) @@ -380,7 +370,7 @@ public: } - var_index add_var(string s) { + var_index add_var(std::string s) { auto got = m_var_names_to_var_index.find(s); if (got != m_var_names_to_var_index.end()) return got->second; @@ -392,7 +382,7 @@ public: constraint_index add_constraint(const buffer>& left_side, lconstraint_kind kind_par, mpq right_side_par) { if (left_side.size() == 0) { - cout << "cannot add a constraint without left side" << endl; + std::cout << "cannot add a constraint without left side" << std::endl; return (constraint_index)(-1); } constraint_index i = m_available_constr_index++; @@ -412,18 +402,18 @@ public: } bool all_constraints_hold() { - unordered_map var_map; + std::unordered_map var_map; get_model(var_map); for ( auto & it : m_normalized_constraints ) if (!constraint_holds(it.second.m_origin_constraint, var_map)) { print_constraint(&it.second.m_origin_constraint); - cout << endl; + std::cout << std::endl; return false; } return true; } - bool constraint_holds(const lar_constraint & constr, unordered_map & var_map) { + bool constraint_holds(const lar_constraint & constr, std::unordered_map & var_map) { mpq left_side_val = get_left_side_val(constr, var_map); switch (constr.m_kind) { case LE: return left_side_val <= constr.m_right_side; @@ -453,9 +443,9 @@ public: for (auto & it : evidence) { mpq coeff = it.first; constraint_index con_ind = it.second; - cout << coeff.get_double() << endl; + std::cout << coeff.get_double() << std::endl; lar_constraint & constr = m_normalized_constraints[con_ind].m_origin_constraint; - print_constraint(&constr); cout << endl; + print_constraint(&constr); std::cout << std::endl; lconstraint_kind kind = coeff.is_pos()? constr.m_kind: flip_kind(constr.m_kind); if (kind == GT || kind == LT) @@ -470,7 +460,7 @@ public: return n_of_G == 0 || n_of_L == 0; } - void register_in_map(unordered_map & coeffs, lar_constraint & cn, const mpq & a) { + void register_in_map(std::unordered_map & coeffs, lar_constraint & cn, const mpq & a) { for (auto & it : cn.m_left_side) { unsigned j = it.first; auto p = coeffs.find(j); @@ -479,7 +469,7 @@ public: } } bool the_left_sides_sum_to_zero(const buffer> & evidence) { - unordered_map coeff_map; + std::unordered_map coeff_map; for (auto & it : evidence) { mpq coeff = it.first; constraint_index con_ind = it.second; @@ -533,7 +523,7 @@ public: } template - void init_right_sides_with_zeros(vector & rs) { + void init_right_sides_with_zeros(std::vector & rs) { rs.clear(); rs.resize(m_basis.size(), zero_of_type()); } @@ -556,10 +546,10 @@ public: } template - void prepare_core_solver_fields(static_matrix & A, vector & x, - vector & right_side_vector, - vector & low_bound, - vector & upper_bound) { + void prepare_core_solver_fields(static_matrix & A, std::vector & x, + std::vector & right_side_vector, + std::vector & low_bound, + std::vector & upper_bound) { create_matrix_A(A); fill_bounds_for_core_solver(low_bound, upper_bound); if (m_status == INFEASIBLE) { @@ -571,10 +561,10 @@ public: } template - void prepare_core_solver_fields_with_signature(static_matrix & A, vector & x, - vector & right_side_vector, - vector & low_bound, - vector & upper_bound, const lar_solution_signature & signature) { + void prepare_core_solver_fields_with_signature(static_matrix & A, std::vector & x, + std::vector & right_side_vector, + std::vector & low_bound, + std::vector & upper_bound, const lar_solution_signature & signature) { create_matrix_A(A); fill_bounds_for_core_solver(low_bound, upper_bound); if (m_status == INFEASIBLE) { @@ -586,9 +576,9 @@ public: void find_solution_signature_with_doubles(lar_solution_signature & signature) { static_matrix A; - vector x, right_side_vector, low_bounds, upper_bounds; + std::vector x, right_side_vector, low_bounds, upper_bounds; prepare_core_solver_fields(A, x, right_side_vector, low_bounds, upper_bounds); - vector column_scale_vector; + std::vector column_scale_vector; scaler scaler(right_side_vector, A, m_settings.scaling_minimum, m_settings.scaling_maximum, column_scale_vector, this->m_settings); if (!scaler.scale()) { // the scale did not succeed, unscaling @@ -597,7 +587,7 @@ public: for (auto & s : column_scale_vector) s = one_of_type(); } - vector costs(A.column_count()); + std::vector costs(A.column_count()); auto core_solver = lp_primal_core_solver(A, right_side_vector, x, @@ -643,7 +633,7 @@ public: } void get_infeasibility_evidence(buffer> & evidence){ if (!m_mpq_core_solver.get_infeasible_row_sign()) { - cout << "don't have the infeasibility evidence" << endl; + std::cout << "don't have the infeasibility evidence" << std::endl; return; } // the infeasibility sign @@ -654,7 +644,7 @@ public: } void get_infeasibility_evidence_for_inf_sign(buffer> & evidence, - const vector> & inf_row, + const std::vector> & inf_row, int inf_sign) { for (auto & it : inf_row) { mpq coeff = it.first; @@ -714,19 +704,19 @@ public: } } - void get_model(unordered_map & variable_values){ + void get_model(std::unordered_map & variable_values){ lean_assert(m_status == OPTIMAL); mpq delta = find_delta_for_strict_bounds(); for (auto & it : m_map_from_var_index_to_left_side) { numeric_pair & rp = m_x[it.second->m_column_index]; - // cout << it.second->m_column_info.get_name() << " = " << rp << endl; + // std::cout << it.second->m_column_info.get_name() << " = " << rp << std::endl; variable_values[it.first] = rp.x + delta * rp.y; } } - string get_variable_name(var_index vi) { + std::string get_variable_name(var_index vi) { if (m_map_from_var_index_to_left_side.size() <= vi) { - string s="variable " + T_to_string(vi) + " is not found"; + std::string s = "variable " + T_to_string(vi) + " is not found"; return s; } return m_map_from_var_index_to_left_side[vi]->m_column_info.get_name(); @@ -735,8 +725,8 @@ public: // ********** print region start void print_constraint(constraint_index ci) { if (m_normalized_constraints.size() <= ci) { - string s = "constraint " + T_to_string(ci) + " is not found"; - cout << s << endl; + std::string s = "constraint " + T_to_string(ci) + " is not found"; + std::cout << s << std::endl; return; } @@ -751,15 +741,15 @@ public: first = false; } else { if (val.is_pos()) { - cout << " + "; + std::cout << " + "; } else { - cout << " - "; + std::cout << " - "; val = -val; } } if (val != numeric_traits::one()) - cout << T_to_string(val); - cout << m_map_from_var_index_to_left_side[it.second]->m_column_info.get_name(); + std::cout << T_to_string(val); + std::cout << m_map_from_var_index_to_left_side[it.second]->m_column_info.get_name(); } } @@ -772,21 +762,20 @@ public: first = false; } else { if (val.is_pos()) { - cout << " + "; + std::cout << " + "; } else { - cout << " - "; + std::cout << " - "; val = -val; } } if (val != numeric_traits::one()) - cout << val; - cout << m_map_from_var_index_to_left_side[it.second]->m_column_info.get_name(); + std::cout << val; + std::cout << m_map_from_var_index_to_left_side[it.second]->m_column_info.get_name(); } } - - numeric_pair get_infeasibility_from_core_solver(unordered_map & solution) { + numeric_pair get_infeasibility_from_core_solver(std::unordered_map & solution) { prepare_independently_of_numeric_type(); prepare_core_solver_fields(m_A, m_x, m_right_side_vector, m_low_bounds, m_upper_bounds); m_mpq_core_solver.prefix(); // just to fill the core solver @@ -803,34 +792,34 @@ public: if (static_cast(ls->m_column_index) == j) { auto & ci = ls->m_column_info; if (ci.low_bound_is_set()) { - cout << "l = " << ci.get_low_bound(); + std::cout << "l = " << ci.get_low_bound(); } if (ci.upper_bound_is_set()) { - cout << "u = " << ci.get_upper_bound(); + std::cout << "u = " << ci.get_upper_bound(); } - cout << endl; + std::cout << std::endl; m_mpq_core_solver.print_column_info(j); } } } - mpq get_infeasibility_of_solution(unordered_map & solution) { - cout << "solution" << endl; + mpq get_infeasibility_of_solution(std::unordered_map & solution) { + std::cout << "solution" << std::endl; for (auto it : solution) { - cout << it.first << " = " << it.second.get_double() << endl; + std::cout << it.first << " = " << it.second.get_double() << std::endl; } mpq ret = numeric_traits::zero(); for (auto it : m_normalized_constraints) { ret += get_infeasibility_of_constraint(it.second, solution); } - cout << "ret = " << ret.get_double() << endl; + std::cout << "ret = " << ret.get_double() << std::endl; auto core_inf = get_infeasibility_from_core_solver(solution); - cout << "core inf = " << T_to_string(core_inf) << endl; + std::cout << "core inf = " << T_to_string(core_inf) << std::endl; lean_assert(numeric_pair(ret, 0) == core_inf); return ret; } - mpq get_infeasibility_of_constraint(const lar_normalized_constraint & norm_constr, unordered_map & solution) { + mpq get_infeasibility_of_constraint(const lar_normalized_constraint & norm_constr, std::unordered_map & solution) { auto kind = norm_constr.m_kind; mpq left_side_val = get_canonic_left_side_val(norm_constr.m_canonic_left_side, solution); @@ -849,14 +838,14 @@ public: } } - mpq get_canonic_left_side_val(canonic_left_side * ls, unordered_map & solution) { + mpq get_canonic_left_side_val(canonic_left_side * ls, std::unordered_map & solution) { mpq ret = numeric_traits::zero(); for (auto it : ls->m_coeffs) { var_index j = it.second; auto vi = m_map_from_var_index_to_left_side.find(j); lean_assert(vi != m_map_from_var_index_to_left_side.end()); canonic_left_side * var_ls = vi->second; - string s = var_ls->m_column_info.get_name(); + std::string s = var_ls->m_column_info.get_name(); auto t = solution.find(s); lean_assert(t != solution.end()); ret += it.first * (t->second); @@ -864,7 +853,7 @@ public: return ret; } - mpq get_left_side_val(const lar_constraint & cns, const unordered_map & var_map) { + mpq get_left_side_val(const lar_constraint & cns, const std::unordered_map & var_map) { mpq ret = numeric_traits::zero(); for (auto it : cns.m_left_side) { var_index j = it.first; @@ -877,7 +866,7 @@ public: void print_constraint(const lar_base_constraint * c) { print_left_side_of_constraint(c); - cout <<" " << lconstraint_kind_string(c->m_kind) << " " << c->m_right_side; + std::cout <<" " << lconstraint_kind_string(c->m_kind) << " " << c->m_right_side; } unsigned get_total_iterations() const { return m_mpq_core_solver.m_total_iterations; } }; diff --git a/src/util/lp/lp_core_solver_base.h b/src/util/lp/lp_core_solver_base.h index 73e987b93..ed044931f 100644 --- a/src/util/lp/lp_core_solver_base.h +++ b/src/util/lp/lp_core_solver_base.h @@ -4,23 +4,24 @@ Author: Lev Nachmanson */ - #pragma once -#include -#include "util/lp/lp.h" -#include "util/lp/core_solver_pretty_printer.h" #include #include +#include +#include "util/sstream.h" +#include "util/exception.h" +#include "util/lp/lp.h" +#include "util/lp/core_solver_pretty_printer.h" #include "util/lp/numeric_pair.h" namespace lean { - void init_basic_part_of_basis_heading(std::vector & basis, unsigned m, vector & basis_heading) { +void init_basic_part_of_basis_heading(std::vector & basis, unsigned m, std::vector & basis_heading) { for (unsigned i = 0; i < m; i++) { unsigned column = basis[i]; basis_heading[column] = i; } } -void init_non_basic_part_of_basis_heading(vector & basis_heading, vector & non_basic_columns, unsigned n) { +void init_non_basic_part_of_basis_heading(std::vector & basis_heading, std::vector & non_basic_columns, unsigned n) { for (int j = n; j--;){ if (basis_heading[j] < 0) { non_basic_columns.push_back(j); @@ -30,10 +31,10 @@ void init_non_basic_part_of_basis_heading(vector & basis_heading, vector & basis, - unsigned m, - vector & basis_heading, - unsigned n, - vector & non_basic_columns) { + unsigned m, + std::vector & basis_heading, + unsigned n, + std::vector & non_basic_columns) { init_basic_part_of_basis_heading(basis, m, basis_heading); init_non_basic_part_of_basis_heading(basis_heading, non_basic_columns, n); } @@ -45,9 +46,9 @@ public: unsigned m_n; // the number of columns in the matrix m_A std::vector m_pivot_row_of_B_1; // the pivot row of the reverse of B std::vector m_pivot_row; // this is the real pivot row of the simplex tableu - vector m_pivot_row_index; + std::vector m_pivot_row_index; static_matrix & m_A; // the matrix A - vector & m_b; // the right side + std::vector & m_b; // the right side std::vector & m_basis; std::vector m_basis_heading; std::vector & m_x; // a feasible solution, the fist time set in the constructor @@ -57,31 +58,31 @@ public: lp_status m_status; // a device that is able to solve Bx=c, xB=d, and change the basis lu * m_factorization; - const unordered_map & m_column_names; + const std::unordered_map & m_column_names; indexed_vector m_w; // the vector featuring in 24.3 of the Chvatal book std::vector m_d; // the vector of reduced costs std::vector m_ed; // the solution of B*m_ed = a - vector m_index_of_ed; + std::vector m_index_of_ed; unsigned m_total_iterations = 0; int m_start_time; unsigned m_iters_with_no_cost_growing = 0; - vector m_non_basic_columns; - vector & m_column_type; - vector & m_low_bound_values; - vector & m_upper_bound_values; - vector m_column_norms; // the approximate squares of column norms that help choosing a profitable column - vector m_copy_of_xB; + std::vector m_non_basic_columns; + std::vector & m_column_type; + std::vector & m_low_bound_values; + std::vector & m_upper_bound_values; + std::vector m_column_norms; // the approximate squares of column norms that help choosing a profitable column + std::vector m_copy_of_xB; unsigned m_refactor_counter = 200; lp_core_solver_base(static_matrix & A, - vector & b, // the right side vector + std::vector & b, // the right side vector std::vector & basis, std::vector & x, std::vector & costs, lp_settings & settings, - const unordered_map & column_names, - vector & column_types, - vector & low_bound_values, - vector & upper_bound_values): + const std::unordered_map & column_names, + std::vector & column_types, + std::vector & low_bound_values, + std::vector & upper_bound_values): m_m(A.row_count()), m_n(A.column_count()), m_pivot_row_of_B_1(m_m), @@ -130,7 +131,7 @@ public: delete m_factorization; } - vector & non_basis() { + std::vector & non_basis() { return m_factorization->m_non_basic_columns; } @@ -242,11 +243,11 @@ public: X eps = feps * (one + T(0.1) * abs(m_b[i])); if (delta >eps) { - cout << "x is off ("; - cout << "m_b[" << i << "] = " << m_b[i] << " "; - cout << "left side = " << m_A.dot_product_with_row(i, m_x) << ' '; - cout << "delta = " << delta << ' '; - cout << "iters = " << m_total_iterations << ")" << endl; + std::cout << "x is off ("; + std::cout << "m_b[" << i << "] = " << m_b[i] << " "; + std::cout << "left side = " << m_A.dot_product_with_row(i, m_x) << ' '; + std::cout << "delta = " << delta << ' '; + std::cout << "iters = " << m_total_iterations << ")" << std::endl; return true; } } @@ -307,13 +308,13 @@ public: } void print_statistics(X cost) { - cout << "cost = " << T_to_string(cost) << - ", nonzeros = " << m_factorization->get_number_of_nonzeroes() << endl; + std::cout << "cost = " << T_to_string(cost) << + ", nonzeros = " << m_factorization->get_number_of_nonzeroes() << std::endl; } bool print_statistics_with_iterations_and_check_that_the_time_is_over(unsigned total_iterations) { if (total_iterations % m_settings.report_frequency == 0) { - cout << "iterations = " << total_iterations << ", nonzeros = " << m_factorization->get_number_of_nonzeroes() << endl; + std::cout << "iterations = " << total_iterations << ", nonzeros = " << m_factorization->get_number_of_nonzeroes() << std::endl; if (time_is_over()) { return true; } @@ -321,9 +322,9 @@ public: return false; } - bool print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(string str, unsigned total_iterations) { + bool print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(std::string str, unsigned total_iterations) { if (total_iterations % m_settings.report_frequency == 0) { - cout << str << " iterations = " << total_iterations << " cost = " << T_to_string(get_cost()) <<", nonzeros = " << m_factorization->get_number_of_nonzeroes() << endl; + std::cout << str << " iterations = " << total_iterations << " cost = " << T_to_string(get_cost()) <<", nonzeros = " << m_factorization->get_number_of_nonzeroes() << std::endl; if (time_is_over()) { return true; } @@ -333,7 +334,7 @@ public: bool print_statistics_with_cost_and_check_that_the_time_is_over(unsigned total_iterations, X cost) { if (total_iterations % m_settings.report_frequency == 0) { - cout << "iterations = " << total_iterations << ", "; + std::cout << "iterations = " << total_iterations << ", "; print_statistics(cost); if (time_is_over()) { return true; @@ -344,7 +345,7 @@ public: bool print_statistics_and_check_that_the_time_is_over(unsigned total_iterations) { if (total_iterations % (numeric_traits::precise()? static_cast(m_settings.report_frequency/10) : m_settings.report_frequency) == 0) { - cout << "iterations = " << total_iterations << ", "; + std::cout << "iterations = " << total_iterations << ", "; if (time_is_over()) { return true; } @@ -414,16 +415,14 @@ public: case low_bound: return x_is_at_low_bound(j) && d_is_not_negative(j); case upper_bound: - cout << "upper_bound type should be switched to low_bound" << endl; + std::cout << "upper_bound type should be switched to low_bound" << std::endl; lean_assert(false); // impossible case case free_column: return numeric_traits::is_zero(m_d[j]); default: - cout << "column = " << j << endl; - cout << "unexpected column type = " << column_type_to_string(m_column_type[j]) << endl; - lean_assert(false); - throw "unexpected column type"; - break; + std::cout << "column = " << j << std::endl; + std::cout << "unexpected column type = " << column_type_to_string(m_column_type[j]) << std::endl; + lean_unreachable(); } } bool d_is_not_negative(unsigned j) { @@ -444,13 +443,13 @@ public: bool time_is_over() { int span_in_mills = get_millisecond_span(m_start_time); if (span_in_mills / 1000.0 > m_settings.time_limit) { - cout << "time is over" << endl; + std::cout << "time is over" << std::endl; return true; } return false; } - void rs_minus_Anx(vector & rs) { + void rs_minus_Anx(std::vector & rs) { unsigned row = m_m; while (row--) { auto &rsv = rs[row] = m_b[row]; @@ -467,9 +466,9 @@ public: solve_Ax_eq_b(); bool ret= !A_mult_x_is_off(); if (ret) - cout << "find_x_by_solving succeeded" << endl; + std::cout << "find_x_by_solving succeeded" << std::endl; else - cout << "find_x_by_solving did not succeed" << endl; + std::cout << "find_x_by_solving did not succeed" << std::endl; return ret; } @@ -487,8 +486,7 @@ public: m_refactor_counter = 0; m_iters_with_no_cost_growing++; if (m_factorization->get_status() != LU_status::OK) { - cout << "failing refactor on off_result for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << m_total_iterations << endl; - throw ""; + throw exception(sstream() << "failing refactor on off_result for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << m_total_iterations); } return false; } @@ -509,11 +507,11 @@ public: m_factorization->change_basis(entering, leaving); init_factorization(m_factorization, m_A, m_basis, m_basis_heading, m_settings, m_non_basic_columns); if (m_factorization->get_status() != LU_status::OK || A_mult_x_is_off()) { - cout << "failing refactor for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << m_total_iterations << endl; + std::cout << "failing refactor for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << m_total_iterations << std::endl; restore_x_and_refactor(entering, leaving, tt); lean_assert(!A_mult_x_is_off()); m_iters_with_no_cost_growing++; - cout << "rolled back after failing of init_factorization()" << endl; + std::cout << "rolled back after failing of init_factorization()" << std::endl; m_status = UNSTABLE; return false; } @@ -571,12 +569,12 @@ public: restore_x(entering, t); init_factorization(m_factorization, m_A, m_basis, m_basis_heading, m_settings, m_non_basic_columns); if (m_factorization->get_status() == LU_status::Degenerated) { - cout << "cannot refactor" << endl; + std::cout << "cannot refactor" << std::endl; m_status = lp_status::FLOATING_POINT_ERROR; } // solve_Ax_eq_b(); if (A_mult_x_is_off()) { - cout << "cannot restore solution" << endl; + std::cout << "cannot restore solution" << std::endl; m_status = lp_status::FLOATING_POINT_ERROR; return; } @@ -584,7 +582,7 @@ public: void restore_x(unsigned entering, X const & t) { if (is_zero(t)) return; - cout << "calling restore for entering " << entering << endl; + std::cout << "calling restore for entering " << entering << std::endl; m_x[entering] -= t; for (unsigned i : m_index_of_ed) { m_x[m_basis[i]] = m_copy_of_xB[i]; @@ -612,7 +610,7 @@ public: } } - void copy_rs_to_xB(vector & rs) { + void copy_rs_to_xB(std::vector & rs) { unsigned j = m_m; while (j--) { m_x[m_basis[j]] = rs[j]; @@ -636,26 +634,26 @@ public: auto it = m_column_names.find(column); if (it == m_column_names.end()) { std::string name = T_to_string(column); - return std::string(string("u") + name); + return std::string(std::string("u") + name); } return it->second; } - void copy_right_side(vector & rs) { + void copy_right_side(std::vector & rs) { unsigned i = m_m; while (i --) { rs[i] = m_b[i]; } } - void add_delta_to_xB(vector & del) { + void add_delta_to_xB(std::vector & del) { unsigned i = m_m; while (i--) { this->m_x[this->m_basis[i]] -= del[i]; } } - void find_error_in_BxB(vector& rs){ + void find_error_in_BxB(std::vector& rs){ unsigned row = m_m; while (row--) { auto &rsv = rs[row]; @@ -670,9 +668,9 @@ public: // recalculates the projection of x to B, such that Ax = b, whereab is the right side void solve_Ax_eq_b() { - vector rs(m_m); + std::vector rs(m_m); rs_minus_Anx(rs); - vector rrs = rs; // another copy of rs + std::vector rrs = rs; // another copy of rs m_factorization->solve_By(rs); copy_rs_to_xB(rs); find_error_in_BxB(rrs); diff --git a/src/util/lp/lp_dual_core_solver.h b/src/util/lp/lp_dual_core_solver.h index 87185710e..405be4b2a 100644 --- a/src/util/lp/lp_dual_core_solver.h +++ b/src/util/lp/lp_dual_core_solver.h @@ -17,7 +17,7 @@ namespace lean { template class lp_dual_core_solver:public lp_core_solver_base { public: - vector & m_can_enter_basis; + std::vector & m_can_enter_basis; int m_r; // the row of the leaving column int m_p; // leaving column; that is m_p = m_basis[m_r] T m_delta; // the offset of the leaving basis variable @@ -29,21 +29,21 @@ public: std::set m_breakpoint_set; // it is F in "Progress in the dual simplex method ..." std::set m_flipped_boxed; std::set m_tight_set; // it is the set of all breakpoints that become tight when m_q becomes tight - vector m_a_wave; - vector m_betas; // m_betas[i] is approximately a square of the norm of the i-th row of the reverse of B + std::vector m_a_wave; + std::vector m_betas; // m_betas[i] is approximately a square of the norm of the i-th row of the reverse of B T m_harris_tolerance; lp_dual_core_solver(static_matrix & A, - vector & can_enter_basis, - vector & b, // the right side vector - vector & x, // the number of elements in x needs to be at least as large as the number of columns in A - vector & basis, - vector & costs, - vector & column_type_array, - vector & low_bound_values, - vector & upper_bound_values, + std::vector & can_enter_basis, + std::vector & b, // the right side std::vector + std::vector & x, // the number of elements in x needs to be at least as large as the number of columns in A + std::vector & basis, + std::vector & costs, + std::vector & column_type_array, + std::vector & low_bound_values, + std::vector & upper_bound_values, lp_settings & settings, - unordered_map const & column_names): + std::unordered_map const & column_names): lp_core_solver_base(A, b, basis, @@ -82,11 +82,11 @@ public: } void print_nb() { - cout << "this is nb " << endl; + std::cout << "this is nb " << std::endl; for (auto l : this->m_factorization->m_non_basic_columns) { - cout << l << " "; + std::cout << l << " "; } - cout << endl; + std::cout << std::endl; } void restore_non_basis() { @@ -108,7 +108,7 @@ public: if (!(this->m_refactor_counter++ >= 200)) { this->m_factorization->replace_column(leaving, this->m_ed[this->m_factorization->basis_heading(leaving)], this->m_w); if (this->m_factorization->get_status() != LU_status::OK) { - cout << "failed on replace_column( " << leaving << ", " << this->m_ed[this->m_factorization->basis_heading(leaving)] << ") total_iterations = " << this->m_total_iterations << endl; + std::cout << "failed on replace_column( " << leaving << ", " << this->m_ed[this->m_factorization->basis_heading(leaving)] << ") total_iterations = " << this->m_total_iterations << std::endl; init_factorization(this->m_factorization, this->m_A, this->m_basis, this->m_basis_heading, this->m_settings, this->m_non_basic_columns); this->m_iters_with_no_cost_growing++; this->m_status = UNSTABLE; @@ -119,7 +119,7 @@ public: this->m_factorization->change_basis(entering, leaving); init_factorization(this->m_factorization, this->m_A, this->m_basis, this->m_basis_heading, this->m_settings, this->m_non_basic_columns); if (this->m_factorization->get_status() != LU_status::OK) { - cout << "failing refactor for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << this->m_total_iterations << endl; + std::cout << "failing refactor for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << this->m_total_iterations << std::endl; this->m_iters_with_no_cost_growing++; return false; } @@ -137,7 +137,7 @@ public: this->fill_reduced_costs_from_m_y_by_rows(); } - vector & non_basis() { return this->m_factorization->m_non_basic_columns; } + std::vector & non_basis() { return this->m_factorization->m_non_basic_columns; } void init_betas() { // todo : look at page 194 of Progress in the dual simplex algorithm for solving large scale LP problems : techniques for a fast and stable implementation @@ -185,10 +185,10 @@ public: } // void print_x_and_low_bound(unsigned p) { - // cout << "x l[" << p << "] = " << this->m_x[p] << " " << this->m_low_bound_values[p] << endl; + // std::cout << "x l[" << p << "] = " << this->m_x[p] << " " << this->m_low_bound_values[p] << std::endl; // } // void print_x_and_upper_bound(unsigned p) { - // cout << "x u[" << p << "] = " << this->m_x[p] << " " << this->m_upper_bound_values[p] << endl; + // std::cout << "x u[" << p << "] = " << this->m_x[p] << " " << this->m_upper_bound_values[p] << std::endl; // } // returns the @@ -199,13 +199,13 @@ public: case boxed: if (this->x_below_low_bound(p)) { T del = get_edge_steepness_for_low_bound(p); - // cout << "case boxed low_bound in pricing" << endl; + // std::cout << "case boxed low_bound in pricing" << std::endl; // print_x_and_low_bound(p); return del; } if (this->x_above_upper_bound(p)) { T del = get_edge_steepness_for_upper_bound(p); - // cout << "case boxed at upper_bound in pricing" << endl; + // std::cout << "case boxed at upper_bound in pricing" << std::endl; // print_x_and_upper_bound(p); return del; } @@ -213,7 +213,7 @@ public: case low_bound: if (this->x_below_low_bound(p)) { T del = get_edge_steepness_for_low_bound(p); - // cout << "case low_bound in pricing" << endl; + // std::cout << "case low_bound in pricing" << std::endl; // print_x_and_low_bound(p); return del; } @@ -222,7 +222,7 @@ public: case upper_bound: if (this->x_above_upper_bound(p)) { T del = get_edge_steepness_for_upper_bound(p); - // cout << "case upper_bound in pricing" << endl; + // std::cout << "case upper_bound in pricing" << std::endl; // print_x_and_upper_bound(p); return del; } @@ -232,11 +232,7 @@ public: lean_assert(numeric_traits::is_zero(this->m_d[p])); return numeric_traits::zero(); default: - cout << "row = " << i << " p = " << p << endl; - cout << "unexpected column type = " << column_type_to_string(this->m_column_type[p]) << endl; - lean_assert(false); - throw "unexpected column type"; - break; + lean_unreachable(); } } @@ -282,7 +278,7 @@ public: rows_left = number_of_rows_to_try; goto loop_start; // if (this->m_total_iterations % 80 == 0) { - // cout << "m_delta = " << m_delta << endl; + // std::cout << "m_delta = " << m_delta << std::endl; // } } } @@ -312,58 +308,22 @@ public: if (this->x_above_upper_bound(m_p)) { return 1; } - lean_assert(false); // wrong choice of leaving row - throw "wrong choice of leaving row"; + lean_unreachable(); case low_bound: if (this->x_below_low_bound(m_p)) { return -1; } - lean_assert(false); // wrong choice of leaving row - throw "wrong choice of leaving row"; + lean_unreachable(); case upper_bound: if (this->x_above_upper_bound(m_p)) { return 1; } - lean_assert(false); // wrong choice of leaving row - throw "wrong choice of leaving row"; + lean_unreachable(); default: - cout << column_type_to_string(this->m_column_type[m_p]) << endl; - lean_assert(false); // wrong choice of leaving row - throw "wrong choice of leaving row"; - break; + lean_unreachable(); } } - - // void try_update_theta_D_and_q_for_boxed(unsigned j) { - // if (this->m_settings.abs_val_is_smaller_than_zero_tolerance(this->m_pivot_row[j])) { - // return; - // } - - // T ratio = abs(this->m_d[j] / this->m_pivot_row[j]); - // if (ratio < m_theta_D) { - // m_theta_D = ratio; - // m_q = j; - // m_delta -= abs(bound_span(j) * this->m_pivot_row[j]); - // } - // } - - - // void try_update_theta_D_and_q(unsigned j) { - // if (this->m_settings.abs_val_is_smaller_than_zero_tolerance(this->m_pivot_row[j])) { - // return; - // cout << " investigate " << endl; - // throw "try_update_theta_D_and_q"; - // } - - // T ratio = this->m_d[j] / (m_sign_of_alpha_r * this->m_pivot_row[j]); - // if (ratio < m_theta_D) { - // m_theta_D = ratio; - // m_q = j; - // } - // } - - bool can_be_breakpoint(unsigned j) { if (this->pivot_row_element_is_too_small_for_ratio_test(j)) return false; switch (this->m_column_type[j]) { @@ -416,35 +376,26 @@ public: if (this->x_above_upper_bound(m_p)) { return this->m_x[m_p] - this->m_upper_bound_values[m_p];; } - cout << "incorrect m_p = " << m_p << endl; - lean_assert(false); - throw "incorrect m_p"; + lean_unreachable(); case low_bound: if (this->x_below_low_bound(m_p)) { return this->m_x[m_p] - this->m_low_bound_values[m_p]; } - cout << "incorrect m_p = " << m_p << endl; - lean_assert(false); - throw "incorrect m_p"; - + lean_unreachable(); case upper_bound: if (this->x_above_upper_bound(m_p)) { return get_edge_steepness_for_upper_bound(m_p); } - cout << "incorrect m_p = " << m_p << endl; - lean_assert(false); - throw "incorrect m_p"; + lean_unreachable(); case fixed: return this->m_x[m_p] - this->m_upper_bound_values[m_p];; default: - cout << "unsigned column type " << this->m_column_type[m_p] << endl; - throw "unhandled column type"; - break; + lean_unreachable(); } } void restore_d() { - cout << "restore_d" << endl; + std::cout << "restore_d" << std::endl; this->m_d[m_p] = numeric_traits::zero(); for (auto j : non_basis()) { this->m_d[j] += m_theta_D * this->m_pivot_row[j]; @@ -456,8 +407,8 @@ public: for (auto j : non_basis()) { T d = this->m_costs[j] - this->m_A.dot_product_with_column(this->m_y, j); if (numeric_traits::get_double(abs(d - this->m_d[j])) >= 0.001) { - cout << "m_total_iterations = " << this->m_total_iterations << endl; - cout << "d[" << j << "] = " << this->m_d[j] << " but should be " << d << endl; + std::cout << "m_total_iterations = " << this->m_total_iterations << std::endl; + std::cout << "d[" << j << "] = " << this->m_d[j] << " but should be " << d << std::endl; return false; } } @@ -517,11 +468,7 @@ public: case free_column: break; default: - cout << "column = " << j << endl; - cout << "unexpected column type = " << column_type_to_string(this->m_column_type[j]) << endl; - lean_assert(false); - throw "unexpected column type"; - break; + lean_unreachable(); } } @@ -532,7 +479,7 @@ public: } void init_beta_precisely(unsigned i) { - vector vec(this->m_m, numeric_traits::zero()); + std::vector vec(this->m_m, numeric_traits::zero()); vec[i] = numeric_traits::one(); this->m_factorization->solve_yB(vec); T beta = numeric_traits::zero(); @@ -543,12 +490,12 @@ public: } void init_betas_precisely() { - cout << "init beta precisely..." << endl; + std::cout << "init beta precisely..." << std::endl; unsigned i = this->m_m; while (i--) { init_beta_precisely(i); } - cout << "done" << endl; + std::cout << "done" << std::endl; } // step 7 of the algorithm from Progress @@ -569,7 +516,7 @@ public: } void revert_to_previous_basis() { - cout << "recovering basis p = " << m_p << " q = " << m_q << endl; + std::cout << "recovering basis p = " << m_p << " q = " << m_q << std::endl; this->m_factorization->change_basis(m_p, m_q); init_factorization(this->m_factorization, this->m_A, this->m_basis, this->m_basis_heading, this->m_settings, this->m_non_basic_columns); if (this->m_factorization->get_status() != LU_status::OK) { @@ -590,15 +537,12 @@ public: bool problem_is_dual_feasible() { for (unsigned j : non_basis()){ if (!this->column_is_dual_feasible(j)) { - cout << "column " << j << " is not dual feasible" << endl; - cout << "m_d[" << j << "] = " << this->m_d[j] << endl; - cout << "x[" << j << "] = " << this->m_x[j] << endl; - cout << "type = " << column_type_to_string(this->m_column_type[j]) << endl; - cout << "bounds = " << this->m_low_bound_values[j] << "," << this->m_upper_bound_values[j] << endl; - cout << "m_total_iterations = " << this->m_total_iterations << endl; - // cout << "m_betas "; - // print_vector(m_betas); - // column_is_dual_feasible(j); // debug + std::cout << "column " << j << " is not dual feasible" << std::endl; + std::cout << "m_d[" << j << "] = " << this->m_d[j] << std::endl; + std::cout << "x[" << j << "] = " << this->m_x[j] << std::endl; + std::cout << "type = " << column_type_to_string(this->m_column_type[j]) << std::endl; + std::cout << "bounds = " << this->m_low_bound_values[j] << "," << this->m_upper_bound_values[j] << std::endl; + std::cout << "m_total_iterations = " << this->m_total_iterations << std::endl; return false; } } @@ -628,14 +572,14 @@ public: } void set_status_to_tentative_dual_unbounded_or_dual_unbounded() { - cout << "cost = " << this->get_cost() << endl; - if (this->m_status == TENTATIVE_DUAL_UNBOUNDED) { - cout << "setting status to DUAL_UNBOUNDED" << endl; - this->m_status = DUAL_UNBOUNDED; - } else { - cout << "setting to TENTATIVE_DUAL_UNBOUNDED" << endl; - this->m_status = TENTATIVE_DUAL_UNBOUNDED; - } + std::cout << "cost = " << this->get_cost() << std::endl; + if (this->m_status == TENTATIVE_DUAL_UNBOUNDED) { + std::cout << "setting status to DUAL_UNBOUNDED" << std::endl; + this->m_status = DUAL_UNBOUNDED; + } else { + std::cout << "setting to TENTATIVE_DUAL_UNBOUNDED" << std::endl; + this->m_status = TENTATIVE_DUAL_UNBOUNDED; + } } // it is positive if going from low bound to upper bound and negative if going from upper bound to low bound @@ -817,7 +761,7 @@ public: this->m_total_iterations = 0; this->m_iters_with_no_cost_growing = 0; do { - if (this->print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(string(), this->m_total_iterations)){ + if (this->print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(std::string(), this->m_total_iterations)){ this->m_status = lp_status::TIME_EXHAUSTED; return; } diff --git a/src/util/lp/lp_dual_simplex.h b/src/util/lp/lp_dual_simplex.h index 871b2eb28..bdebdbd7e 100644 --- a/src/util/lp/lp_dual_simplex.h +++ b/src/util/lp/lp_dual_simplex.h @@ -4,17 +4,18 @@ Author: Lev Nachmanson */ - #pragma once +#include +#include "util/sstream.h" +#include "util/exception.h" #include "util/lp/lp_solver.h" #include "util/lp/lp_dual_core_solver.h" -#include namespace lean { template class lp_dual_simplex: public lp_solver { lp_dual_core_solver * m_core_solver = nullptr; - vector m_b_copy; + std::vector m_b_copy; std::vector m_low_bounds; // We don't have a convention here that all low bounds are zeros. At least it does not hold for the first stage solver std::vector m_column_types_of_core_solver; std::vector m_column_types_of_logicals; @@ -31,33 +32,28 @@ public: case OPTIMAL: if (this->m_settings.abs_val_is_smaller_than_artificial_tolerance(m_core_solver->get_cost())) { this->m_status = FEASIBLE; - cout << "status is FEASIBLE" << endl; + std::cout << "status is FEASIBLE" << std::endl; } else { - cout << "status is UNBOUNDED" << endl; + std::cout << "status is UNBOUNDED" << std::endl; this->m_status = UNBOUNDED; } break; case DUAL_UNBOUNDED: - cout << "the status cannot be DUAL_UNBOUNDED since the price is not positive!" << endl; - lean_assert(false); - throw "unexpected status DUAL_UNBOUNDED"; - break; + lean_unreachable(); case ITERATIONS_EXHAUSTED: - cout << "status is ITERATIONS_EXHAUSTED" << endl; + std::cout << "status is ITERATIONS_EXHAUSTED" << std::endl; this->m_status = ITERATIONS_EXHAUSTED; break; case TIME_EXHAUSTED: - cout << "status is TIME_EXHAUSTED" << endl; + std::cout << "status is TIME_EXHAUSTED" << std::endl; this->m_status = TIME_EXHAUSTED; break; case FLOATING_POINT_ERROR: - cout << "status is FLOATING_POINT_ERROR" << endl; + std::cout << "status is FLOATING_POINT_ERROR" << std::endl; this->m_status = FLOATING_POINT_ERROR; break; default: - cout << "the status is not expected: " << lp_status_to_string(m_core_solver->get_status()) << endl; - lean_assert(false); - throw "unexpected status"; + lean_unreachable(); } } @@ -75,8 +71,7 @@ public: m_can_enter_basis[j] = false; break; default: - throw 1; - lean_assert(false); + lean_unreachable(); } } @@ -90,9 +85,7 @@ public: break; case fixed: case upper_bound: - lean_assert(false); - throw "unexpected bound type"; - break; + lean_unreachable(); case boxed: this->m_upper_bounds[j] = ci->get_adjusted_upper_bound() / this->m_column_scale[j]; m_low_bounds[j] = numeric_traits::zero(); @@ -104,14 +97,13 @@ public: m_column_types_of_core_solver[j] = free_column; break; default: - lean_assert(false); - throw "unexpected bound type"; + lean_unreachable(); } T cost_was = this->m_costs[j]; this->set_scaled_cost(j); bool in_basis = m_core_solver->m_factorization->m_basis_heading[j] >= 0; if (in_basis && cost_was != this->m_costs[j]) { - cout << "cost change in basis" << endl; + std::cout << "cost change in basis" << std::endl; } } @@ -154,9 +146,7 @@ public: this->m_status = FLOATING_POINT_ERROR; break; default: - cout << "status of core solver is " << lp_status_to_string(m_core_solver->get_status()) << endl; - lean_assert(false); - throw "unexpected status"; + lean_unreachable(); } this->m_second_stage_iterations = m_core_solver->m_total_iterations; } @@ -187,11 +177,11 @@ public: m_core_solver->fill_reduced_costs_from_m_y_by_rows(); m_core_solver->start_with_initial_basis_and_make_it_dual_feasible(); if (this->m_settings.abs_val_is_smaller_than_artificial_tolerance(m_core_solver->get_cost())) { - cout << "skipping stage 1" << endl; + std::cout << "skipping stage 1" << std::endl; m_core_solver->set_status(OPTIMAL); m_core_solver->m_total_iterations = 0; } else { - cout << "stage 1" << endl; + std::cout << "stage 1" << std::endl; m_core_solver->solve(); } decide_on_status_after_stage1(); @@ -199,7 +189,7 @@ public: } void stage2() { - cout << "starting stage2" << endl; + std::cout << "starting stage2" << std::endl; unmark_boxed_and_fixed_columns_and_fix_structural_costs(); restore_right_sides(); solve_for_stage2(); @@ -230,15 +220,12 @@ public: T free_bound = T(1e4); // see 4.8 unsigned jj = this->m_core_solver_columns_to_external_columns[j]; - lean_assert(this->m_columns.find(jj) != this->m_columns.end()); + lean_assert(this->m_columns.find(jj) != this->m_columns.end()); column_info * ci = this->m_columns[jj]; switch (ci->get_column_type()) { case upper_bound: - cout << j << endl; - cout << column_type_to_string(get_column_type(j)) << endl; - cout << "throwing upper_bound case " << endl; - throw "unexpected bound type"; // we flip columns so this case is impossible - break; + throw exception(sstream() << "unexpected bound type " << j << " " + << column_type_to_string(get_column_type(j))); case low_bound: { m_can_enter_basis[j] = true; this->set_scaled_cost(j); @@ -259,9 +246,7 @@ public: this->m_upper_bounds[j] = this->m_low_bounds[j] = numeric_traits::zero(); // is it needed? break; default: - lean_assert(false); - throw "unexpected column type"; - break; + lean_unreachable(); } m_column_types_of_core_solver[j] = boxed; } diff --git a/src/util/lp/lp_primal_core_solver.h b/src/util/lp/lp_primal_core_solver.h index 6968a6518..940a6758b 100644 --- a/src/util/lp/lp_primal_core_solver.h +++ b/src/util/lp/lp_primal_core_solver.h @@ -37,15 +37,15 @@ public: // todo : move public lower ; it is for debug only T m_enter_price_eps; X m_infeasibility = zero_of_type(); int m_sign_of_entering_delta; - vector> m_breakpoints; + std::vector> m_breakpoints; binary_heap_priority_queue m_breakpoint_indices_queue; bool m_using_inf_costs = false; bool m_recalc_reduced_costs = false; std::set m_forbidden_enterings; - vector m_beta; // see Swietanowski working vector beta for column norms + std::vector m_beta; // see Swietanowski working vector beta for column norms T m_epsilon_of_reduced_cost = T(1e-7); bool m_exit_on_feasible_solution = false; - vector m_costs_backup; + std::vector m_costs_backup; bool m_current_x_is_feasible; int choose_entering_column(unsigned number_of_benefitial_columns_to_go_over) { // at this moment m_y = cB * B(-1) @@ -82,9 +82,7 @@ public: // todo : move public lower ; it is for debug only } continue; default: - cout << "unexpected column type " << column_type_to_string(this->m_column_type[j]) << endl; - throw "unexpected column_type"; - break; + lean_unreachable(); } // if we are here then j is a candidate to enter the basis @@ -196,11 +194,11 @@ public: // todo : move public lower ; it is for debug only } while ( i != initial_i); restore_harris_eps(); // if (m_j_uht.size() > 1) { - // cout << "under set " << endl; + // cout << "under set " << std::endl; // for(auto j : m_j_uht) // print_column(j); // // } - // cout << "done with under set" << endl; + // cout << "done with under set" << std::endl; return leaving; // debug // return leaving_fixed != -1 ? leaving_fixed : leaving; } @@ -443,8 +441,7 @@ public: // todo : move public lower ; it is for debug only break; default: - cout << column_type_to_string(this->m_column_type[j]) << endl; - throw "unexpected type"; + lean_unreachable(); } if (theta < zero_of_type()) theta = zero_of_type(); @@ -515,9 +512,9 @@ public: // todo : move public lower ; it is for debug only } - vector m_low_bound_values_dummy; // needed for the base class only + std::vector m_low_bound_values_dummy; // needed for the base class only - X get_max_bound(vector & b) { + X get_max_bound(std::vector & b) { X ret = zero_of_type(); for (auto & v : b) { X a = abs(v); @@ -528,7 +525,7 @@ public: // todo : move public lower ; it is for debug only // stage1 constructor lp_primal_core_solver(static_matrix & A, - vector & b, // the right side vector + std::vector & b, // the right side vector std::vector & x, // the number of elements in x needs to be at least as large as the number of columns in A std::vector & basis, std::vector & costs, @@ -536,7 +533,7 @@ public: // todo : move public lower ; it is for debug only std::vector & low_bound_values, std::vector & upper_bound_values, lp_settings & settings, - unordered_map const & column_names): + std::unordered_map const & column_names): lp_core_solver_base(A, b, basis, x, @@ -553,14 +550,14 @@ public: // todo : move public lower ; it is for debug only // constructor lp_primal_core_solver(static_matrix & A, - vector & b, // the right side vector + std::vector & b, // the right side vector std::vector & x, // the number of elements in x needs to be at least as large as the number of columns in A std::vector & basis, std::vector & costs, std::vector & column_type_array, std::vector & upper_bound_values, lp_settings & settings, - unordered_map const & column_names): + std::unordered_map const & column_names): lp_core_solver_base(A, b, basis, x, @@ -593,19 +590,19 @@ public: // todo : move public lower ; it is for debug only } for (int j = 0; j < this->m_n; j++) { if (column_has_low_bound(j) && this->m_x[j] < numeric_traits::zero()) { - cout << "low bound for variable " << j << " does not hold: this->m_x[" << j << "] = " << this->m_x[j] << " is negative " << endl; + std::cout << "low bound for variable " << j << " does not hold: this->m_x[" << j << "] = " << this->m_x[j] << " is negative " << std::endl; return false; } if (column_has_upper_bound(j) && this->m_x[j] > this->m_upper_bound_values[j]) { - cout << "upper bound for " << j << " does not hold: " << this->m_upper_bound_values[j] << ">" << this->m_x[j] << endl; + std::cout << "upper bound for " << j << " does not hold: " << this->m_upper_bound_values[j] << ">" << this->m_x[j] << std::endl; return false; } if (basis_set.find(j) != basis_set.end()) continue; if (this->m_column_type[j] == low_bound) { if (numeric_traits::zero() != this->m_x[j]) { - cout << "only low bound is set for " << j << " but low bound value " << numeric_traits::zero() << " is not equal to " << this->m_x[j] << endl; + std::cout << "only low bound is set for " << j << " but low bound value " << numeric_traits::zero() << " is not equal to " << this->m_x[j] << std::endl; return false; } } @@ -754,7 +751,7 @@ public: // todo : move public lower ; it is for debug only this->restore_x(entering, t * m_sign_of_entering_delta); m_forbidden_enterings.insert(entering); this->m_iters_with_no_cost_growing++; - cout << "failing in advance_on_entering_and_leaving for entering == leaving = " << leaving << endl; + std::cout << "failing in advance_on_entering_and_leaving for entering == leaving = " << leaving << std::endl; return; } } @@ -827,7 +824,7 @@ public: // todo : move public lower ; it is for debug only if (leaving == -1){ if (get_current_x_is_infeasible()) { if (this->m_status == UNSTABLE) { - cout << "setting status to FLOATING_POINT_ERROR" << endl; + std::cout << "setting status to FLOATING_POINT_ERROR" << std::endl; this->m_status = FLOATING_POINT_ERROR; return; } @@ -861,12 +858,12 @@ public: // todo : move public lower ; it is for debug only } void print_column_norms() { - cout << " column norms " << endl; + std::cout << " column norms " << std::endl; for (unsigned j = 0; j < this->m_n; j++) { - cout << this->m_column_norms[j] << " "; + std::cout << this->m_column_norms[j] << " "; } - cout << endl; - cout << endl; + std::cout << std::endl; + std::cout << std::endl; } void set_current_x_is_feasible() { @@ -987,7 +984,7 @@ public: // todo : move public lower ; it is for debug only T calculate_column_norm_exactly(unsigned j) { indexed_vector w(this->m_m); this->m_A.copy_column_to_vector(j, w); - vector d(this->m_m); + std::vector d(this->m_m); this->m_factorization->solve_Bd_when_w_is_ready(d, w); T ret = zero_of_type(); for (auto v : d) @@ -1277,11 +1274,11 @@ public: // todo : move public lower ; it is for debug only return true; } if (this->m_iters_with_no_cost_growing >= this->m_settings.max_number_of_iterations_with_no_improvements) { - cout << "m_iters_with_no_cost_growing = " << this->m_iters_with_no_cost_growing << endl; + std::cout << "m_iters_with_no_cost_growing = " << this->m_iters_with_no_cost_growing << std::endl; this->m_status = ITERATIONS_EXHAUSTED; return true; } if (this->m_total_iterations >= this->m_settings.max_total_number_of_iterations) { - cout << "max_total_number_of_iterations " << this->m_total_iterations << " is reached " << endl; + std::cout << "max_total_number_of_iterations " << this->m_total_iterations << " is reached " << std::endl; this->m_status = ITERATIONS_EXHAUSTED; return true; } return false; @@ -1301,22 +1298,22 @@ public: // todo : move public lower ; it is for debug only } void print_column(unsigned j) { - cout << this->column_name(j) << " " << j << " " << column_type_to_string(this->m_column_type[j]) << " x = " << this->m_x[j] << " " << "c = " << this->m_costs[j];; + std::cout << this->column_name(j) << " " << j << " " << column_type_to_string(this->m_column_type[j]) << " x = " << this->m_x[j] << " " << "c = " << this->m_costs[j];; switch (this->m_column_type[j]) { case fixed: case boxed: - cout << "( " << this->m_low_bound_values[j] << " " << this->m_x[j] << " " << this->m_upper_bound_values[j] << ")" << endl; + std::cout << "( " << this->m_low_bound_values[j] << " " << this->m_x[j] << " " << this->m_upper_bound_values[j] << ")" << std::endl; break; case upper_bound: - cout << "( _" << this->m_x[j] << " " << this->m_upper_bound_values[j] << ")" << endl; + std::cout << "( _" << this->m_x[j] << " " << this->m_upper_bound_values[j] << ")" << std::endl; break; case low_bound: - cout << "( " << this->m_low_bound_values[j] << " " << this->m_x[j] << " " << "_ )" << endl; + std::cout << "( " << this->m_low_bound_values[j] << " " << this->m_x[j] << " " << "_ )" << std::endl; break; case free_column: - cout << "( _" << this->m_x[j] << "_)" << endl; + std::cout << "( _" << this->m_x[j] << "_)" << std::endl; default: - throw "unexpected type"; + lean_unreachable(); } } diff --git a/src/util/lp/lp_primal_simplex.h b/src/util/lp/lp_primal_simplex.h index 2ca60cc6d..1a5071cdb 100644 --- a/src/util/lp/lp_primal_simplex.h +++ b/src/util/lp/lp_primal_simplex.h @@ -4,24 +4,22 @@ Author: Lev Nachmanson */ - #pragma once -#include "util/lp/lp_primal_core_solver.h" -#include "util/lp/lp_solver.h" #include #include #include #include +#include "util/exception.h" +#include "util/sstream.h" #include "util/lp/column_info.h" +#include "util/lp/lp_primal_core_solver.h" +#include "util/lp/lp_solver.h" namespace lean { -using std::vector; -using std::tuple; - template class lp_primal_simplex: public lp_solver { lp_primal_core_solver * m_core_solver = nullptr; - vector m_low_bounds; + std::vector m_low_bounds; private: unsigned original_rows() { return this->m_external_rows_to_core_solver_rows.size(); } @@ -34,7 +32,7 @@ private: } } - void init_buffer(unsigned k, vector & r) { + void init_buffer(unsigned k, std::vector & r) { for (unsigned i = 0; i < k; i++) { r[i] = 0; } @@ -47,8 +45,7 @@ private: void refactor() { m_core_solver->init_lu(); if (m_core_solver->factorization()->get_status() != LU_status::OK) { - cout << "cannot refactor \n"; - throw "cannot refactor"; + throw exception("cannot refactor"); } } @@ -60,7 +57,7 @@ private: } void stage_two() { - cout << "starting stage 2" << endl; + std::cout << "starting stage 2" << std::endl; lean_assert(!m_core_solver->A_mult_x_is_off()); int j = this->m_A->column_count() - 1; unsigned core_solver_cols = this->number_of_core_structurals(); @@ -73,7 +70,7 @@ private: m_core_solver->set_status(lp_status::FEASIBLE); this->m_second_stage_iterations = m_core_solver->solve(); this->m_status = m_core_solver->get_status(); - // cout << "status is " << lp_status_to_string(this->m_status) << endl; + // std::cout << "status is " << lp_status_to_string(this->m_status) << std::endl; } public: lp_primal_simplex() {} @@ -175,11 +172,11 @@ public: - string name_of_core_solver_column(unsigned j) { // j here is the core solver index + std::string name_of_core_solver_column(unsigned j) { // j here is the core solver index unsigned external_j = this->m_core_solver_columns_to_external_columns[j]; auto t = this->m_columns.find(external_j); if (t == this->m_columns.end()) { - return string("name_not_found"); + return std::string("name_not_found"); } return t->m_name; } @@ -274,7 +271,7 @@ public: } void solve_with_total_inf() { - cout << "starting solve_with_total_inf()" << endl; + std::cout << "starting solve_with_total_inf()" << std::endl; int total_vars = this->m_A->column_count() + this->row_count(); m_low_bounds.clear(); m_low_bounds.resize(total_vars, zero_of_type()); // low bounds are shifted ot zero @@ -308,7 +305,7 @@ public: // void stage_one_of_total_inf() { - // cout << "starting stage_one_of_total_inf()" << endl; + // std::cout << "starting stage_one_of_total_inf()" << std::endl; // int total_vars = this->m_A->column_count() + this->row_count(); // m_low_bounds.clear(); // m_low_bounds.resize(total_vars, zero_of_type()); // low bounds are shifted ot zero @@ -339,16 +336,16 @@ public: } } - bool bounds_hold(unordered_map const & solution) { + bool bounds_hold(std::unordered_map const & solution) { for (auto it : this->m_columns) { auto sol_it = solution.find(it.second->get_name()); if (sol_it == solution.end()) { - cout << "cannot find column " << it.first << " in solution " << endl; + std::cout << "cannot find column " << it.first << " in solution " << std::endl; throw; } if (!it.second->bounds_hold(sol_it->second)) { - cout << "bounds do not hold for " << it.second->get_name() << endl; + std::cout << "bounds do not hold for " << it.second->get_name() << std::endl; it.second->bounds_hold(sol_it->second); return false; } @@ -356,37 +353,37 @@ public: return true; } - T get_row_value(unsigned i, unordered_map const & solution, bool print) { + T get_row_value(unsigned i, std::unordered_map const & solution, bool print) { auto it = this->m_A_values.find(i); if (it == this->m_A_values.end()) { - cout << "cannot find row " << i << endl; + std::cout << "cannot find row " << i << std::endl; throw "get_row_value"; } T ret = numeric_traits::zero(); for (auto & pair : it->second) { auto cit = this->m_columns.find(pair.first); if (cit == this->m_columns.end()){ - cout << "cannot find column " << pair.first << endl; + std::cout << "cannot find column " << pair.first << std::endl; } column_info * ci = cit->second; auto sol_it = solution.find(ci->get_name()); if (sol_it == solution.end()) { - cout << "cannot find in the solution column " << ci->get_name() << endl; + std::cout << "cannot find in the solution column " << ci->get_name() << std::endl; } T column_val = sol_it->second; if (print) { - cout << pair.second << "(" << ci->get_name() << "=" << column_val << ") "; + std::cout << pair.second << "(" << ci->get_name() << "=" << column_val << ") "; } ret += pair.second * column_val; } if (print) { - cout << " = " << ret << endl; + std::cout << " = " << ret << std::endl; } return ret; } - bool row_constraint_holds(unsigned i, unordered_map const & solution, bool print) { + bool row_constraint_holds(unsigned i, std::unordered_map const & solution, bool print) { T row_val = get_row_value(i, solution, print); auto & constraint = this->m_constraints[i]; T rs = constraint.m_rs; @@ -394,7 +391,7 @@ public: case Equal: if (fabs(numeric_traits::get_double(row_val - rs)) > 0.00001) { if (print) { - cout << "should be = " << rs << endl; + std::cout << "should be = " << rs << std::endl; } return false; } @@ -402,7 +399,7 @@ public: case Greater_or_equal: if (numeric_traits::get_double(row_val - rs) < -0.00001) { if (print) { - cout << "should be >= " << rs << endl; + std::cout << "should be >= " << rs << std::endl; } return false; } @@ -411,17 +408,17 @@ public: case Less_or_equal: if (numeric_traits::get_double(row_val - rs) > 0.00001) { if (print) { - cout << "should be <= " << rs << endl; + std::cout << "should be <= " << rs << std::endl; } return false; } return true;; } - cout << "throw in row_constraint_holds " << endl; + std::cout << "throw in row_constraint_holds " << std::endl; throw "wrong case"; } - bool row_constraints_hold(unordered_map const & solution) { + bool row_constraints_hold(std::unordered_map const & solution) { for (auto it : this->m_A_values) { if (!row_constraint_holds(it.first, solution, false)) { row_constraint_holds(it.first, solution, true); @@ -432,21 +429,19 @@ public: } - T * get_array_from_map(unordered_map const & solution) { + T * get_array_from_map(std::unordered_map const & solution) { T * t = new T[solution.size()]; for (auto it : solution) { auto g = this->m_names_to_columns.find(it.first); if (g == this->m_names_to_columns.end()) { - string s = string("cannot find name ") + " "+ it.first; - cout << "throw in get_array_from_map" << endl; - throw s; + throw exception(sstream() << "cannot find name " << it.first); } t[g->second] = it.second; } return t; } - bool solution_is_feasible(unordered_map const & solution) { + bool solution_is_feasible(std::unordered_map const & solution) { return bounds_hold(solution) && row_constraints_hold(solution); } diff --git a/src/util/lp/lp_solver.h b/src/util/lp/lp_solver.h index 831aa6024..9bb4ac04f 100644 --- a/src/util/lp/lp_solver.h +++ b/src/util/lp/lp_solver.h @@ -23,8 +23,6 @@ enum lp_relation { Greater_or_equal }; - - template struct lp_constraint { X m_rs; // right side of the constraint @@ -50,26 +48,26 @@ protected: public: unsigned m_total_iterations; static_matrix* m_A = nullptr; // this is the matrix of constraints - vector m_b; // the right side vector + std::vector m_b; // the right side vector unsigned m_first_stage_iterations = 0; unsigned m_second_stage_iterations = 0; - unordered_map> m_constraints; - unordered_map*> m_columns; - unordered_map > m_A_values; - unordered_map m_names_to_columns; // don't have to use it - unordered_map m_external_rows_to_core_solver_rows; - unordered_map m_core_solver_rows_to_external_rows; - unordered_map m_external_columns_to_core_solver_columns; - unordered_map m_core_solver_columns_to_external_columns; - vector m_column_scale; - unordered_map m_name_map; + std::unordered_map> m_constraints; + std::unordered_map*> m_columns; + std::unordered_map > m_A_values; + std::unordered_map m_names_to_columns; // don't have to use it + std::unordered_map m_external_rows_to_core_solver_rows; + std::unordered_map m_core_solver_rows_to_external_rows; + std::unordered_map m_external_columns_to_core_solver_columns; + std::unordered_map m_core_solver_columns_to_external_columns; + std::vector m_column_scale; + std::unordered_map m_name_map; unsigned m_artificials = 0; unsigned m_slacks = 0; - vector m_column_types; - vector m_costs; - vector m_x; - vector m_upper_bounds; - vector m_basis; + std::vector m_column_types; + std::vector m_costs; + std::vector m_x; + std::vector m_upper_bounds; + std::vector m_basis; lp_status m_status = lp_status::UNKNOWN; @@ -94,7 +92,7 @@ public: // returns the current cost virtual T get_current_cost() const = 0; // do not have to call it - void give_symbolic_name_to_column(string name, unsigned column) { + void give_symbolic_name_to_column(std::string name, unsigned column) { auto it = m_columns.find(column); column_info *ci; if (it == m_columns.end()){ @@ -111,7 +109,7 @@ public: T get_column_value_by_name(std::string name) const { auto it = m_names_to_columns.find(name); if (it == m_names_to_columns.end()) { - cout << "throwing in get_column_value_by_name" << endl; + std::cout << "throwing in get_column_value_by_name" << std::endl; throw "get_column_value_by_name"; } return get_column_value(it -> second); @@ -211,29 +209,29 @@ protected: void print_rows_scale_stats() { - cout << "rows max" << endl; - for (unsigned i = 0; i < m_A->row_count(); i++) { + std::cout << "rows max" << std::endl; + for (unsigned i = 0; i < m_A->row_count(); i++) { print_row_scale_stats(i); } - cout << endl; + std::cout << std::endl; } void print_columns_scale_stats() { - cout << "columns max" << endl; + std::cout << "columns max" << std::endl; for (unsigned i = 0; i < m_A->column_count(); i++) { print_column_scale_stats(i); } - cout << endl; + std::cout << std::endl; } void print_row_scale_stats(unsigned i) { - cout << "(" << std::min(m_A->get_min_abs_in_row(i), abs(m_b[i])) << " "; - cout << std::max(m_A->get_max_abs_in_row(i), abs(m_b[i])) << ")"; + std::cout << "(" << std::min(m_A->get_min_abs_in_row(i), abs(m_b[i])) << " "; + std::cout << std::max(m_A->get_max_abs_in_row(i), abs(m_b[i])) << ")"; } void print_column_scale_stats(unsigned j) { - cout << "(" << m_A->get_min_abs_in_row(j) << " "; - cout << m_A->get_max_abs_in_column(j) << ")"; + std::cout << "(" << m_A->get_min_abs_in_row(j) << " "; + std::cout << m_A->get_max_abs_in_column(j) << ")"; } void print_scale_stats() { @@ -241,7 +239,7 @@ protected: print_columns_scale_stats(); } - void get_max_abs_in_row(unordered_map & row_map) { + void get_max_abs_in_row(std::unordered_map & row_map) { T ret = numeric_traits::zero(); for (auto jp : row_map) { T ac = numeric_traits::abs(jp->second); @@ -252,16 +250,16 @@ protected: return ret; } - void pin_vars_down_on_row(unordered_map & row) { + void pin_vars_down_on_row(std::unordered_map & row) { pin_vars_on_row_with_sign(row, - numeric_traits::one()); } - void pin_vars_up_on_row(unordered_map & row) { + void pin_vars_up_on_row(std::unordered_map & row) { pin_vars_on_row_with_sign(row, numeric_traits::one()); } - void pin_vars_on_row_with_sign(unordered_map & row, T sign ) { - unordered_map pinned; + void pin_vars_on_row_with_sign(std::unordered_map & row, T sign ) { + std::unordered_map pinned; for (auto t : row) { unsigned j = t.first; column_info * ci = m_columns[j]; @@ -276,7 +274,7 @@ protected: } } - bool get_minimal_row_value(unordered_map & row, T & low_bound) { + bool get_minimal_row_value(std::unordered_map & row, T & low_bound) { low_bound = numeric_traits::zero(); for (auto & t : row) { T a = t.second; @@ -298,7 +296,7 @@ protected: return true; } - bool get_maximal_row_value(unordered_map & row, T & low_bound) { + bool get_maximal_row_value(std::unordered_map & row, T & low_bound) { low_bound = numeric_traits::zero(); for (auto & t : row) { T a = t.second; @@ -320,7 +318,7 @@ protected: return true; } - bool row_is_zero(unordered_map & row) { + bool row_is_zero(std::unordered_map & row) { for (auto & t : row) { if (!is_zero(t.second)) return false; @@ -328,7 +326,7 @@ protected: return true; } - bool row_e_is_obsolete(unordered_map & row, unsigned row_index) { + bool row_e_is_obsolete(std::unordered_map & row, unsigned row_index) { T rs = m_constraints[row_index].m_rs; if (row_is_zero(row)) { if (!is_zero(rs)) @@ -369,7 +367,7 @@ protected: return false; } - int row_ge_is_obsolete(unordered_map & row, unsigned row_index) { + int row_ge_is_obsolete(std::unordered_map & row, unsigned row_index) { T rs = m_constraints[row_index].m_rs; if (row_is_zero(row)) { if (rs > zero_of_type()) @@ -394,7 +392,7 @@ protected: return false; } - bool row_le_is_obsolete(unordered_map & row, unsigned row_index) { + bool row_le_is_obsolete(std::unordered_map & row, unsigned row_index) { T low_bound; T rs = m_constraints[row_index].m_rs; if (row_is_zero(row)) { @@ -425,7 +423,7 @@ protected: // the low boundary of the var and for a negative - the upper. // this routing also pins the variables to the boundaries - bool row_is_obsolete(unordered_map & row, unsigned row_index ) { + bool row_is_obsolete(std::unordered_map & row, unsigned row_index ) { auto & constraint = m_constraints[row_index]; switch (constraint.m_relation) { case lp_relation::Equal: @@ -448,9 +446,9 @@ protected: } } - void remove_fixed_or_zero_columns_from_row(unsigned i, unordered_map & row) { + void remove_fixed_or_zero_columns_from_row(unsigned i, std::unordered_map & row) { auto & constraint = m_constraints[i]; - vector removed; + std::vector removed; for (auto & col : row) { unsigned j = col.first; lean_assert(m_columns.find(j) != m_columns.end()); @@ -472,7 +470,7 @@ protected: } unsigned try_to_remove_some_rows() { - vector rows_to_delete; + std::vector rows_to_delete; for (auto & t : m_A_values) { if (row_is_obsolete(t.second, t.first)) { rows_to_delete.push_back(t.first); @@ -498,9 +496,9 @@ protected: n += d; if (n == 1) - cout << "deleted one row" << endl; + std::cout << "deleted one row" << std::endl; else if (n) - cout << "deleted " << n << " rows" << endl; + std::cout << "deleted " << n << " rows" << std::endl; } void map_external_rows_to_core_solver_rows() { @@ -517,7 +515,7 @@ protected: for (auto & row : m_A_values) { for (auto & col : row.second) { if (col.second == numeric_traits::zero() || m_columns[col.first]->is_fixed()) { - cout << "found fixed column " << endl; + std::cout << "found fixed column " << std::endl; throw "map_external_columns_to_core_solver_columns"; } unsigned j = col.first; @@ -675,10 +673,10 @@ protected: this->m_costs[j] = cost * this->m_column_scale[j]; } void print_statistics_on_A() { - cout << "extended A[" << this->m_A->row_count() << "," << this->m_A->column_count() << "]" << endl; + std::cout << "extended A[" << this->m_A->row_count() << "," << this->m_A->column_count() << "]" << std::endl; // for (unsigned i = 0; i < this->m_A->row_count(); i++) { // if (this->m_A->number_of_non_zeroes_in_row(i) <= 2 ) { - // cout << "m_p[" << i << "] = " << this->m_A->number_of_non_zeroes_in_row(i) << endl; + // std::cout << "m_p[" << i << "] = " << this->m_A->number_of_non_zeroes_in_row(i) << std::endl; // } // } } diff --git a/src/util/lp/lu.h b/src/util/lp/lu.h index 50c22a4bc..7948617b2 100644 --- a/src/util/lp/lu.h +++ b/src/util/lp/lu.h @@ -27,10 +27,10 @@ std::string T_to_string(const T & t); // forward definition #ifdef LEAN_DEBUG template // print the nr x nc submatrix at the top left corner void print_submatrix(sparse_matrix & m, unsigned mr, unsigned nc) { - vector> A; - vector widths; + std::vector> A; + std::vector widths; for (unsigned i = 0; i < m.row_count() && i < mr ; i++) { - A.push_back(vector()); + A.push_back(std::vector()); for (unsigned j = 0; j < m.column_count() && j < nc; j++) { A[i].push_back(T_to_string(static_cast(m(i, j)))); } @@ -45,11 +45,11 @@ void print_submatrix(sparse_matrix & m, unsigned mr, unsigned nc) { template void print_matrix(static_matrix &m) { - vector> A; - vector widths; + std::vector> A; + std::vector widths; std::set> domain = m.get_domain(); for (unsigned i = 0; i < m.row_count(); i++) { - A.push_back(vector()); + A.push_back(std::vector()); for (unsigned j = 0; j < m.column_count(); j++) { A[i].push_back(T_to_string(static_cast(m(i, j)))); } @@ -64,10 +64,10 @@ void print_matrix(static_matrix &m) { template void print_matrix(sparse_matrix& m) { - vector> A; - vector widths; + std::vector> A; + std::vector widths; for (unsigned i = 0; i < m.row_count(); i++) { - A.push_back(vector()); + A.push_back(std::vector()); for (unsigned j = 0; j < m.column_count(); j++) { A[i].push_back(T_to_string(static_cast(m(i, j)))); } @@ -135,11 +135,11 @@ public: unsigned row_count() const { return m_m; } // not defined } unsigned column_count() const { return m_m; } // not defined } #endif - void apply_from_left(vector & w, lp_settings &) { + void apply_from_left(std::vector & w, lp_settings &) { w[m_i] /= m_val; } - void apply_from_right(vector & w) { + void apply_from_right(std::vector & w) { w[m_i] /= m_val; } @@ -177,7 +177,7 @@ public: // the fields unsigned m_dim; static_matrix const &m_A; - vector& m_basis; + std::vector& m_basis; permutation_matrix m_Q; permutation_matrix m_R; sparse_matrix m_U; @@ -185,20 +185,20 @@ public: // m_tail is composed of tail_matrices: // one_off_diagonal_matrix, and transposition_matrix - vector *> m_tail; + std::vector *> m_tail; lp_settings & m_settings; - vector & m_basis_heading; + std::vector & m_basis_heading; bool m_failure = false; - vector & m_non_basic_columns; + std::vector & m_non_basic_columns; indexed_vector m_row_eta_work_vector; // constructor // if A is an m by n matrix then basis has length m and values in [0,n); the values are all different // they represent the set of m columns lu(static_matrix const & A, - vector& basis, - vector & basis_heading, + std::vector& basis, + std::vector & basis_heading, lp_settings & settings, - vector & non_basic_columns): + std::vector & non_basic_columns): m_dim(A.row_count()), m_A(A), m_basis(basis), @@ -215,9 +215,9 @@ public: create_initial_factorization(); if (get_status() != LU_status::OK) { if (get_status() == LU_status::Degenerated) { - cout << "lu status is Degenerated" << endl; + std::cout << "lu status is Degenerated" << std::endl; } else { - cout << "lu status is " <(get_status()) << endl; + std::cout << "lu status is " <(get_status()) << std::endl; } return; } @@ -240,7 +240,7 @@ public: return - m_basis_heading[j] - 1; } - void solve_By(vector & y) { + void solve_By(std::vector & y) { init_vector_y(y); solve_By_when_y_is_ready(y); } @@ -253,7 +253,7 @@ public: } template - void solve_By_when_y_is_ready(vector & y) { + void solve_By_when_y_is_ready(std::vector & y) { m_U.double_solve_U_y(y); m_R.apply_reverse_from_left(y); // see 24.3 from Chvatal if (precise()) return; @@ -268,42 +268,42 @@ public: void print_indexed_vector(indexed_vector & w, std::ofstream & f) { - f << "vector_start" << endl; + f << "vector_start" << std::endl; for (unsigned j : w.m_index) { - f << j << " " << w[j] << endl; + f << j << " " << w[j] << std::endl; } - f << "vector_end" << endl; + f << "vector_end" << std::endl; } void print_basis(std::ofstream & f) { - f << "basis_start" << endl; + f << "basis_start" << std::endl; for (unsigned j : m_basis) - f << j << endl; - f << "basis_end" << endl; + f << j << std::endl; + f << "basis_end" << std::endl; } void print_matrix_compact(std::ofstream & f) { - f << "matrix_start" << endl; - f << "nrows " << m_A.row_count() << endl; - f << "ncolumns " << m_A.column_count() << endl; + f << "matrix_start" << std::endl; + f << "nrows " << m_A.row_count() << std::endl; + f << "ncolumns " << m_A.column_count() << std::endl; for (unsigned i = 0; i < m_A.row_count(); i++) { auto & row = m_A.m_rows[i]; - f << "row " << i << endl; + f << "row " << i << std::endl; for (auto & t : row.m_cells) { - f << "column " << t.m_j << " value " << t.m_value << endl; + f << "column " << t.m_j << " value " << t.m_value << std::endl; } - f << "row_end" << endl; + f << "row_end" << std::endl; } - f << "matrix_end" << endl; + f << "matrix_end" << std::endl; } void print(indexed_vector & w) { - string dump_file_name("/tmp/lu"); + std::string dump_file_name("/tmp/lu"); remove(dump_file_name.c_str()); std::ofstream f(dump_file_name); if (!f.is_open()) { - cout << "cannot open file " << dump_file_name << endl; + std::cout << "cannot open file " << dump_file_name << std::endl; return; } - cout << "writing lu dump to " << dump_file_name << endl; + std::cout << "writing lu dump to " << dump_file_name << std::endl; print_matrix_compact(f); print_basis(f); print_indexed_vector(w, f); @@ -319,7 +319,7 @@ public: return m_basis_heading[i] < 0; } - void solve_yB_internal(vector& y) { + void solve_yB_internal(std::vector& y) { // first solve yU = cb*R(-1) m_R.apply_reverse_from_right(y); // got y = cb*R(-1) m_U.solve_y_U(y); // got y*U=cb*R(-1) @@ -332,13 +332,13 @@ public: } } - void add_delta_to_solution(vector& yc, vector& y){ + void add_delta_to_solution(std::vector& yc, std::vector& y){ unsigned i = y.size(); while (i--) y[i]+=yc[i]; } - void find_error_of_yB(vector& yc, const vector& y) { + void find_error_of_yB(std::vector& yc, const std::vector& y) { unsigned i = m_dim; while (i--) { yc[i] -= m_A.dot_product_with_column(y, m_basis[i]); @@ -348,8 +348,8 @@ public: // solves y*B = y // y is the input - void solve_yB(vector & y) { - vector yc(y); // copy y aside + void solve_yB(std::vector & y) { + std::vector yc(y); // copy y aside solve_yB_internal(y); find_error_of_yB(yc, y); solve_yB_internal(yc); @@ -400,7 +400,7 @@ public: return m_A(i, m_basis[j]); } - void init_vector_y(vector & y) { + void init_vector_y(std::vector & y) { apply_lp_lists_to_y(y); m_Q.apply_reverse_from_left(y); } @@ -426,7 +426,7 @@ public: } } - void apply_lp_lists_to_y(vector& y) { + void apply_lp_lists_to_y(std::vector& y) { for (unsigned i = 0; i < m_tail.size(); i++) { m_tail[i]->apply_from_left(y, m_settings); } @@ -559,14 +559,14 @@ public: unsigned pi, pj; m_U.get_pivot_for_column(pi, pj, T(m_settings.c_partial_pivoting), j); if (pi == -1) { - cout << "cannot find the pivot for column " << j << endl; + std::cout << "cannot find the pivot for column " << j << std::endl; m_failure = true; return; } swap_columns(j, pj); swap_rows(j, pi); if (!pivot_the_row(j)) { - cout << "pivot_the_row(" << j << ") failed" << endl; + std::cout << "pivot_the_row(" << j << ") failed" << std::endl; m_failure = true; } } @@ -681,7 +681,7 @@ public: return; } j++; - // cout << "switching to dense factoring for " << j << endl; + // std::cout << "switching to dense factoring for " << j << endl; m_dense_LU = new square_dense_submatrix(&m_U, j); for (; j < m_dim; j++) { pivot_in_dense_mode(j); @@ -715,7 +715,7 @@ public: } void scan_last_row_to_work_vector(unsigned lowest_row_of_the_bump) { - vector> & last_row_vec = m_U.get_row_values(m_U.adjust_row(lowest_row_of_the_bump)); + std::vector> & last_row_vec = m_U.get_row_values(m_U.adjust_row(lowest_row_of_the_bump)); for (auto & iv : last_row_vec) { if (is_zero(iv.m_value)) continue; lean_assert(!m_settings.abs_val_is_smaller_than_drop_tolerance(iv.m_value)); @@ -739,7 +739,7 @@ public: T v = m_row_eta_work_vector[j]; if (numeric_traits::is_zero(v)) continue; // this column does not contribute to the solution unsigned aj = m_U.adjust_row(j); - vector> & row = m_U.get_row_values(aj); + std::vector> & row = m_U.get_row_values(aj); for (auto & iv : row) { unsigned col = m_U.adjust_column_inverse(iv.m_index); lean_assert(col >= j || numeric_traits::is_zero(iv.m_value)); @@ -780,9 +780,9 @@ public: !is_zero(pivot_elem_for_checking) && #endif !m_settings.abs_val_is_smaller_than_pivot_tolerance((m_row_eta_work_vector[lowest_row_of_the_bump] - pivot_elem_for_checking) / denom)) { - // cout << "m_row_eta_work_vector[" << lowest_row_of_the_bump << "] = " << T_to_string(m_row_eta_work_vector[lowest_row_of_the_bump]) << ", but pivot = " << T_to_string(pivot_elem_for_checking) << endl; + // std::cout << "m_row_eta_work_vector[" << lowest_row_of_the_bump << "] = " << T_to_string(m_row_eta_work_vector[lowest_row_of_the_bump]) << ", but pivot = " << T_to_string(pivot_elem_for_checking) << endl; set_status(LU_status::Degenerated); - // cout << "diagonal element is off" << endl; + // std::cout << "diagonal element is off" << endl; return nullptr; } #ifdef LEAN_DEBUG @@ -861,13 +861,13 @@ public: } }; // end of lu template -void init_factorization(lu* & factorization, static_matrix & m_A, std::vector & m_basis, vector & m_basis_heading, lp_settings &m_settings, vector & non_basic_columns) { +void init_factorization(lu* & factorization, static_matrix & m_A, std::vector & m_basis, std::vector & m_basis_heading, lp_settings &m_settings, std::vector & non_basic_columns) { if (factorization != nullptr) { delete factorization; } factorization = new lu(m_A, m_basis, m_basis_heading, m_settings, non_basic_columns); if (factorization->get_status() != LU_status::OK) { - cout << "failing in init_factorization" << endl; + std::cout << "failing in init_factorization" << std::endl; return; } } diff --git a/src/util/lp/matrix_domain.h b/src/util/lp/matrix_domain.h index 5f04041e4..f3767a616 100644 --- a/src/util/lp/matrix_domain.h +++ b/src/util/lp/matrix_domain.h @@ -36,15 +36,13 @@ template struct hash> { } namespace lean { -using std::unordered_map; - template class matrix_domain { - vector> m_domain; + std::vector> m_domain; public: matrix_domain(unsigned rows) { while (rows--) { - unordered_map t; + std::unordered_map t; m_domain.push_back(t); } } diff --git a/src/util/lp/permutation_matrix.h b/src/util/lp/permutation_matrix.h index 579ad4c54..43115f28b 100644 --- a/src/util/lp/permutation_matrix.h +++ b/src/util/lp/permutation_matrix.h @@ -4,7 +4,6 @@ Author: Lev Nachmanson */ - #pragma once #include #include "util/debug.h" @@ -22,253 +21,250 @@ #include "util/lp/lp_settings.h" #include namespace lean { - using std::string; - using std::endl; +template +std::string T_to_string(const T & t) { + // return is_zero(t)?string(" "):string("."); + std::ostringstream strs; + strs << t; + std::string str = strs.str(); + return str; +} - template - string T_to_string(const T & t) { - // return is_zero(t)?string(" "):string("."); - std::ostringstream strs; - strs << t; - std::string str = strs.str(); - return str; - } - - template <> - string T_to_string(const int & t) { - std::ostringstream strs; - strs << t; - std::string str = strs.str(); - return str; - } - template <> - string T_to_string(const unsigned & t) { - std::ostringstream strs; - strs << t; - std::string str = strs.str(); - return str; +template <> +std::string T_to_string(const int & t) { + std::ostringstream strs; + strs << t; + std::string str = strs.str(); + return str; +} +template <> +std::string T_to_string(const unsigned & t) { + std::ostringstream strs; + strs << t; + std::string str = strs.str(); + return str; +} + + +std::string T_to_string(const mpq & t) { + std::ostringstream strs; + strs << t.get_double(); + std::string str = strs.str(); + return str; +} + +template +bool val_is_smaller_than_eps(T const & t, double const & eps) { + if (!numeric_traits::precise()) { + return numeric_traits::get_double(t) < eps; } + return t <= numeric_traits::zero(); +} - string T_to_string(const mpq & t) { - std::ostringstream strs; - strs << t.get_double(); - std::string str = strs.str(); - return str; - } +inline bool is_even(int k) { + return (k/2)*2 == k; +} - template - bool val_is_smaller_than_eps(T const & t, double const & eps) { - if (!numeric_traits::precise()) { - return numeric_traits::get_double(t) < eps; - } - return t <= numeric_traits::zero(); - } - - - inline bool is_even(int k) { - return (k/2)*2 == k; - } - - template - bool vectors_are_equal(T * a, T *b, unsigned n) { - double sum = 0; - double max = 0; - if (numeric_traits::precise()) { - for (unsigned i = 0; i < n; i ++){ - if (!numeric_traits::is_zero(a[i] - b[i])) { - std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; - return false; - } - } - } else { - for (unsigned i = 0; i < n; i ++){ - double t = fabs(numeric_traits::get_double(a[i] - b[i])); - if (t > 0.000001) { - std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; - return false; - } - if (t > max) { - max = t; - } - sum += t; - } - } - if (sum > 0.00001) { - return false; - } - // cout << "vectors_are_equal :" << "sum = " << sum << ", max = " << max << endl; - return true; - } - - template - bool vectors_are_equal(T * a, std::vector &b, unsigned n) { - if (numeric_traits::precise()) { - for (unsigned i = 0; i < n; i ++){ - if (!numeric_traits::is_zero(a[i] - b[i])) { - std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; - return false; - } - } - } else { - for (unsigned i = 0; i < n; i ++){ - if (fabs(numeric_traits::get_double(a[i] - b[i])) > 0.000001) { - std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; - return false; - } - } - } - return true; - } - - template - bool vectors_are_equal(const std::vector & a, const buffer &b) { - unsigned n = a.size(); - if (n != b.size()) return false; - if (numeric_traits::precise()) { - for (unsigned i = 0; i < n; i ++){ - if (!numeric_traits::is_zero(a[i] - b[i])) { - std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; - return false; - } - } - } else { - for (unsigned i = 0; i < n; i ++){ - if (fabs(numeric_traits::get_double(a[i] - b[i])) > 0.000001) { - std::cout << "a[" << i <<"] = " << a[i] << ", but " << "b[" << i <<"] = " << b[i] << std::endl; - return false; - } - } - } - return true; - } - template - bool vectors_are_equal(const std::vector & a, const std::vector &b) { - unsigned n = a.size(); - if (n != b.size()) return false; - if (numeric_traits::precise()) { - for (unsigned i = 0; i < n; i ++){ - if (!numeric_traits::is_zero(a[i] - b[i])) { - std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; - return false; - } - } - } else { - for (unsigned i = 0; i < n; i ++){ - if (fabs(numeric_traits::get_double(a[i] - b[i])) > 0.000001) { - std::cout << "a[" << i <<"] = " << a[i] << ", but " << "b[" << i <<"] = " << b[i] << std::endl; - return false; - } - } - } - return true; - } - - 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; - } - - template - X min_abs_in_vector(vector& t){ - X r(zero_of_type()); - for (auto & v : t) { - if (is_zero(v)) continue; - if (is_zero(r)) { - r = abs(v); - } else { - r = std::min(abs(v) , r); - } - } - return r; - } - -#ifdef LEAN_DEBUG - // used for debugging purposes only - template - class matrix { - public: - virtual T get_elem (unsigned i, unsigned j) const = 0; - virtual unsigned row_count() const = 0; - virtual unsigned column_count() const = 0; - virtual void set_number_of_rows(unsigned m) = 0; - virtual void set_number_of_columns(unsigned n) = 0; - - virtual ~matrix() {} - - bool is_equal(const matrix& other) { - if (other.row_count() != row_count() || other.column_count() != column_count()) +template +bool vectors_are_equal(T * a, T *b, unsigned n) { + double sum = 0; + double max = 0; + if (numeric_traits::precise()) { + for (unsigned i = 0; i < n; i ++){ + if (!numeric_traits::is_zero(a[i] - b[i])) { + std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; return false; - lp_settings settings; - for (unsigned i = 0; i < row_count(); i++) { - for (unsigned j = 0; j < column_count(); j++) { - auto a = get_elem(i, j); - auto b = other.get_elem(i, j); - if (numeric_traits::precise()) { - if (a != b) return false; - } else if (fabs(numeric_traits::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; - } + } + } + } else { + for (unsigned i = 0; i < n; i ++){ + double t = fabs(numeric_traits::get_double(a[i] - b[i])); + if (t > 0.000001) { + std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; + return false; + } + if (t > max) { + max = t; + } + sum += t; + } + } + if (sum > 0.00001) { + return false; + } + // cout << "vectors_are_equal :" << "sum = " << sum << ", max = " << max << endl; + return true; +} + +template +bool vectors_are_equal(T * a, std::vector &b, unsigned n) { + if (numeric_traits::precise()) { + for (unsigned i = 0; i < n; i ++){ + if (!numeric_traits::is_zero(a[i] - b[i])) { + std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; + return false; + } + } + } else { + for (unsigned i = 0; i < n; i ++){ + if (fabs(numeric_traits::get_double(a[i] - b[i])) > 0.000001) { + std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; + return false; + } + } + } + return true; +} + +template +bool vectors_are_equal(const std::vector & a, const buffer &b) { + unsigned n = a.size(); + if (n != b.size()) return false; + if (numeric_traits::precise()) { + for (unsigned i = 0; i < n; i ++){ + if (!numeric_traits::is_zero(a[i] - b[i])) { + std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; + return false; + } + } + } else { + for (unsigned i = 0; i < n; i ++){ + if (fabs(numeric_traits::get_double(a[i] - b[i])) > 0.000001) { + std::cout << "a[" << i <<"] = " << a[i] << ", but " << "b[" << i <<"] = " << b[i] << std::endl; + return false; + } + } + } + return true; +} +template +bool vectors_are_equal(const std::vector & a, const std::vector &b) { + unsigned n = a.size(); + if (n != b.size()) return false; + if (numeric_traits::precise()) { + for (unsigned i = 0; i < n; i ++){ + if (!numeric_traits::is_zero(a[i] - b[i])) { + std::cout << "a[" << i <<"]" << a[i] << ", " << "b[" << i <<"]" << b[i] << std::endl; + return false; + } + } + } else { + for (unsigned i = 0; i < n; i ++){ + if (fabs(numeric_traits::get_double(a[i] - b[i])) > 0.000001) { + std::cout << "a[" << i <<"] = " << a[i] << ", but " << "b[" << i <<"] = " << b[i] << std::endl; + return false; + } + } + } + return true; +} + +template +X max_abs_in_vector(std::vector& t){ + X r(zero_of_type()); + for (auto & v : t) + r = std::max(abs(v) , r); + return r; +} + +template +X min_abs_in_vector(std::vector& t){ + X r(zero_of_type()); + for (auto & v : t) { + if (is_zero(v)) continue; + if (is_zero(r)) { + r = abs(v); + } else { + r = std::min(abs(v) , r); + } + } + return r; +} + +#ifdef LEAN_DEBUG +// used for debugging purposes only +template +class matrix { +public: + virtual T get_elem (unsigned i, unsigned j) const = 0; + virtual unsigned row_count() const = 0; + virtual unsigned column_count() const = 0; + virtual void set_number_of_rows(unsigned m) = 0; + virtual void set_number_of_columns(unsigned n) = 0; + + virtual ~matrix() {} + + bool is_equal(const matrix& other) { + if (other.row_count() != row_count() || other.column_count() != column_count()) + return false; + lp_settings settings; + for (unsigned i = 0; i < row_count(); i++) { + for (unsigned j = 0; j < column_count(); j++) { + auto a = get_elem(i, j); + auto b = other.get_elem(i, j); + if (numeric_traits::precise()) { + if (a != b) return false; + } else if (fabs(numeric_traits::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; } } - return true; } - bool operator == (matrix const & other) { - return is_equal(other); - } - T operator()(unsigned i, unsigned j) const { return get_elem(i, j); } - }; + return true; + } + bool operator == (matrix const & other) { + return is_equal(other); + } + T operator()(unsigned i, unsigned j) const { return get_elem(i, j); } +}; #endif - // These matrices appear at the end of the list - template - class tail_matrix +// These matrices appear at the end of the list +template +class tail_matrix #ifdef LEAN_DEBUG - : public matrix + : public matrix #endif - { - public: - virtual void apply_from_left_to_T(indexed_vector & w, lp_settings & settings) = 0; - virtual void apply_from_left(vector & w, lp_settings & settings) = 0; - virtual void apply_from_right(vector & w) = 0; - virtual ~tail_matrix() {} - }; +{ +public: + virtual void apply_from_left_to_T(indexed_vector & w, lp_settings & settings) = 0; + virtual void apply_from_left(std::vector & w, lp_settings & settings) = 0; + virtual void apply_from_right(std::vector & w) = 0; + virtual ~tail_matrix() {} +}; #ifdef LEAN_DEBUG - template - void apply_to_vector(matrix & m, T * w) { - // here m is a square matrix - unsigned dim = m.row_count(); +template +void apply_to_vector(matrix & m, T * w) { + // here m is a square matrix + unsigned dim = m.row_count(); - T * wc = new T[dim]; + T * wc = new T[dim]; - for (unsigned i = 0; i < dim; i++) { - wc[i] = w[i]; - } - - for (unsigned i = 0; i < dim; i++) { - T t = numeric_traits::zero(); - for (unsigned j = 0; j < dim; j++) { - t += m(i, j) * wc[j]; - } - w[i] = t; - } - delete [] wc; + for (unsigned i = 0; i < dim; i++) { + wc[i] = w[i]; } + for (unsigned i = 0; i < dim; i++) { + T t = numeric_traits::zero(); + for (unsigned j = 0; j < dim; j++) { + t += m(i, j) * wc[j]; + } + w[i] = t; + } + delete [] wc; +} - // used for debugging purposes only - template - class dense_matrix: public matrix { - public: + +// used for debugging purposes only +template +class dense_matrix: public matrix { +public: struct ref { unsigned m_i; dense_matrix & m_s; @@ -280,959 +276,874 @@ namespace lean { return m_s.m_v[m_i + j]; } }; - ref operator[] (unsigned i) { - return ref(i, *this); - } - unsigned m_m; // number of rows - unsigned m_n; // number of const - T* m_values;// - dense_matrix(unsigned m, unsigned n) : m_m(m), m_n(n) { - m_values = new T[m * n]; - for (unsigned i = 0; i < m * n; i ++) - m_values[i] = numeric_traits::zero(); - } - - dense_matrix operator*=(matrix const & a){ - lean_assert(column_count() == a.row_count()); - dense_matrix c(row_count(), a.column_count()); - for (unsigned i = 0; i < row_count(); i++) { - for (unsigned j = 0; j < a.column_count(); j++) { - T v = numeric_traits::zero(); - for (unsigned k = 0; k < a.column_count(); k++) { - v += get_elem(i, k) * a(k, j); - } - c.set_elem(i, j, v); - } - } - *this = c; - return *this; - } - - dense_matrix & operator=(matrix const & other){ - if ( this == & other) - return *this; - m_values = new T[m_m * m_n]; - for (unsigned i = 0; i < m_m; i ++) - for (unsigned j = 0; j < m_n; j++) - m_values[i * m_n + j] = other.get_elem(i, j); - return *this; - } - - dense_matrix & operator=(dense_matrix const & other){ - if ( this == & other) - return *this; - m_m = other.m_m; - m_n = other.m_n; - delete [] m_values; - m_values = new T[m_m * m_n]; - for (unsigned i = 0; i < m_m; i ++) - for (unsigned j = 0; j < m_n; j++) - m_values[i * m_n + j] = other.get_elem(i, j); - return *this; - } - - dense_matrix(dense_matrix const & other) : m_m(other.row_count()), m_n(other.column_count()) { - m_values = new T[m_m * m_n]; - for (unsigned i = 0; i < m_m; i ++) - for (unsigned j = 0; j < m_n; j++) - m_values[i * m_n + j] = other.get_elem(i, j); - } - - dense_matrix(matrix const & other) : - m_m(other.row_count()), - m_n(other.column_count()) { - m_values = new T[m_m * m_n]; - for (unsigned i = 0; i < m_m; i++) - for (unsigned j = 0; j < m_n; j++) - m_values[i * m_n + j] = other.get_elem(i, j); - } - - void apply_from_right(T * w) { - T * t = new T[m_m]; - for (int i = 0; i < m_m; i ++) { - T v = numeric_traits::zero(); - for (int j = 0; j < m_m; j++) { - v += w[j]* get_elem(j, i); - } - t[i] = v; - } - - for (int i = 0; i < m_m; i++) { - w[i] = t[i]; - } - delete [] t; - } - - void apply_from_right(vector & w) { - T * t = new T[m_m]; - for (int i = 0; i < m_m; i ++) { - T v = numeric_traits::zero(); - for (int j = 0; j < m_m; j++) { - v += w[j]* get_elem(j, i); - } - t[i] = v; - } - - for (int i = 0; i < m_m; i++) { - w[i] = t[i]; - } - delete [] t; - } - - // void apply_from_right(indexed_vector & w) { - // vector t(w.m_index.size()); - // vector tmp_index(w.m_index.size()); - // copy_aside(t, tmp_index, w); - // clear_data(w); - - // for (int i = 0; i < m_m; i ++) { - // T v = numeric_traits::zero(); - // for (int j = 0; j < m_m; j++) { - // v += w[j]* get_elem(j, i); - // } - // t[i] = v; - // } - - // w.m_index.clear(); - // for (int i = 0; i < m_m; i++) { - // w[i] = t[i]; - // if (!numeric_traits::is_zero(w[i])) { - // w.m_index.push_back(i); - // } - // } - // delete [] t; - // } - T * apply_from_left_with_different_dims(vector & w) { - T * t = new T[m_m]; - for (int i = 0; i < m_m; i ++) { - T v = numeric_traits::zero(); - for (int j = 0; j < m_n; j++) { - v += w[j]* get_elem(i, j); - } - t[i] = v; - } - - return t; - } - void apply_from_left(vector & w , lp_settings & ) { - apply_from_left(w); - } - - void apply_from_left(vector & w) { - T * t = new T[m_m]; - for (int i = 0; i < m_m; i ++) { - T v = numeric_traits::zero(); - for (int j = 0; j < m_m; j++) { - v += w[j]* get_elem(i, j); - } - t[i] = v; - } - - for (int i = 0; i < m_m; i ++) { - w[i] = t[i]; - } - delete [] t; - } - - void apply_from_left(X * w, lp_settings & ) { - T * t = new T[m_m]; - for (int i = 0; i < m_m; i ++) { - T v = numeric_traits::zero(); - for (int j = 0; j < m_m; j++) { - v += w[j]* get_elem(i, j); - } - t[i] = v; - } - - for (int i = 0; i < m_m; i ++) { - w[i] = t[i]; - } - delete [] t; - } - - void apply_from_left_to_X(vector & w, lp_settings & ) { - vector t(m_m); - for (int i = 0; i < m_m; i ++) { - X v = zero_of_type(); - for (int j = 0; j < m_m; j++) { - v += w[j]* get_elem(i, j); - } - t[i] = v; - } - - for (int i = 0; i < m_m; i ++) { - w[i] = t[i]; - } - } - - virtual void set_number_of_rows(unsigned /*m*/) {} - virtual void set_number_of_columns(unsigned /*n*/) { } - - T get_elem(unsigned i, unsigned j) const { return m_values[i * m_n + j]; } - - unsigned row_count() const { return m_m; } - unsigned column_count() const { return m_n; } - - void set_elem(unsigned i, unsigned j, const T& val) { - m_values[i * m_n + j] = val; - } - - // This method pivots row i to row i0 by muliplying row i by - // alpha and adding it to row i0. - void pivot_row_to_row(unsigned i, T alpha, unsigned i0, - double & pivot_epsilon) { - thread_local T _0 = numeric_traits::zero(); - for (unsigned j = 0; j < m_n; j++) { - m_values[i0 * m_n + j] += m_values[i * m_n + j] * alpha; - if (fabs(m_values[i0 + m_n + j]) < pivot_epsilon) { - m_values[i0 + m_n + j] = _0; - } - } - } - - void swap_columns(unsigned a, unsigned b) { - for (unsigned i = 0; i < m_m; i++) { - T t = get_elem(i, a); - set_elem(i, a, get_elem(i, b)); - set_elem(i, b, t); - } - } - - void swap_rows(unsigned a, unsigned b) { - for (unsigned i = 0; i < m_n; i++) { - T t = get_elem(a, i); - set_elem(a, i, get_elem(b, i)); - set_elem(b, i, t); - } - } - - void multiply_row_by_constant(unsigned row, T & t) { - for (unsigned i = 0; i < m_n; i++) { - set_elem(row, i, t * get_elem(row, i)); - } - } - - ~dense_matrix() { - delete [] m_values; - } - }; - - template - dense_matrix operator* (matrix & a, matrix & b){ - dense_matrix ret(a.row_count(), b.column_count()); - for (unsigned i = 0; i < ret.m_m; i++) - for (unsigned j = 0; j< ret.m_n; j++) { - T v = numeric_traits::zero(); - for (unsigned k = 0; k < a.column_count(); k ++){ - v += (a.get_elem(i, k) * b.get_elem(k, j)); - } - ret.set_elem(i, j, v); - } - return ret; + ref operator[] (unsigned i) { + return ref(i, *this); + } + unsigned m_m; // number of rows + unsigned m_n; // number of const + T* m_values;// + dense_matrix(unsigned m, unsigned n) : m_m(m), m_n(n) { + m_values = new T[m * n]; + for (unsigned i = 0; i < m * n; i ++) + m_values[i] = numeric_traits::zero(); } - inline unsigned get_width_of_column(unsigned j, vector> & A) { - unsigned r = 0; - for (unsigned i = 0; i < A.size(); i++) { - unsigned s = A[i][j].size(); - if (r < s) { - r = s; + dense_matrix operator*=(matrix const & a){ + lean_assert(column_count() == a.row_count()); + dense_matrix c(row_count(), a.column_count()); + for (unsigned i = 0; i < row_count(); i++) { + for (unsigned j = 0; j < a.column_count(); j++) { + T v = numeric_traits::zero(); + for (unsigned k = 0; k < a.column_count(); k++) { + v += get_elem(i, k) * a(k, j); + } + c.set_elem(i, j, v); } } + *this = c; + return *this; + } + + dense_matrix & operator=(matrix const & other){ + if ( this == & other) + return *this; + m_values = new T[m_m * m_n]; + for (unsigned i = 0; i < m_m; i ++) + for (unsigned j = 0; j < m_n; j++) + m_values[i * m_n + j] = other.get_elem(i, j); + return *this; + } + + dense_matrix & operator=(dense_matrix const & other){ + if ( this == & other) + return *this; + m_m = other.m_m; + m_n = other.m_n; + delete [] m_values; + m_values = new T[m_m * m_n]; + for (unsigned i = 0; i < m_m; i ++) + for (unsigned j = 0; j < m_n; j++) + m_values[i * m_n + j] = other.get_elem(i, j); + return *this; + } + + dense_matrix(dense_matrix const & other) : m_m(other.row_count()), m_n(other.column_count()) { + m_values = new T[m_m * m_n]; + for (unsigned i = 0; i < m_m; i ++) + for (unsigned j = 0; j < m_n; j++) + m_values[i * m_n + j] = other.get_elem(i, j); + } + + dense_matrix(matrix const & other) : + m_m(other.row_count()), + m_n(other.column_count()) { + m_values = new T[m_m * m_n]; + for (unsigned i = 0; i < m_m; i++) + for (unsigned j = 0; j < m_n; j++) + m_values[i * m_n + j] = other.get_elem(i, j); + } + + void apply_from_right(T * w) { + T * t = new T[m_m]; + for (int i = 0; i < m_m; i ++) { + T v = numeric_traits::zero(); + for (int j = 0; j < m_m; j++) { + v += w[j]* get_elem(j, i); + } + t[i] = v; + } + + for (int i = 0; i < m_m; i++) { + w[i] = t[i]; + } + delete [] t; + } + + void apply_from_right(std::vector & w) { + T * t = new T[m_m]; + for (int i = 0; i < m_m; i ++) { + T v = numeric_traits::zero(); + for (int j = 0; j < m_m; j++) { + v += w[j]* get_elem(j, i); + } + t[i] = v; + } + + for (int i = 0; i < m_m; i++) { + w[i] = t[i]; + } + delete [] t; + } + + T * apply_from_left_with_different_dims(std::vector & w) { + T * t = new T[m_m]; + for (int i = 0; i < m_m; i ++) { + T v = numeric_traits::zero(); + for (int j = 0; j < m_n; j++) { + v += w[j]* get_elem(i, j); + } + t[i] = v; + } + + return t; + } + void apply_from_left(std::vector & w , lp_settings & ) { + apply_from_left(w); + } + + void apply_from_left(std::vector & w) { + T * t = new T[m_m]; + for (int i = 0; i < m_m; i ++) { + T v = numeric_traits::zero(); + for (int j = 0; j < m_m; j++) { + v += w[j]* get_elem(i, j); + } + t[i] = v; + } + + for (int i = 0; i < m_m; i ++) { + w[i] = t[i]; + } + delete [] t; + } + + void apply_from_left(X * w, lp_settings & ) { + T * t = new T[m_m]; + for (int i = 0; i < m_m; i ++) { + T v = numeric_traits::zero(); + for (int j = 0; j < m_m; j++) { + v += w[j]* get_elem(i, j); + } + t[i] = v; + } + + for (int i = 0; i < m_m; i ++) { + w[i] = t[i]; + } + delete [] t; + } + + void apply_from_left_to_X(std::vector & w, lp_settings & ) { + std::vector t(m_m); + for (int i = 0; i < m_m; i ++) { + X v = zero_of_type(); + for (int j = 0; j < m_m; j++) { + v += w[j]* get_elem(i, j); + } + t[i] = v; + } + + for (int i = 0; i < m_m; i ++) { + w[i] = t[i]; + } + } + + virtual void set_number_of_rows(unsigned /*m*/) {} + virtual void set_number_of_columns(unsigned /*n*/) { } + + T get_elem(unsigned i, unsigned j) const { return m_values[i * m_n + j]; } + + unsigned row_count() const { return m_m; } + unsigned column_count() const { return m_n; } + + void set_elem(unsigned i, unsigned j, const T& val) { + m_values[i * m_n + j] = val; + } + + // This method pivots row i to row i0 by muliplying row i by + // alpha and adding it to row i0. + void pivot_row_to_row(unsigned i, T alpha, unsigned i0, + double & pivot_epsilon) { + thread_local T _0 = numeric_traits::zero(); + for (unsigned j = 0; j < m_n; j++) { + m_values[i0 * m_n + j] += m_values[i * m_n + j] * alpha; + if (fabs(m_values[i0 + m_n + j]) < pivot_epsilon) { + m_values[i0 + m_n + j] = _0; + } + } + } + + void swap_columns(unsigned a, unsigned b) { + for (unsigned i = 0; i < m_m; i++) { + T t = get_elem(i, a); + set_elem(i, a, get_elem(i, b)); + set_elem(i, b, t); + } + } + + void swap_rows(unsigned a, unsigned b) { + for (unsigned i = 0; i < m_n; i++) { + T t = get_elem(a, i); + set_elem(a, i, get_elem(b, i)); + set_elem(b, i, t); + } + } + + void multiply_row_by_constant(unsigned row, T & t) { + for (unsigned i = 0; i < m_n; i++) { + set_elem(row, i, t * get_elem(row, i)); + } + } + + ~dense_matrix() { + delete [] m_values; + } +}; + +template +dense_matrix operator* (matrix & a, matrix & b){ + dense_matrix ret(a.row_count(), b.column_count()); + for (unsigned i = 0; i < ret.m_m; i++) + for (unsigned j = 0; j< ret.m_n; j++) { + T v = numeric_traits::zero(); + for (unsigned k = 0; k < a.column_count(); k ++){ + v += (a.get_elem(i, k) * b.get_elem(k, j)); + } + ret.set_elem(i, j, v); + } + return ret; +} + +inline unsigned get_width_of_column(unsigned j, std::vector> & A) { + unsigned r = 0; + for (unsigned i = 0; i < A.size(); i++) { + unsigned s = A[i][j].size(); + if (r < s) { + r = s; + } + } + return r; +} +#endif +inline void print_blanks(int n) { + lean_assert(n >= 0); + while (n--) { + std::cout << ' '; + } +} +#ifdef LEAN_DEBUG +inline void print_matrix_with_widths(std::vector> & A, std::vector & ws) { + for (unsigned i = 0; i < A.size(); i++) { + for (unsigned j = 0; j < A[i].size(); j++) { + print_blanks(ws[j] - A[i][j].size()); + std::cout << A[i][j] << " "; + } + std::cout << std::endl; + } +} + +inline void print_string_matrix(std::vector> & A) { + std::vector widths; + + for (unsigned j = 0; j < A[0].size(); j++) { + widths.push_back(get_width_of_column(j, A)); + } + + print_matrix_with_widths(A, widths); + std::cout << std::endl; +} + +template +void print_matrix(matrix const & m) { + if (&m == nullptr) { + std::cout << "null" << std::endl; + return; + } + std::vector> A(m.row_count()); + for (unsigned i = 0; i < m.row_count(); i++) { + for (unsigned j = 0; j < m.column_count(); j++) { + A[i].push_back(T_to_string(m.get_elem(i, j))); + } + } + + print_string_matrix(A); +} + + +#endif + +template +class permutation_matrix + : public tail_matrix { + unsigned m_length; + std::vector m_permutation; + std::vector m_rev; + + class ref { + permutation_matrix & m_p; + unsigned m_i; + public: + ref(permutation_matrix & m, unsigned i):m_p(m), m_i(i) {} + + ref & operator=(unsigned v) { m_p.set_val(m_i, v); return *this; } + + ref & operator=(ref const & v) { + m_p.set_val(m_i, v.m_p.m_permutation[v.m_i]); + return *this; + } + operator unsigned & () const { return m_p.m_permutation[m_i]; } + }; + +public: + permutation_matrix() : m_length(0) {} + permutation_matrix(unsigned length): m_length(length), m_permutation(length), m_rev(length) { + unsigned i = m_length; + while (i--) + m_permutation[i] = m_rev[i] = i; + } + + permutation_matrix(unsigned length, std::vector const & values): m_length(length), m_permutation(length), m_rev(length) { + for (unsigned i = 0; i < length; i++) { + set_val(i, values[i]); + } + } + // create a unit permutation of the given length + void init(unsigned length) { + m_length = length; + m_permutation.resize(length); + m_rev.resize(length); + unsigned i = length; + while (i--) + m_permutation[i] = m_rev[i] = i; + } + + unsigned get_rev(unsigned i) { + return m_rev[i]; + } + +#ifdef LEAN_DEBUG + permutation_matrix get_inverse() const { + return permutation_matrix(m_length, m_rev); + } + void print() const { + std::cout << "["; + for (unsigned i = 0; i < m_length; i++) { + std::cout << m_permutation[i]; + if (i < m_length - 1) { + std::cout << ","; + } else { + std::cout << "]"; + } + } + std::cout << std::endl; + } +#endif + + ref operator[](unsigned i) { return ref(*this, i); } + + unsigned operator[](unsigned i) const { return m_permutation[i]; } + + template + void apply_from_left_perm(std::vector & w) { +#ifdef LEAN_DEBUG + // dense_matrix deb(*this); + // L * deb_w = clone_vector(w, row_count()); + // deb.apply_from_left(deb_w); +#endif + L * t = new L[m_length]; + for (unsigned i = 0; i < m_length; i++) { + t[i] = w[m_permutation[i]]; + } + + for (unsigned i = 0; i < m_length; i++) { + w[i] = t[i]; + } + delete [] t; +#ifdef LEAN_DEBUG + // lean_assert(vectors_are_equal(deb_w, w, row_count())); + // delete [] deb_w; +#endif + } + + void apply_from_left(std::vector & w, lp_settings &) { + apply_from_left_perm(w); + } + + void apply_from_left_to_T(indexed_vector & w, lp_settings & settings) { + apply_from_left_perm(w, settings); + } + + + template + void apply_from_left_perm(indexed_vector & w, lp_settings &) { +#ifdef LEAN_DEBUG + // dense_matrix deb(*this); + // T * deb_w = clone_vector(w.m_data, row_count()); + // deb.apply_from_right(deb_w); +#endif + std::vector t(w.m_index.size()); + std::vector tmp_index(w.m_index.size()); + copy_aside(t, tmp_index, w); + clear_data(w); + // set the new values + for (unsigned i = t.size(); i > 0;) { + i--; + unsigned j = m_rev[tmp_index[i]]; + w[j] = t[i]; + w.m_index[i] = j; + } +#ifdef LEAN_DEBUG + // lean_assert(vectors_are_equal(deb_w, w.m_data, row_count())); + // delete [] deb_w; +#endif + } + + + void apply_from_right(std::vector & w) { +#ifdef LEAN_DEBUG + // dense_matrix deb(*this); + // T * deb_w = clone_vector(w, row_count()); + // deb.apply_from_right(deb_w); +#endif + T * t = new T[m_length]; + for (unsigned i = 0; i < m_length; i++) { + t[i] = w[m_rev[i]]; + } + + for (unsigned i = 0; i < m_length; i++) { + w[i] = t[i]; + } + delete [] t; +#ifdef LEAN_DEBUG + // lean_assert(vectors_are_equal(deb_w, w, row_count())); + // delete [] deb_w; +#endif + } + + template + void copy_aside(std::vector & t, std::vector & tmp_index, indexed_vector & w) { + for (unsigned i = t.size(); i > 0;) { + i--; + unsigned j = w.m_index[i]; + t[i] = w[j]; // copy aside all non-zeroes + tmp_index[i] = j; // and the indices too + } + } + + template + void clear_data(indexed_vector & w) { + // clear old non-zeroes + for (unsigned i = w.m_index.size(); i > 0;) { + i--; + unsigned j = w.m_index[i]; + w[j] = zero_of_type(); + } + } + + template + void apply_reverse_from_left(indexed_vector & w) { + // the result will be w = p(-1) * w +#ifdef LEAN_DEBUG + // dense_matrix deb(get_reverse()); + // L * deb_w = clone_vector(w.m_data, row_count()); + // deb.apply_from_left(deb_w); +#endif + std::vector t(w.m_index.size()); + std::vector tmp_index(w.m_index.size()); + + copy_aside(t, tmp_index, w); + clear_data(w); + + // set the new values + for (unsigned i = t.size(); i > 0;) { + i--; + unsigned j = m_permutation[tmp_index[i]]; + w[j] = t[i]; + w.m_index[i] = j; + } +#ifdef LEAN_DEBUG + // lean_assert(vectors_are_equal(deb_w, w.m_data, row_count())); + // delete [] deb_w; +#endif + } + + template + void apply_reverse_from_left(std::vector & w) { + // the result will be w = p(-1) * w +#ifdef LEAN_DEBUG + // dense_matrix deb(get_reverse()); + // T * deb_w = clone_vector(w, row_count()); + // deb.apply_from_left(deb_w); +#endif + std::vector t(m_length); + for (unsigned i = 0; i < m_length; i++) { + t[m_permutation[i]] = w[i]; + } + + for (unsigned i = 0; i < m_length; i++) { + w[i] = t[i]; + } +#ifdef LEAN_DEBUG + // lean_assert(vectors_are_equal(deb_w, w, row_count())); + // delete [] deb_w; +#endif + } + template + void apply_reverse_from_right(std::vector & w) { + // the result will be w = w * p(-1) +#ifdef LEAN_DEBUG + // dense_matrix deb(get_reverse()); + // T * deb_w = clone_vector(w, row_count()); + // deb.apply_from_right(deb_w); +#endif + L * t = new T[m_length]; + for (unsigned i = 0; i < m_length; i++) { + t[i] = w[m_permutation[i]]; + } + + for (unsigned i = 0; i < m_length; i++) { + w[i] = t[i]; + } + delete [] t; +#ifdef LEAN_DEBUG + // lean_assert(vectors_are_equal(deb_w, w, row_count())); + // delete deb_w; +#endif + } + + void set_val(unsigned i, unsigned pi) { + lean_assert(i < m_length && pi < m_length); + m_permutation[i] = pi; + m_rev[pi] = i; + } + + void transpose_from_left(unsigned i, unsigned j) { + // the result will be this = (i,j)*this + lean_assert(i < m_length && j < m_length && i != j); + auto pi = m_rev[i]; + auto pj = m_rev[j]; + set_val(pi, j); + set_val(pj, i); + } + + unsigned apply_reverse(unsigned i) const { + return m_rev[i]; + } + + void transpose_from_right(unsigned i, unsigned j) { + // the result will be this = this * (i,j) + lean_assert(i < m_length && j < m_length && i != j); + auto pi = m_permutation[i]; + auto pj = m_permutation[j]; + set_val(i, pj); + set_val(j, pi); + } +#ifdef LEAN_DEBUG + T get_elem(unsigned i, unsigned j) const{ + return m_permutation[i] == j? numeric_traits::one() : numeric_traits::zero(); + } + unsigned row_count() const{ return m_length; } + unsigned column_count() const { return m_length; } + virtual void set_number_of_rows(unsigned /*m*/) { } + virtual void set_number_of_columns(unsigned /*n*/) { } +#endif + + unsigned * clone_m_permutation() { + auto r = new unsigned[m_length]; + for (int i = m_length - 1; i >= 0; i--) { + r[i] = m_permutation[i]; + } return r; } -#endif - inline void print_blanks(int n) { - lean_assert(n >= 0); - while (n--) { - cout << ' '; + + void multiply_by_permutation_from_left(permutation_matrix & p) { + auto clone = clone_m_permutation(); + lean_assert(p.m_length == m_length); + for (unsigned i = 0; i < m_length; i++) { + set_val(i, clone[p[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation } + delete clone; } -#ifdef LEAN_DEBUG - inline void print_matrix_with_widths(vector> & A, vector & ws) { - for (unsigned i = 0; i < A.size(); i++) { - for (unsigned j = 0; j < A[i].size(); j++) { - print_blanks(ws[j] - A[i][j].size()); - cout << A[i][j] << " "; - } - cout << endl; + + // this is multiplication in the matrix sense + void multiply_by_permutation_from_right(permutation_matrix & p) { + auto clone = clone_m_permutation(); + lean_assert(p.m_length == m_length); + for (unsigned i = 0; i < m_length; i++) { + set_val(i, p[clone[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation + } + delete clone; + } + + void multiply_by_reverse_from_right(permutation_matrix & q){ // todo : condensed permutations ? + auto clone = clone_m_permutation(); + // the result is this = this*q(-1) + for (unsigned i = 0; i < m_length; i++) { + set_val(i, q.m_rev[clone[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation + } + delete clone; + } + + void multiply_by_permutation_reverse_from_left(permutation_matrix & r){ // todo : condensed permutations? + // the result is this = r(-1)*this + auto clone = clone_m_permutation(); + // the result is this = this*q(-1) + for (unsigned i = 0; i < m_length; i++) { + set_val(i, clone[r.m_rev[i]]); + } + delete clone; + } + + void shrink_by_one_identity() { + lean_assert(is_identity()); + m_length--; + delete [] m_permutation; + delete [] m_rev; + m_permutation = new unsigned[m_length]; + m_rev = new unsigned[m_length]; + for (unsigned i = 0; i < m_length; i++) { + m_permutation[i] = m_rev[i] = i; } } - inline void print_string_matrix(vector> & A) { - vector widths; - - for (unsigned j = 0; j < A[0].size(); j++) { - widths.push_back(get_width_of_column(j, A)); - } - - print_matrix_with_widths(A, widths); - std::cout << std::endl; - } - - template - void print_matrix(matrix const & m) { - if (&m == nullptr) { - std::cout << "null" << std::endl; - return; - } - vector> A(m.row_count()); - for (unsigned i = 0; i < m.row_count(); i++) { - for (unsigned j = 0; j < m.column_count(); j++) { - A[i].push_back(T_to_string(m.get_elem(i, j))); - } - } - - print_string_matrix(A); - } - - -#endif - - template - class permutation_matrix - : public tail_matrix { - unsigned m_length; - vector m_permutation; - vector m_rev; - - class ref { - permutation_matrix & m_p; - unsigned m_i; - public: - ref(permutation_matrix & m, unsigned i):m_p(m), m_i(i) {} - - ref & operator=(unsigned v) { m_p.set_val(m_i, v); return *this; } - - ref & operator=(ref const & v) { - m_p.set_val(m_i, v.m_p.m_permutation[v.m_i]); - return *this; - } - operator unsigned & () const { return m_p.m_permutation[m_i]; } - }; - - public: - permutation_matrix() : m_length(0) {} - permutation_matrix(unsigned length): m_length(length), m_permutation(length), m_rev(length) { - unsigned i = m_length; - while (i--) - m_permutation[i] = m_rev[i] = i; - } - - permutation_matrix(unsigned length, vector const & values): m_length(length), m_permutation(length), m_rev(length) { - for (unsigned i = 0; i < length; i++) { - set_val(i, values[i]); - } - } - // create a unit permutation of the given length - void init(unsigned length) { - m_length = length; - m_permutation.resize(length); - m_rev.resize(length); - unsigned i = length; - while (i--) - m_permutation[i] = m_rev[i] = i; - } - - unsigned get_rev(unsigned i) { - return m_rev[i]; - } - -#ifdef LEAN_DEBUG - permutation_matrix get_inverse() const { - return permutation_matrix(m_length, m_rev); - } - void print() const { - std::cout << "["; - for (unsigned i = 0; i < m_length; i++) { - std::cout << m_permutation[i]; - if (i < m_length - 1) { - std::cout << ","; - } else { - std::cout << "]"; - } - } - std::cout << std::endl; - } -#endif - // void enlarge(unsigned delta) { - // unsigned len = m_length + delta; - // unsigned * np = new unsigned[len]; - // unsigned * nr = new unsigned[len]; - // memcpy(np, m_permutation, m_length*sizeof(unsigned)); - // memcpy(nr, m_rev, m_length*sizeof(unsigned)); - // unsigned i = m_length; - // m_length = len; - // delete [] m_permutation; - // delete [] m_rev; - // m_permutation = np; - // m_rev = nr; - // for (; i < len; i++) { - // set_val(i, i); - // } - // } - - ref operator[](unsigned i) { return ref(*this, i); } - - unsigned operator[](unsigned i) const { return m_permutation[i]; } - - template - void apply_from_left_perm(vector & w) { -#ifdef LEAN_DEBUG - // dense_matrix deb(*this); - // L * deb_w = clone_vector(w, row_count()); - // deb.apply_from_left(deb_w); -#endif - L * t = new L[m_length]; - for (unsigned i = 0; i < m_length; i++) { - t[i] = w[m_permutation[i]]; - } - - for (unsigned i = 0; i < m_length; i++) { - w[i] = t[i]; - } - delete [] t; -#ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w, row_count())); - // delete [] deb_w; -#endif - } - - void apply_from_left(vector & w, lp_settings &) { - apply_from_left_perm(w); - } - - void apply_from_left_to_T(indexed_vector & w, lp_settings & settings) { - apply_from_left_perm(w, settings); - } - - - template - void apply_from_left_perm(indexed_vector & w, lp_settings &) { -#ifdef LEAN_DEBUG - // dense_matrix deb(*this); - // T * deb_w = clone_vector(w.m_data, row_count()); - // deb.apply_from_right(deb_w); -#endif - vector t(w.m_index.size()); - vector tmp_index(w.m_index.size()); - copy_aside(t, tmp_index, w); - clear_data(w); - // set the new values - for (unsigned i = t.size(); i > 0;) { - i--; - unsigned j = m_rev[tmp_index[i]]; - w[j] = t[i]; - w.m_index[i] = j; - } -#ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w.m_data, row_count())); - // delete [] deb_w; -#endif - } - - - void apply_from_right(vector & w) { -#ifdef LEAN_DEBUG - // dense_matrix deb(*this); - // T * deb_w = clone_vector(w, row_count()); - // deb.apply_from_right(deb_w); -#endif - T * t = new T[m_length]; - for (unsigned i = 0; i < m_length; i++) { - t[i] = w[m_rev[i]]; - } - - for (unsigned i = 0; i < m_length; i++) { - w[i] = t[i]; - } - delete [] t; -#ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w, row_count())); - // delete [] deb_w; -#endif - } - -// void apply_from_right(indexed_vector & w) { -// lean_assert(false); // i think it is never called -// #ifdef LEAN_DEBUG -// // dense_matrix deb(*this); -// // T * deb_w = clone_vector(w.m_data, row_count()); -// // deb.apply_from_right(deb_w); -// #endif -// vector t(w.m_index.size()); -// vector tmp_index(w.m_index.size()); -// copy_aside(t, tmp_index, w); -// clear_data(w); -// // set the new values -// for (unsigned i = t.size(); i > 0;) { -// i--; -// unsigned j = m_permutation[tmp_index[i]]; -// w[j] = t[i]; -// w.m_index[i] = j; -// } -// for (unsigned i = 0; i < m_length; i++) { -// w[i] = t[i]; -// } -// #ifdef LEAN_DEBUG -// // lean_assert(vectors_are_equal(deb_w, w.m_data, row_count())); -// // delete [] deb_w; -// #endif -// } - - template - void copy_aside(vector & t, vector & tmp_index, indexed_vector & w) { - for (unsigned i = t.size(); i > 0;) { - i--; - unsigned j = w.m_index[i]; - t[i] = w[j]; // copy aside all non-zeroes - tmp_index[i] = j; // and the indices too - } - } - - template - void clear_data(indexed_vector & w) { - // clear old non-zeroes - for (unsigned i = w.m_index.size(); i > 0;) { - i--; - unsigned j = w.m_index[i]; - w[j] = zero_of_type(); - } - } - - template - void apply_reverse_from_left(indexed_vector & w) { - // the result will be w = p(-1) * w -#ifdef LEAN_DEBUG - // dense_matrix deb(get_reverse()); - // L * deb_w = clone_vector(w.m_data, row_count()); - // deb.apply_from_left(deb_w); -#endif - vector t(w.m_index.size()); - vector tmp_index(w.m_index.size()); - - copy_aside(t, tmp_index, w); - clear_data(w); - - // set the new values - for (unsigned i = t.size(); i > 0;) { - i--; - unsigned j = m_permutation[tmp_index[i]]; - w[j] = t[i]; - w.m_index[i] = j; - } -#ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w.m_data, row_count())); - // delete [] deb_w; -#endif - } - - template - void apply_reverse_from_left(std::vector & w) { - // the result will be w = p(-1) * w -#ifdef LEAN_DEBUG - // dense_matrix deb(get_reverse()); - // T * deb_w = clone_vector(w, row_count()); - // deb.apply_from_left(deb_w); -#endif - vector t(m_length); - for (unsigned i = 0; i < m_length; i++) { - t[m_permutation[i]] = w[i]; - } - - for (unsigned i = 0; i < m_length; i++) { - w[i] = t[i]; - } -#ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w, row_count())); - // delete [] deb_w; -#endif - } - template - void apply_reverse_from_right(vector & w) { - // the result will be w = w * p(-1) -#ifdef LEAN_DEBUG - // dense_matrix deb(get_reverse()); - // T * deb_w = clone_vector(w, row_count()); - // deb.apply_from_right(deb_w); -#endif - L * t = new T[m_length]; - for (unsigned i = 0; i < m_length; i++) { - t[i] = w[m_permutation[i]]; - } - - for (unsigned i = 0; i < m_length; i++) { - w[i] = t[i]; - } - delete [] t; -#ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w, row_count())); - // delete deb_w; -#endif - } - - void set_val(unsigned i, unsigned pi) { - lean_assert(i < m_length && pi < m_length); - m_permutation[i] = pi; - m_rev[pi] = i; - } - - void transpose_from_left(unsigned i, unsigned j) { - // the result will be this = (i,j)*this - lean_assert(i < m_length && j < m_length && i != j); - auto pi = m_rev[i]; - auto pj = m_rev[j]; - set_val(pi, j); - set_val(pj, i); - } - - unsigned apply_reverse(unsigned i) const { - return m_rev[i]; - } - - void transpose_from_right(unsigned i, unsigned j) { - // the result will be this = this * (i,j) - lean_assert(i < m_length && j < m_length && i != j); - auto pi = m_permutation[i]; - auto pj = m_permutation[j]; - set_val(i, pj); - set_val(j, pi); - } -#ifdef LEAN_DEBUG - T get_elem(unsigned i, unsigned j) const{ - return m_permutation[i] == j? numeric_traits::one() : numeric_traits::zero(); - } - unsigned row_count() const{ return m_length; } - unsigned column_count() const { return m_length; } - virtual void set_number_of_rows(unsigned /*m*/) { } - virtual void set_number_of_columns(unsigned /*n*/) { } -#endif - - unsigned * clone_m_permutation() { - auto r = new unsigned[m_length]; - for (int i = m_length - 1; i >= 0; i--) { - r[i] = m_permutation[i]; - } - return r; - } - - void multiply_by_permutation_from_left(permutation_matrix & p) { - auto clone = clone_m_permutation(); - lean_assert(p.m_length == m_length); - for (unsigned i = 0; i < m_length; i++) { - set_val(i, clone[p[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation - } - delete clone; - } - - // this is multiplication in the matrix sense - void multiply_by_permutation_from_right(permutation_matrix & p) { - auto clone = clone_m_permutation(); - lean_assert(p.m_length == m_length); - for (unsigned i = 0; i < m_length; i++) { - set_val(i, p[clone[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation - } - delete clone; - } - - void multiply_by_reverse_from_right(permutation_matrix & q){ // todo : condensed permutations ? - auto clone = clone_m_permutation(); - // the result is this = this*q(-1) - for (unsigned i = 0; i < m_length; i++) { - set_val(i, q.m_rev[clone[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation - } - delete clone; - } - - void multiply_by_permutation_reverse_from_left(permutation_matrix & r){ // todo : condensed permutations? - // the result is this = r(-1)*this - auto clone = clone_m_permutation(); - // the result is this = this*q(-1) - for (unsigned i = 0; i < m_length; i++) { - set_val(i, clone[r.m_rev[i]]); - } - delete clone; - } - - void shrink_by_one_identity() { - lean_assert(is_identity()); - m_length--; - delete [] m_permutation; - delete [] m_rev; - m_permutation = new unsigned[m_length]; - m_rev = new unsigned[m_length]; - for (unsigned i = 0; i < m_length; i++) { - m_permutation[i] = m_rev[i] = i; - } - } - - bool is_identity() const { - for (unsigned i = 0; i < m_length; i++) { - if (m_permutation[i] != i) { - return false; - } - } - return true; - } - - unsigned size() const { return m_length; } - - unsigned * values() const { return m_permutation; } - }; // end of the permutation class - -#ifdef LEAN_DEBUG - template - class permutation_generator { - unsigned m_n; - permutation_generator* m_lower; - bool m_done = false; - permutation_matrix m_current; - unsigned m_last; - public: - permutation_generator(unsigned n): m_n(n), m_current(n) { - lean_assert(n > 0); - if (n > 1) { - m_lower = new permutation_generator(n - 1); - } else { - m_lower = nullptr; - } - - m_last = 0; - } - - permutation_generator(const permutation_generator & o): m_n(o.m_n), m_done(o.m_done), m_current(o.m_current), m_last(o.m_last) { - if (m_lower != nullptr) { - m_lower = new permutation_generator(o.m_lower); - } else { - m_lower = nullptr; - } - } - - bool move_next() { - if (m_done) { + bool is_identity() const { + for (unsigned i = 0; i < m_length; i++) { + if (m_permutation[i] != i) { return false; } + } + return true; + } - if (m_lower == nullptr) { - if (m_last == 0) { - m_last++; + unsigned size() const { return m_length; } + + unsigned * values() const { return m_permutation; } +}; // end of the permutation class + +#ifdef LEAN_DEBUG +template +class permutation_generator { + unsigned m_n; + permutation_generator* m_lower; + bool m_done = false; + permutation_matrix m_current; + unsigned m_last; +public: + permutation_generator(unsigned n): m_n(n), m_current(n) { + lean_assert(n > 0); + if (n > 1) { + m_lower = new permutation_generator(n - 1); + } else { + m_lower = nullptr; + } + + m_last = 0; + } + + permutation_generator(const permutation_generator & o): m_n(o.m_n), m_done(o.m_done), m_current(o.m_current), m_last(o.m_last) { + if (m_lower != nullptr) { + m_lower = new permutation_generator(o.m_lower); + } else { + m_lower = nullptr; + } + } + + bool move_next() { + if (m_done) { + return false; + } + + if (m_lower == nullptr) { + if (m_last == 0) { + m_last++; + return true; + } else { + m_done = true; + return false; + } + } else { + if (m_last < m_n && m_last > 0) { + m_current[m_last - 1] = m_current[m_last]; + m_current[m_last] = m_n - 1; + m_last++; + return true; + } else { + if (m_lower -> move_next()) { + auto lower_curr = m_lower -> current(); + for ( unsigned i = 1; i < m_n; i++ ){ + m_current[i] = (*lower_curr)[i - 1]; + } + m_current[0] = m_n - 1; + m_last = 1; return true; } else { m_done = true; return false; } - } else { - if (m_last < m_n && m_last > 0) { - m_current[m_last - 1] = m_current[m_last]; - m_current[m_last] = m_n - 1; - m_last++; - return true; - } else { - if (m_lower -> move_next()) { - auto lower_curr = m_lower -> current(); - for ( unsigned i = 1; i < m_n; i++ ){ - m_current[i] = (*lower_curr)[i - 1]; - } - m_current[0] = m_n - 1; - m_last = 1; - return true; - } else { - m_done = true; - return false; - } - } } } + } - ~permutation_generator() { - if (m_lower != nullptr) { - delete m_lower; + ~permutation_generator() { + if (m_lower != nullptr) { + delete m_lower; + } + } + + permutation_matrix *current() { + return &m_current; + } +}; + +template +inline unsigned number_of_inversions(permutation_matrix & p) { + unsigned ret = 0; + unsigned n = p.size(); + for (unsigned i = 0; i < n; i++) { + for (unsigned j = i + 1; j < n; j++) { + if (p[i] > p[j]) { + ret++; } } - - permutation_matrix *current() { - return &m_current; - } - }; - - template - inline unsigned number_of_inversions(permutation_matrix & p) { - unsigned ret = 0; - unsigned n = p.size(); - for (unsigned i = 0; i < n; i++) { - for (unsigned j = i + 1; j < n; j++) { - if (p[i] > p[j]) { - ret++; - } - } - } - return ret; } + return ret; +} - template - int sign(permutation_matrix & p) { - return is_even(number_of_inversions(p))? 1: -1; - } +template +int sign(permutation_matrix & p) { + return is_even(number_of_inversions(p))? 1: -1; +} - template - T det_val_on_perm(permutation_matrix* u, const matrix& m) { - unsigned n = m.row_count(); - T ret = numeric_traits::one(); - for (unsigned i = 0; i < n; i++) { - unsigned j = (*u)[i]; - ret *= m(i, j); - } - return ret * sign(*u); +template +T det_val_on_perm(permutation_matrix* u, const matrix& m) { + unsigned n = m.row_count(); + T ret = numeric_traits::one(); + for (unsigned i = 0; i < n; i++) { + unsigned j = (*u)[i]; + ret *= m(i, j); } + return ret * sign(*u); +} - template - T determinant(const matrix& m) { - lean_assert(m.column_count() == m.row_count()); - unsigned n = m.row_count(); - permutation_generator allp(n); - T ret = numeric_traits::zero(); - while (allp.move_next()){ - ret += det_val_on_perm(allp.current(), m); - } - return ret; +template +T determinant(const matrix& m) { + lean_assert(m.column_count() == m.row_count()); + unsigned n = m.row_count(); + permutation_generator allp(n); + T ret = numeric_traits::zero(); + while (allp.move_next()){ + ret += det_val_on_perm(allp.current(), m); } + return ret; +} #endif - // this matrix has ones on the diagonal, outside of a column - // and one non-zero element off the diagonal in the column +// this matrix has ones on the diagonal, outside of a column +// and one non-zero element off the diagonal in the column - template - struct one_off_diagonal_matrix: +template +struct one_off_diagonal_matrix: public tail_matrix { - unsigned m_i; // the element row - unsigned m_j; // the element column - T m_val_jj; // the value in the column's diagonal element - T m_val_ij; // the value off the diagonal element - public: - one_off_diagonal_matrix(unsigned i, unsigned j, T val_at_jj, T val_at_ij): m_i(i), m_j(j), m_val_jj(val_at_jj), m_val_ij(val_at_ij) { - } + unsigned m_i; // the element row + unsigned m_j; // the element column + T m_val_jj; // the value in the column's diagonal element + T m_val_ij; // the value off the diagonal element +public: + one_off_diagonal_matrix(unsigned i, unsigned j, T val_at_jj, T val_at_ij): m_i(i), m_j(j), m_val_jj(val_at_jj), m_val_ij(val_at_ij) { + } - one_off_diagonal_matrix(const one_off_diagonal_matrix * o):m_i(o.m_i), m_j(o.m_j), m_val_jj(o.m_val_jj), m_val_ij(o.m_val_ij) { + one_off_diagonal_matrix(const one_off_diagonal_matrix * o):m_i(o.m_i), m_j(o.m_j), m_val_jj(o.m_val_jj), m_val_ij(o.m_val_ij) { #ifdef LEAN_DEBUG - m_m = m_n = o.m_m; + m_m = m_n = o.m_m; #endif - } + } - void conjugate_by_permutation(permutation_matrix & p) { - // this = p * this * p(-1) + void conjugate_by_permutation(permutation_matrix & p) { + // this = p * this * p(-1) #ifdef LEAN_DEBUG - // auto rev = p.get_reverse(); - // auto deb = ((*this) * rev); - // deb = p * deb; + // auto rev = p.get_reverse(); + // auto deb = ((*this) * rev); + // deb = p * deb; #endif - m_j = p.get_rev(m_j); - m_i = p.get_rev(m_i); + m_j = p.get_rev(m_j); + m_i = p.get_rev(m_i); #ifdef LEAN_DEBUG - // lean_assert(deb == *this); + // lean_assert(deb == *this); #endif - } + } #ifdef LEAN_DEBUG - unsigned m_m; - unsigned m_n; - virtual void set_number_of_rows(unsigned m) { m_n = m_m = m; } - virtual void set_number_of_columns(unsigned n) {m_m = m_n = n; } + unsigned m_m; + unsigned m_n; + virtual void set_number_of_rows(unsigned m) { m_n = m_m = m; } + virtual void set_number_of_columns(unsigned n) {m_m = m_n = n; } - T get_elem (unsigned i, unsigned j) const { - if (j == m_j){ - if (i == m_j){ - return 1 / m_val_jj; - } - if (i == m_i) { - return m_val_ij; - } - return numeric_traits::zero(); + T get_elem (unsigned i, unsigned j) const { + if (j == m_j){ + if (i == m_j){ + return 1 / m_val_jj; } - - return i == j ? numeric_traits::one() : numeric_traits::zero(); - } - - unsigned row_count() const { return m_m; } // not defined } - unsigned column_count() const { return m_n; } // not defined } -#endif - void apply_from_left(vector & w, lp_settings &) { -#ifdef LEAN_DEBUG - // dense_matrix deb(*this); - // T * deb_w = clone_vector(w, row_count()); - // deb.apply_from_left(deb_w); -#endif - auto wj = w[m_j]; - w[m_j] = wj / m_val_jj; - w[m_i] += wj * m_val_ij; -#ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w, row_count())); - // delete deb_w; -#endif - } - - template - void apply_from_left_local(indexed_vector & w, lp_settings & settings) { -#ifdef LEAN_DEBUG - // dense_matrix deb(*this); - // T * deb_w = clone_vector(w.m_data, row_count()); - // deb.apply_from_left(deb_w); -#endif - if (is_zero(w[m_j])) { - return; + if (i == m_i) { + return m_val_ij; } - - bool m_i_is_zero = is_zero(w[m_i]); - L wj = w[m_j]; - w[m_j] = wj / m_val_jj; - if (m_i_is_zero) { - w[m_i] = wj * m_val_ij; - w.m_index.push_back(m_i); - } else { - w[m_i] += wj * m_val_ij; // we can get a zero here - do we need to check for it - } - - lean_assert(check_vector_for_small_values(w, settings )); - -#ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w.m_data, row_count())); - // delete deb_w; -#endif + return numeric_traits::zero(); } - void apply_from_left_to_T(indexed_vector &w, lp_settings &settings) { - apply_from_left_local(w, settings); - } - void apply_from_right(vector & w) { -#ifdef LEAN_DEBUG - // dense_matrix deb(*this); - // T * deb_w = clone_vector(w, row_count()); - // deb.apply_from_right(deb_w); + return i == j ? numeric_traits::one() : numeric_traits::zero(); + } + + unsigned row_count() const { return m_m; } // not defined } + unsigned column_count() const { return m_n; } // not defined } #endif - w[m_j] = w[m_j] / m_val_jj + m_val_ij * w[m_i]; + void apply_from_left(std::vector & w, lp_settings &) { #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w, row_count())); - // delete deb_w; + // dense_matrix deb(*this); + // T * deb_w = clone_vector(w, row_count()); + // deb.apply_from_left(deb_w); #endif + auto wj = w[m_j]; + w[m_j] = wj / m_val_jj; + w[m_i] += wj * m_val_ij; +#ifdef LEAN_DEBUG + // lean_assert(vectors_are_equal(deb_w, w, row_count())); + // delete deb_w; +#endif + } + + template + void apply_from_left_local(indexed_vector & w, lp_settings & settings) { +#ifdef LEAN_DEBUG + // dense_matrix deb(*this); + // T * deb_w = clone_vector(w.m_data, row_count()); + // deb.apply_from_left(deb_w); +#endif + if (is_zero(w[m_j])) { + return; } -// void apply_from_right(indexed_vector & w) { -// #ifdef LEAN_DEBUG -// // dense_matrix deb(*this); -// // vector deb_w(w.m_data); -// // deb.apply_from_right(deb_w); -// #endif -// bool j_is_used = !numeric_traits::is_zero(w[m_j]); -// if (j_is_used) { -// w[m_j] = w[m_j] / m_val_jj + m_val_ij * w[m_i]; -// } else { -// w[m_j] = m_val_ij * w[m_i]; -// w.m_index.push_back(m_j); -// } -// #ifdef LEAN_DEBUG -// // lean_assert(vectors_are_equal(deb_w, w.m_data, row_count())); -// // delete deb_w; -// #endif -// } - }; // end of one_off_diagonal_matrix + bool m_i_is_zero = is_zero(w[m_i]); + L wj = w[m_j]; + w[m_j] = wj / m_val_jj; + if (m_i_is_zero) { + w[m_i] = wj * m_val_ij; + w.m_index.push_back(m_i); + } else { + w[m_i] += wj * m_val_ij; // we can get a zero here - do we need to check for it + } + + lean_assert(check_vector_for_small_values(w, settings )); + +#ifdef LEAN_DEBUG + // lean_assert(vectors_are_equal(deb_w, w.m_data, row_count())); + // delete deb_w; +#endif + } + + void apply_from_left_to_T(indexed_vector &w, lp_settings &settings) { + apply_from_left_local(w, settings); + } + void apply_from_right(std::vector & w) { +#ifdef LEAN_DEBUG + // dense_matrix deb(*this); + // T * deb_w = clone_vector(w, row_count()); + // deb.apply_from_right(deb_w); +#endif + w[m_j] = w[m_j] / m_val_jj + m_val_ij * w[m_i]; +#ifdef LEAN_DEBUG + // lean_assert(vectors_are_equal(deb_w, w, row_count())); + // delete deb_w; +#endif + } +}; // end of one_off_diagonal_matrix } diff --git a/src/util/lp/row_eta_matrix.h b/src/util/lp/row_eta_matrix.h index f24d75e4c..a7a06330b 100644 --- a/src/util/lp/row_eta_matrix.h +++ b/src/util/lp/row_eta_matrix.h @@ -54,7 +54,7 @@ public: return m_row_vector.m_data[m_row]; } - void apply_from_left(vector & w, lp_settings & + void apply_from_left(std::vector & w, lp_settings & #ifdef LEAN_DEBUG // settings #endif @@ -114,7 +114,7 @@ public: m_row_vector.push_back(row_index, val); } - void apply_from_right(vector & w) { + void apply_from_right(std::vector & w) { T w_row = w[m_row]; if (numeric_traits::is_zero(w_row)) return; #ifdef LEAN_DEBUG @@ -170,7 +170,7 @@ public: #endif m_row = p.apply_reverse(m_row); // copy aside the column indices - vector columns; + std::vector columns; for (auto it = sparse_vector_iterator(m_row_vector); !it.done(); it.move()) { columns.push_back(it.index()); } diff --git a/src/util/lp/scaler.h b/src/util/lp/scaler.h index 05ffe3c72..5a64a25eb 100644 --- a/src/util/lp/scaler.h +++ b/src/util/lp/scaler.h @@ -6,264 +6,263 @@ */ #pragma once - -#include "util/numerics/double.h" #include #include #include #include /* printf, fopen */ #include /* exit, EXIT_FAILURE */ +#include "util/numerics/double.h" namespace lean { - // for scaling an LP - template - class scaler { - vector & m_b; // right side - static_matrix &m_A; // the constraint matrix - const T & m_scaling_minimum; - const T & m_scaling_maximum; - vector& m_column_scale; - lp_settings & m_settings; - public: - // constructor - scaler(vector & b, static_matrix &A, const T & scaling_minimum, const T & scaling_maximum, vector & column_scale, - lp_settings & settings): - m_b(b), - m_A(A), - m_scaling_minimum(scaling_minimum), - m_scaling_maximum(scaling_maximum), - m_column_scale(column_scale), - m_settings(settings) { - lean_assert(m_column_scale.size() == 0); - m_column_scale.resize(m_A.column_count(), numeric_traits::one()); - } +// for scaling an LP +template +class scaler { + std::vector & m_b; // right side + static_matrix &m_A; // the constraint matrix + const T & m_scaling_minimum; + const T & m_scaling_maximum; + std::vector& m_column_scale; + lp_settings & m_settings; +public: + // constructor + scaler(std::vector & b, static_matrix &A, const T & scaling_minimum, const T & scaling_maximum, std::vector & column_scale, + lp_settings & settings): + m_b(b), + m_A(A), + m_scaling_minimum(scaling_minimum), + m_scaling_maximum(scaling_maximum), + m_column_scale(column_scale), + m_settings(settings) { + lean_assert(m_column_scale.size() == 0); + m_column_scale.resize(m_A.column_count(), numeric_traits::one()); + } - T right_side_balance() { - T ret = zero_of_type(); - unsigned i = m_A.row_count(); - while (i--) { - T rs = abs(convert_struct::convert(m_b[i])); - if (!is_zero(rs)) { - numeric_traits::log(rs); - ret += rs * rs; - } - } - return ret; - } - - T get_balance() { - return m_A.get_balance(); - } - - T A_min() const { - T min = zero_of_type(); - for (unsigned i = 0; i < m_A.row_count(); i++) { - T t = m_A.get_min_abs_in_row(i); - min = i == 0 ? t : std::min(t, min); - } - return min; - } - - T A_max() const { - T max = zero_of_type(); - for (unsigned i = 0; i < m_A.row_count(); i++) { - T t = m_A.get_max_abs_in_row(i); - max = i == 0? t : std::max(t, max); - } - return max; - } - - T get_A_ratio() const { - T min = A_min(); - T max = A_max(); - T ratio = max / min; - return ratio; - } - - T get_max_ratio_on_rows() const { - T ret = T(1); - unsigned i = m_A.row_count(); - while (i--) { - T t = m_A.get_max_abs_in_row(i)/m_A.get_min_abs_in_row(i); - if (t > ret) - ret = t; - } - return ret; - } - - T get_max_ratio_on_columns() const { - T ret = T(1); - unsigned i = m_A.column_count(); - while (i--) { - T t = m_A.get_max_abs_in_column(i)/m_A.get_min_abs_in_column(i); - if (t > ret) - ret = t; - } - return ret; - } - - void scale_rows_with_geometric_mean() { - unsigned i = m_A.row_count(); - while (i--) { - T max = m_A.get_max_abs_in_row(i); - T min = m_A.get_min_abs_in_row(i); - lean_assert(max > zero_of_type() && min > zero_of_type()); - T gm = T(sqrt(numeric_traits::get_double(max*min))); - m_A.divide_row_by_constant(i, gm); - m_b[i] /= gm; + T right_side_balance() { + T ret = zero_of_type(); + unsigned i = m_A.row_count(); + while (i--) { + T rs = abs(convert_struct::convert(m_b[i])); + if (!is_zero(rs)) { + numeric_traits::log(rs); + ret += rs * rs; } } + return ret; + } - void scale_columns_with_geometric_mean() { - unsigned i = m_A.column_count(); - while (i--) { - T max = m_A.get_max_abs_in_column(i); - T min = m_A.get_min_abs_in_column(i); - T gm = T(1)/T(sqrt(numeric_traits::get_double(max*min))); - m_A.scale_column(i, gm); - m_column_scale[i]*=gm; - } + T get_balance() { + return m_A.get_balance(); + } + + T A_min() const { + T min = zero_of_type(); + for (unsigned i = 0; i < m_A.row_count(); i++) { + T t = m_A.get_min_abs_in_row(i); + min = i == 0 ? t : std::min(t, min); } + return min; + } - void scale_once_for_ratio() { - T max_ratio_on_rows = get_max_ratio_on_rows(); - T max_ratio_on_columns = get_max_ratio_on_columns(); - bool scale_rows_first = max_ratio_on_rows > max_ratio_on_columns; - // if max_ratio_on_columns is the largerst then the rows are in worser shape then columns - if (scale_rows_first) { - scale_rows_with_geometric_mean(); - scale_columns_with_geometric_mean(); + T A_max() const { + T max = zero_of_type(); + for (unsigned i = 0; i < m_A.row_count(); i++) { + T t = m_A.get_max_abs_in_row(i); + max = i == 0? t : std::max(t, max); + } + return max; + } + + T get_A_ratio() const { + T min = A_min(); + T max = A_max(); + T ratio = max / min; + return ratio; + } + + T get_max_ratio_on_rows() const { + T ret = T(1); + unsigned i = m_A.row_count(); + while (i--) { + T t = m_A.get_max_abs_in_row(i)/m_A.get_min_abs_in_row(i); + if (t > ret) + ret = t; + } + return ret; + } + + T get_max_ratio_on_columns() const { + T ret = T(1); + unsigned i = m_A.column_count(); + while (i--) { + T t = m_A.get_max_abs_in_column(i)/m_A.get_min_abs_in_column(i); + if (t > ret) + ret = t; + } + return ret; + } + + void scale_rows_with_geometric_mean() { + unsigned i = m_A.row_count(); + while (i--) { + T max = m_A.get_max_abs_in_row(i); + T min = m_A.get_min_abs_in_row(i); + lean_assert(max > zero_of_type() && min > zero_of_type()); + T gm = T(sqrt(numeric_traits::get_double(max*min))); + m_A.divide_row_by_constant(i, gm); + m_b[i] /= gm; + } + } + + void scale_columns_with_geometric_mean() { + unsigned i = m_A.column_count(); + while (i--) { + T max = m_A.get_max_abs_in_column(i); + T min = m_A.get_min_abs_in_column(i); + T gm = T(1)/T(sqrt(numeric_traits::get_double(max*min))); + m_A.scale_column(i, gm); + m_column_scale[i]*=gm; + } + } + + void scale_once_for_ratio() { + T max_ratio_on_rows = get_max_ratio_on_rows(); + T max_ratio_on_columns = get_max_ratio_on_columns(); + bool scale_rows_first = max_ratio_on_rows > max_ratio_on_columns; + // if max_ratio_on_columns is the largerst then the rows are in worser shape then columns + if (scale_rows_first) { + scale_rows_with_geometric_mean(); + scale_columns_with_geometric_mean(); + } else { + scale_columns_with_geometric_mean(); + scale_rows_with_geometric_mean(); + } + } + + bool scale_with_ratio() { + T ratio = get_A_ratio(); + // The ratio is greater than or equal to one. We would like to diminish it and bring it as close to 1 as possible + unsigned reps = 20; + do { + scale_once_for_ratio(); + T new_r = get_A_ratio(); + if (new_r >= T(0.9) * ratio) + break; + } while (reps--); + + bring_rows_and_columns_maximums_to_one(); + return true; + } + + void bring_row_maximums_to_one() { + unsigned i = m_A.row_count(); + while (i--) { + T t = m_A.get_max_abs_in_row(i); + m_A.divide_row_by_constant(i, t); + m_b[i] /= t; + } + } + + void bring_column_maximums_to_one() { + unsigned i = m_A.column_count(); + while (i--) { + T t = T(1) / m_A.get_max_abs_in_column(i); + m_A.scale_column(i, t); + m_column_scale[i] *= t; + } + } + + void bring_rows_and_columns_maximums_to_one() { + if (get_max_ratio_on_rows() > get_max_ratio_on_columns()) { + bring_row_maximums_to_one(); + bring_column_maximums_to_one(); + } else { + bring_column_maximums_to_one(); + bring_row_maximums_to_one(); + } + } + + bool scale_with_log_balance() { + T balance = get_balance(); + T balance_before_scaling = balance; + // todo : analyze the scale order : rows-columns, or columns-rows. Iterate if needed + for (int i = 0; i < 10; i++) { + scale_rows(); + scale_columns(); + T nb = get_balance(); + if (nb < T(0.9) * balance) { + balance = nb; } else { - scale_columns_with_geometric_mean(); - scale_rows_with_geometric_mean(); + balance = nb; + break; } } + return balance <= balance_before_scaling; + } + // Returns true if and only if the scaling was successful. + // It is the caller responsibility to restore the matrix + bool scale() { + if (numeric_traits::precise()) return true; + if (m_settings.scale_with_ratio) + return scale_with_ratio(); + return scale_with_log_balance(); + } - bool scale_with_ratio() { - T ratio = get_A_ratio(); - // The ratio is greater than or equal to one. We would like to diminish it and bring it as close to 1 as possible - unsigned reps = 20; + void scale_rows() { + for (unsigned i = 0; i < m_A.row_count(); i++) + scale_row(i); + } + + void scale_row(unsigned i) { + T row_max = std::max(m_A.get_max_abs_in_row(i), abs(convert_struct::convert(m_b[i]))); + T alpha = numeric_traits::one(); + if (numeric_traits::is_zero(row_max)) { + return; + } + if (numeric_traits::get_double(row_max) < m_scaling_minimum) { do { - scale_once_for_ratio(); - T new_r = get_A_ratio(); - if (new_r >= T(0.9) * ratio) - break; - } while (reps--); + alpha *= 2; + row_max *= 2; + } while (numeric_traits::get_double(row_max) < m_scaling_minimum); + m_A.scale_row(i, alpha); + m_b[i] *= alpha; + } else if (numeric_traits::get_double(row_max) > m_scaling_maximum) { + do { + alpha /= 2; + row_max /= 2; + } while (numeric_traits::get_double(row_max) > m_scaling_maximum); + m_A.scale_row(i, alpha); + m_b[i] *= alpha; + } + } - bring_rows_and_columns_maximums_to_one(); - return true; + void scale_column(unsigned i){ + T column_max = m_A.get_max_abs_in_column(i); + T alpha = numeric_traits::one(); + + if (numeric_traits::is_zero(column_max)){ + return; // the column has zeros only } - void bring_row_maximums_to_one() { - unsigned i = m_A.row_count(); - while (i--) { - T t = m_A.get_max_abs_in_row(i); - m_A.divide_row_by_constant(i, t); - m_b[i] /= t; - } + if (numeric_traits::get_double(column_max) < m_scaling_minimum) { + do { + alpha *= 2; + column_max *= 2; + } while (numeric_traits::get_double(column_max) < m_scaling_minimum); + } else if (numeric_traits::get_double(column_max) > m_scaling_maximum) { + do { + alpha /= 2; + column_max /= 2; + } while (numeric_traits::get_double(column_max) > m_scaling_maximum); + } else { + return; } + m_A.scale_column(i, alpha); + m_column_scale[i] = alpha; + } - void bring_column_maximums_to_one() { - unsigned i = m_A.column_count(); - while (i--) { - T t = T(1) / m_A.get_max_abs_in_column(i); - m_A.scale_column(i, t); - m_column_scale[i] *= t; - } + void scale_columns() { + for (unsigned i = 0; i < m_A.column_count(); i++) { + scale_column(i); } - - void bring_rows_and_columns_maximums_to_one() { - if (get_max_ratio_on_rows() > get_max_ratio_on_columns()) { - bring_row_maximums_to_one(); - bring_column_maximums_to_one(); - } else { - bring_column_maximums_to_one(); - bring_row_maximums_to_one(); - } - } - - bool scale_with_log_balance() { - T balance = get_balance(); - T balance_before_scaling = balance; - // todo : analyze the scale order : rows-columns, or columns-rows. Iterate if needed - for (int i = 0; i < 10; i++) { - scale_rows(); - scale_columns(); - T nb = get_balance(); - if (nb < T(0.9) * balance) { - balance = nb; - } else { - balance = nb; - break; - } - } - return balance <= balance_before_scaling; - } - // Returns true if and only if the scaling was successful. - // It is the caller responsibility to restore the matrix - bool scale() { - if (numeric_traits::precise()) return true; - if (m_settings.scale_with_ratio) - return scale_with_ratio(); - return scale_with_log_balance(); - } - - void scale_rows() { - for (unsigned i = 0; i < m_A.row_count(); i++) - scale_row(i); - } - - void scale_row(unsigned i) { - T row_max = std::max(m_A.get_max_abs_in_row(i), abs(convert_struct::convert(m_b[i]))); - T alpha = numeric_traits::one(); - if (numeric_traits::is_zero(row_max)) { - return; - } - if (numeric_traits::get_double(row_max) < m_scaling_minimum) { - do { - alpha *= 2; - row_max *= 2; - } while (numeric_traits::get_double(row_max) < m_scaling_minimum); - m_A.scale_row(i, alpha); - m_b[i] *= alpha; - } else if (numeric_traits::get_double(row_max) > m_scaling_maximum) { - do { - alpha /= 2; - row_max /= 2; - } while (numeric_traits::get_double(row_max) > m_scaling_maximum); - m_A.scale_row(i, alpha); - m_b[i] *= alpha; - } - } - - void scale_column(unsigned i){ - T column_max = m_A.get_max_abs_in_column(i); - T alpha = numeric_traits::one(); - - if (numeric_traits::is_zero(column_max)){ - return; // the column has zeros only - } - - if (numeric_traits::get_double(column_max) < m_scaling_minimum) { - do { - alpha *= 2; - column_max *= 2; - } while (numeric_traits::get_double(column_max) < m_scaling_minimum); - } else if (numeric_traits::get_double(column_max) > m_scaling_maximum) { - do { - alpha /= 2; - column_max /= 2; - } while (numeric_traits::get_double(column_max) > m_scaling_maximum); - } else { - return; - } - m_A.scale_column(i, alpha); - m_column_scale[i] = alpha; - } - - void scale_columns() { - for (unsigned i = 0; i < m_A.column_count(); i++) { - scale_column(i); - } - } - }; + } +}; } diff --git a/src/util/lp/sparse_matrix.h b/src/util/lp/sparse_matrix.h index 6bf7db8cf..b08186d76 100644 --- a/src/util/lp/sparse_matrix.h +++ b/src/util/lp/sparse_matrix.h @@ -23,10 +23,7 @@ #include "util/lp/eta_matrix.h" #include "util/lp/binary_heap_upair_queue.h" namespace lean { - -using std::vector; -using std::cout; - // it is a square matrix +// it is a square matrix template class sparse_matrix #ifdef LEAN_DEBUG @@ -35,7 +32,7 @@ class sparse_matrix { struct col_header { unsigned m_shortened_markovitz = 0; - vector> m_values; // the actual column values + std::vector> m_values; // the actual column values col_header() {} @@ -50,8 +47,8 @@ class sparse_matrix binary_heap_upair_queue m_pivot_queue; public: - vector>> m_rows; - vector m_columns; + std::vector>> m_rows; + std::vector m_columns; permutation_matrix m_row_permutation; permutation_matrix m_column_permutation; indexed_vector m_work_pivot_vector; @@ -80,13 +77,13 @@ public: } void copy_column_from_static_matrix(unsigned col, static_matrix const &A, unsigned col_index_in_the_new_matrix) { - vector> const & A_col_vector = A.m_columns[col]; + std::vector> const & A_col_vector = A.m_columns[col]; unsigned size = A_col_vector.size(); - vector> & new_column_vector = m_columns[col_index_in_the_new_matrix].m_values; + std::vector> & new_column_vector = m_columns[col_index_in_the_new_matrix].m_values; for (unsigned l = 0; l < size; l++) { column_cell const & col_cell = A_col_vector[l]; unsigned col_offset = new_column_vector.size(); - vector> & row_vector = m_rows[col_cell.m_i]; + std::vector> & row_vector = m_rows[col_cell.m_i]; unsigned row_offset = row_vector.size(); new_column_vector.push_back(indexed_value(col_cell.m_value, col_cell.m_i, row_offset)); row_vector.push_back(indexed_value(col_cell.m_value, col_index_in_the_new_matrix, col_offset)); @@ -134,7 +131,7 @@ public: }; void set_with_no_adjusting_for_row(unsigned row, unsigned col, T val) { // should not be used in efficient code - vector> & row_vec = m_rows[row]; + std::vector> & row_vec = m_rows[row]; for (auto & iv : row_vec) { if (iv.m_index == col) { iv.set_value(val); @@ -146,7 +143,7 @@ public: } void set_with_no_adjusting_for_col(unsigned row, unsigned col, T val) { // should not be used in efficient code - vector> & col_vec = m_columns[col].m_values; + std::vector> & col_vec = m_columns[col].m_values; for (auto & iv : col_vec) { if (iv.m_index == row) { iv.set_value(val); @@ -203,19 +200,19 @@ public: // end of access for debugging helpers - vector> & get_row_values(unsigned row) { + std::vector> & get_row_values(unsigned row) { return m_rows[row]; } - vector> const & get_row_values(unsigned row) const { + std::vector> const & get_row_values(unsigned row) const { return m_rows[row]; } - vector> & get_column_values(unsigned col) { + std::vector> & get_column_values(unsigned col) { return m_columns[col].m_values; } - vector> const & get_column_values(unsigned col) const { + std::vector> const & get_column_values(unsigned col) const { return m_columns[col].m_values; } @@ -240,7 +237,7 @@ public: void init_row_headers() { for (unsigned l = 0; l < m_row_permutation.size(); l++) { - m_rows.push_back(vector>()); + m_rows.push_back(std::vector>()); } } @@ -284,7 +281,7 @@ public: } - void remove_element(vector> & row_vals, unsigned row_offset, vector> & column_vals, unsigned column_offset) { + void remove_element(std::vector> & row_vals, unsigned row_offset, std::vector> & column_vals, unsigned column_offset) { if (column_offset != column_vals.size() - 1) { auto & column_iv = column_vals[column_offset] = column_vals.back(); // copy from the tail column_iv_other(column_iv).m_other = column_offset; @@ -301,13 +298,13 @@ public: row_vals.pop_back(); } - void remove_element(vector> & row_chunk, indexed_value & row_el_iv) { + void remove_element(std::vector> & row_chunk, indexed_value & row_el_iv) { auto & column_chunk = get_column_values(row_el_iv.m_index); indexed_value & col_el_iv = column_chunk[row_el_iv.m_other]; remove_element(row_chunk, col_el_iv.m_other, column_chunk, row_el_iv.m_other); } - void put_max_index_to_0(vector> & row_vals, unsigned max_index) { + void put_max_index_to_0(std::vector> & row_vals, unsigned max_index) { if (max_index == 0) return; indexed_value * max_iv = & row_vals[max_index]; indexed_value * start_iv = & row_vals[0]; @@ -325,7 +322,7 @@ public: set_max_in_row(m_rows[row]); } - void set_max_in_row(vector> & row_vals) { + void set_max_in_row(std::vector> & row_vals) { if (row_vals.size() == 0) return; T max_val = numeric_traits::zero(); @@ -535,11 +532,11 @@ public: } void swap_columns(unsigned a, unsigned b) { - // cout << "swaapoiiin" << endl; - // dense_matrix d(*this); + // cout << "swaapoiiin" << std::endl; + // dense_matrix d(*this); m_column_permutation.transpose_from_left(a, b); - // d.swap_columns(a, b); - // lean_assert(*this == d); + // d.swap_columns(a, b); + // lean_assert(*this == d); } void swap_rows(unsigned a, unsigned b) { @@ -554,7 +551,7 @@ public: for (auto & iv : m_rows[i]) { T v = iv.m_value / t; if (settings.abs_val_is_smaller_than_drop_tolerance(v)){ - v = numeric_traits::zero(); + v = numeric_traits::zero(); } m_columns[iv.m_index].m_values[iv.m_other].set_value(iv.m_value = v); } @@ -685,7 +682,7 @@ public: } template - void find_error_in_solution_U_y(vector& y_orig, vector & y) { + void find_error_in_solution_U_y(std::vector& y_orig, std::vector & y) { unsigned i = dimension(); while (i--) { y_orig[i] -= dot_product_with_row(i, y); @@ -693,7 +690,7 @@ public: } template - void add_delta_to_solution(const vector& del, vector & y) { + void add_delta_to_solution(const std::vector& del, std::vector & y) { unsigned i = dimension(); while (i--) { y[i] += del[i]; @@ -701,8 +698,8 @@ public: } template - void double_solve_U_y(vector& y){ - vector y_orig(y); // copy y aside + void double_solve_U_y(std::vector& y){ + std::vector y_orig(y); // copy y aside solve_U_y(y); find_error_in_solution_U_y(y_orig, y); // y_orig contains the error now @@ -744,7 +741,7 @@ public: virtual void set_number_of_columns(unsigned /*n*/) { } #endif template - L dot_product_with_row (unsigned row, const vector & y) const { + L dot_product_with_row (unsigned row, const std::vector & y) const { L ret = zero_of_type(); auto & mc = get_row_values(adjust_row(row)); for (auto & c : mc) { @@ -781,7 +778,7 @@ public: return false; } - void remove_element_that_is_not_in_w(vector> & column_vals, indexed_value & col_el_iv) { + void remove_element_that_is_not_in_w(std::vector> & column_vals, indexed_value & col_el_iv) { auto & row_chunk = m_rows[col_el_iv.m_index]; indexed_value & row_el_iv = row_chunk[col_el_iv.m_other]; unsigned index_in_row = col_el_iv.m_other; @@ -865,11 +862,11 @@ public: unsigned pivot_score(unsigned i, unsigned j) { - // It goes like this (rnz-1)(cnz-1) is the Markovitz number, that is the max number of - // new non zeroes we can obtain after the pivoting. - // In addition we will get another cnz - 1 elements in the eta matrix created for this pivot, - // which gives rnz(cnz-1). For example, is 0 for a column singleton, but not for - // a row singleton ( which is not a column singleton). + // It goes like this (rnz-1)(cnz-1) is the Markovitz number, that is the max number of + // new non zeroes we can obtain after the pivoting. + // In addition we will get another cnz - 1 elements in the eta matrix created for this pivot, + // which gives rnz(cnz-1). For example, is 0 for a column singleton, but not for + // a row singleton ( which is not a column singleton). auto col_header = m_columns[j]; @@ -906,7 +903,7 @@ public: enqueue_domain_into_pivot_queue(); } - void recover_pivot_queue(vector & rejected_pivots) { + void recover_pivot_queue(std::vector & rejected_pivots) { for (auto p : rejected_pivots) { m_pivot_queue.enqueue(p.first, p.second, pivot_score(p.first, p.second)); } @@ -925,8 +922,6 @@ public: return abs(iv.m_value) * c_partial_pivoting < max ? 1: 0; } return 2; // the element became zero but it still sits in the active pivots? - cout << "column " << j << " does not belong to row " << i << endl; - throw "cannot be here"; } bool remove_row_from_active_pivots_and_shorten_columns(unsigned row) { @@ -994,7 +989,7 @@ public: unsigned cnz = cols.size(); for (auto & iv : cols) { if (adjust_row_inverse(iv.m_index) < k) - cnz--; + cnz--; } lean_assert(cnz > 0); return m_rows[i].m_values.size() * (cnz - 1); @@ -1030,9 +1025,9 @@ public: return true; } void print_active_matrix(unsigned k) { - cout << "active matrix for k = " << k << endl; + std::cout << "active matrix for k = " << k << std::endl; if (k >= dimension()) { - cout << "empty" << endl; + std::cout << "empty" << std::endl; return; } unsigned dim = dimension() - k; @@ -1057,7 +1052,7 @@ public: unsigned arow = adjust_row(i); for (auto & iv : m_rows[arow].m_values) { lean_assert(pivot_score_without_shortened_counters(arow, iv.m_index, k + 1) == - m_pivot_queue.get_priority(arow, iv.m_index)); + m_pivot_queue.get_priority(arow, iv.m_index)); } return true; } @@ -1071,7 +1066,7 @@ public: bool get_pivot_for_column(unsigned &i, unsigned &j, T const & c_partial_pivoting, unsigned k) { - vector pivots_candidates_that_are_too_small; + std::vector pivots_candidates_that_are_too_small; while (!m_pivot_queue.is_empty()) { m_pivot_queue.dequeue(i, j); unsigned i_inv = adjust_row_inverse(i); @@ -1098,26 +1093,26 @@ public: recover_pivot_queue(pivots_candidates_that_are_too_small); return false; /* - unsigned m = dimension(); - unsigned markovitz_number_min = m * m; - unsigned iterations = 0; - for (unsigned k = 2; k <= m; k++){ - if (markovitz_number_min < (k-1) * (k-1)) - return true; + unsigned m = dimension(); + unsigned markovitz_number_min = m * m; + unsigned iterations = 0; + for (unsigned k = 2; k <= m; k++){ + if (markovitz_number_min < (k-1) * (k-1)) + return true; - if (get_pivot_in_k_short_columns(k, markovitz_number_min, i, j, c_partial_pivoting, iterations) - || - get_pivot_in_k_short_rows(k, markovitz_number_min, i, j, c_partial_pivoting, iterations)) { - return true; - } - if (iterations > search_depth * 2 && markovitz_number_min < m * m) - return true; - } - return markovitz_number_min < m * m; + if (get_pivot_in_k_short_columns(k, markovitz_number_min, i, j, c_partial_pivoting, iterations) + || + get_pivot_in_k_short_rows(k, markovitz_number_min, i, j, c_partial_pivoting, iterations)) { + return true; + } + if (iterations > search_depth * 2 && markovitz_number_min < m * m) + return true; + } + return markovitz_number_min < m * m; */ } - bool elem_is_too_small(vector> & row_chunk, indexed_value & iv, T const & c_partial_pivoting) { + bool elem_is_too_small(std::vector> & row_chunk, indexed_value & iv, T const & c_partial_pivoting) { if (&iv == &row_chunk[0]) { return false; // the max element is at the head } @@ -1137,7 +1132,7 @@ public: bool shorten_columns_by_pivot_row(unsigned i, unsigned pivot_column) { - vector> & row_chunk = get_row_values(i); + std::vector> & row_chunk = get_row_values(i); for (indexed_value & iv : row_chunk) { unsigned j = iv.m_index; @@ -1163,7 +1158,7 @@ public: } void fill_eta_matrix(unsigned j, eta_matrix ** eta) { - vector> & col_chunk = get_column_values(adjust_column(j)); + std::vector> & col_chunk = get_column_values(adjust_column(j)); bool is_unit = true; for (auto & iv : col_chunk) { unsigned i = adjust_row_inverse(iv.m_index); @@ -1203,7 +1198,7 @@ public: bool is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings & settings) const { for (unsigned i = 0; i < dimension(); i++) { - vector> const & row_chunk = get_row_values(i); + std::vector> const & row_chunk = get_row_values(i); lean_assert(row_chunk.size()); T const & max = abs(row_chunk[0].m_value); unsigned ai = adjust_row_inverse(i); @@ -1214,7 +1209,7 @@ public: return false; if (aj == ai) { if (iv.m_value != 1) { - cout << "value at diagonal = " << iv.m_value << endl; + std::cout << "value at diagonal = " << iv.m_value << std::endl; return false; } } @@ -1245,18 +1240,18 @@ public: for (indexed_value & column_iv : mc) { indexed_value & row_iv = column_iv_other(column_iv); if (row_iv.m_index != col) { - cout << "m_other in row does not belong to column " << col << ", but to column " << row_iv.m_index << endl; + std::cout << "m_other in row does not belong to column " << col << ", but to column " << row_iv.m_index << std::endl; lean_assert(false); } if (& row_iv_other(row_iv) != &column_iv) { - cout << "row and col do not point to each other" << endl; + std::cout << "row and col do not point to each other" << std::endl; lean_assert(false); } if (row_iv.m_value != column_iv.m_value) { - cout << "the data from col " << col << " for row " << column_iv.m_index << " is different in the column " << endl; - cout << "in the col it is " << column_iv.m_value << ", but in the row it is " << row_iv.m_value << endl; + std::cout << "the data from col " << col << " for row " << column_iv.m_index << " is different in the column " << std::endl; + std::cout << "in the col it is " << column_iv.m_value << ", but in the row it is " << row_iv.m_value << std::endl; lean_assert(false); } } @@ -1268,18 +1263,18 @@ public: indexed_value & column_iv = row_iv_other(row_iv); if (column_iv.m_index != row) { - cout << "col_iv does not point to correct row " << row << " but to " << column_iv.m_index << endl; + std::cout << "col_iv does not point to correct row " << row << " but to " << column_iv.m_index << std::endl; lean_assert(false); } if (& row_iv != & column_iv_other(column_iv)) { - cout << "row and col do not point to each other" << endl; + std::cout << "row and col do not point to each other" << std::endl; lean_assert(false); } if (row_iv.m_value != column_iv.m_value) { - cout << "the data from col " << column_iv.m_index << " for row " << row << " is different in the column " << endl; - cout << "in the col it is " << column_iv.m_value << ", but in the row it is " << row_iv.m_value << endl; + std::cout << "the data from col " << column_iv.m_index << " for row " << row << " is different in the column " << std::endl; + std::cout << "in the col it is " << column_iv.m_value << ", but in the row it is " << row_iv.m_value << std::endl; lean_assert(false); } } @@ -1297,10 +1292,11 @@ public: } } - void map_domain_to_vector(unordered_map, unsigned> & domain, vector> & vec) { + void map_domain_to_vector(std::unordered_map, unsigned> & domain, + std::vector> & vec) { lean_assert(domain.size() == 0 && vec.size() == 0); for (unsigned i = 0; i < dimension(); i++) { - vector> & row = get_row_values(i); + std::vector> & row = get_row_values(i); for (auto & iv : row) { unsigned j = iv.m_index; unsigned nz = vec.size(); diff --git a/src/util/lp/sparse_vector.h b/src/util/lp/sparse_vector.h index f8355fff1..4769b978d 100644 --- a/src/util/lp/sparse_vector.h +++ b/src/util/lp/sparse_vector.h @@ -8,6 +8,7 @@ #pragma once #include #include "util/debug.h" +#include "util/pair.h" #include "util/numerics/numeric_traits.h" #include "util/numerics/xnumeral.h" #include "util/numerics/mpq.h" @@ -18,8 +19,6 @@ #include "util/numerics/mpfp.h" #include "util/lp/lp_settings.h" namespace lean { -using std::vector; -using std::pair; template void zero_vector(T * t, unsigned size) { while (size-- > 0) { // it can be made faster by copying big chunks @@ -37,7 +36,7 @@ class sparse_vector_iterator; // forward definition template class sparse_vector { public: - vector> m_data; + std::vector> m_data; void push_back(unsigned index, T val) { m_data.emplace_back(index, val); } @@ -66,7 +65,7 @@ public: template class sparse_vector_iterator { - typedef typename vector< pair >::iterator p_it; + typedef typename std::vector>::iterator p_it; p_it m_it; p_it m_end; public: diff --git a/src/util/lp/square_dense_submatrix.h b/src/util/lp/square_dense_submatrix.h index 68f77cdec..af0fc6b15 100644 --- a/src/util/lp/square_dense_submatrix.h +++ b/src/util/lp/square_dense_submatrix.h @@ -23,8 +23,6 @@ #include "util/lp/eta_matrix.h" #include "util/lp/binary_heap_upair_queue.h" namespace lean { -using std::vector; -using std::cout; template class square_dense_submatrix : public tail_matrix { // the submatrix uses the permutations of the parent matrix to access the elements @@ -45,7 +43,7 @@ class square_dense_submatrix : public tail_matrix { public: // debug unsigned m_index_start; unsigned m_dim; - vector m_v; + std::vector m_v; sparse_matrix * m_parent = nullptr; permutation_matrix m_row_permutation; public: @@ -230,7 +228,7 @@ public: } } template - L row_by_vector_product(unsigned i, const vector & v) { + L row_by_vector_product(unsigned i, const std::vector & v) { lean_assert(i >= m_index_start); unsigned row_in_subm = i - m_index_start; @@ -242,7 +240,7 @@ public: } template - L column_by_vector_product(unsigned j, const vector & v) { + L column_by_vector_product(unsigned j, const std::vector & v) { lean_assert(j >= m_index_start); unsigned offset = j - m_index_start; @@ -276,7 +274,7 @@ public: #endif // use indexed vector here #ifndef DO_NOT_USE_INDEX - vector t(m_parent->dimension(), zero_of_type()); + std::vector t(m_parent->dimension(), zero_of_type()); for (auto k : w.m_index) { unsigned j = adjust_column(k); // k-th element will contribute only to column j if (j < m_index_start) { @@ -301,7 +299,7 @@ public: } } #else - vector t(m_parent->dimension()); + std::vector t(m_parent->dimension()); for (unsigned i = 0; i < m_index_start; i++) { t[adjust_row_inverse(i)] = w[adjust_column_inverse(i)]; } @@ -327,7 +325,7 @@ public: } template - void apply_from_left_to_vector(vector & w) { + void apply_from_left_to_vector(std::vector & w) { // lp_settings & settings) { // dense_matrix deb(*this); // vector deb_w(w); @@ -338,7 +336,7 @@ public: // // print_vector(w.m_data); // // cout << "deb_w" << endl; // // print_vector(deb_w); - vector t(m_parent->dimension()); + std::vector t(m_parent->dimension()); for (unsigned i = 0; i < m_index_start; i++) { t[adjust_row_inverse(i)] = w[adjust_column_inverse(i)]; } @@ -383,17 +381,17 @@ public: void apply_from_right(indexed_vector & w) { lean_assert(false); // not implemented } - void apply_from_left(vector & w, lp_settings & /*settings*/) { + void apply_from_left(std::vector & w, lp_settings & /*settings*/) { apply_from_left_to_vector(w);// , settings); } - void apply_from_right(vector & w) { + void apply_from_right(std::vector & w) { #ifdef LEAN_DEBUG // dense_matrix deb(*this); // vector deb_w(w); // deb.apply_from_right(deb_w); #endif - vector t(w.size()); + std::vector t(w.size()); for (unsigned j = 0; j < m_index_start; j++) { t[adjust_column_inverse(j)] = w[adjust_row_inverse(j)]; } @@ -404,7 +402,7 @@ public: lean_assert(w.size() == t.size()); w = t; #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w)); + // lean_assert(vector_are_equal(deb_w, w)); #endif } diff --git a/src/util/lp/static_matrix.h b/src/util/lp/static_matrix.h index 13715bca1..f0fa7c95a 100644 --- a/src/util/lp/static_matrix.h +++ b/src/util/lp/static_matrix.h @@ -61,12 +61,12 @@ class static_matrix std::set> m_domain; #endif public: - typedef vector> row_strip; - typedef vector> column_strip; - vector m_work_pivot_vector; + typedef std::vector> row_strip; + typedef std::vector> column_strip; + std::vector m_work_pivot_vector; - vector m_rows; - vector m_columns; + std::vector m_rows; + std::vector m_columns; // starting inner classes class ref { static_matrix & m_matrix; @@ -283,7 +283,7 @@ public: v.set_value(it.m_value, it.m_i); } } - void copy_column_to_vector (unsigned j, vector & v) const { + void copy_column_to_vector (unsigned j, std::vector & v) const { v.resize(row_count(), numeric_traits::zero()); for (auto & it : m_columns[j]) { if (!is_zero(it.m_value)) @@ -352,7 +352,7 @@ public: #ifdef LEAN_DEBUG void check_consistency() { - unordered_map, T> by_rows; + std::unordered_map, T> by_rows; for (int i = 0; i < m_rows.size(); i++){ for (auto & t : m_rows[i]) { pair p(i, t.m_j); @@ -360,7 +360,7 @@ public: by_rows[p] = t.get_val(); } } - unordered_map, T> by_cols; + std::unordered_map, T> by_cols; for (int i = 0; i < m_columns.size(); i++){ for (auto & t : m_columns[i]) { pair p(t.m_i, i); @@ -373,7 +373,8 @@ public: for (auto & t : by_rows) { auto ic = by_cols.find(t.first); if (ic == by_cols.end()){ - cout << "rows have pair (" << t.first.first <<"," << t.first.second << "), but columns don't " << endl; + std::cout << "rows have pair (" << t.first.first <<"," << t.first.second + << "), but columns don't " << std::endl; } lean_assert(ic != by_cols.end()); lean_assert(t.second == ic->second);