mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 19:52:29 +00:00 
			
		
		
		
	add cancellations
Signed-off-by: Lev Nachmanson <levnach@hotmail.com> syntax errors Signed-off-by: Lev Nachmanson <levnach@microsoft.com> use std::vector instead of vector in cut_solver temporarily Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix in is_upper_bound, is_lower_bound Signed-off-by: Lev Nachmanson <levnach@hotmail.com> add bound() for polynomial, needs more testing Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on resolve Signed-off-by: Lev Nachmanson <levnach@microsoft.com> implement resolve() Signed-off-by: Lev Nachmanson <levnach@microsoft.com> implement improves() Signed-off-by: Lev Nachmanson <levnach@hotmail.com> replace low_bound by lower_bound Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> better printing in cut_solver.h Signed-off-by: Lev Nachmanson <levnach@hotmail.com> add value vector to cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on bound propagaion for cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> bound propagation for integer inequalites Signed-off-by: Lev Nachmanson <levnach@hotmail.com> bound propagation for integer inequalites Signed-off-by: Lev Nachmanson <levnach@hotmail.com> bound propagattions on integers Signed-off-by: Lev Nachmanson <levnach@hotmail.com> adding m_explanation field to cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> simplify bound propagation in cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> calculate conflict explanation Signed-off-by: Lev Nachmanson <levnach@hotmail.com> change m_explanation type to a set Signed-off-by: Lev Nachmanson <levnach@hotmail.com> making cut_solver a member of int_solver, missing push/pop support Signed-off-by: Lev Nachmanson <levnach@hotmail.com> Nikolaj's comments Signed-off-by: Lev Nachmanson <levnach@hotmail.com> Nikolaj's comments Signed-off-by: Lev Nachmanson <levnach@hotmail.com> return explanations from cut_solver and hook up push/pop Signed-off-by: Lev Nachmanson <levnach@hotmail.com> hook up push/pop Signed-off-by: Lev Nachmanson <levnach@hotmail.com> using resize of std::vector Signed-off-by: Lev Nachmanson <levnach@hotmail.com> it is a big squashed commit Signed-off-by: Lev Nachmanson <levnach@hotmail.com> rename hpp to cpp Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fixes in push/pop of cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> return simple inequalities a part of a conflict Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on propagation and the main loop Signed-off-by: Lev Nachmanson <levnach@hotmail.com> add file Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> init m_v[j], the var values only when j is fixed Signed-off-by: Lev Nachmanson <levnach@hotmail.com> cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> handle decide in cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> start on resolve_conflict Signed-off-by: Lev Nachmanson <levnach@hotmail.com> start on resolve_conflict Signed-off-by: Lev Nachmanson <levnach@hotmail.com> remove cut_solver_def.h Signed-off-by: Lev Nachmanson <levnach@hotmail.com> in the middle Signed-off-by: Lev Nachmanson <levnach@hotmail.com> change signature of resolve Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix the domain of the decided var Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on tightening of ineqs Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on tight ineqs Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on tightening Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on tightening Signed-off-by: Lev Nachmanson <levnach@hotmail.com> resolve conflict Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix in usage of resolve() Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on conflict resolution Signed-off-by: Lev Nachmanson <levnach@hotmail.com> cut_solver is not a template Signed-off-by: Lev Nachmanson <levnach@hotmail.com> represent var_info as a class, not a struct Signed-off-by: Lev Nachmanson <levnach@hotmail.com> make literal a class Signed-off-by: Lev Nachmanson <levnach@hotmail.com> better resolve_conflict scheme, and switch to *constraints in literals Signed-off-by: Lev Nachmanson <levnach@hotmail.com> debug conflict resolution in cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> switch to vector Signed-off-by: Lev Nachmanson <levnach@hotmail.com> remove nondetermenistic behavior from cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> debug resolve conflict Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix backjump Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix backjump Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix backjump Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix backjump Signed-off-by: Lev Nachmanson <levnach@hotmail.com> dumb explanation Signed-off-by: Lev Nachmanson <levnach@hotmail.com> get rid of a parameter Signed-off-by: Lev Nachmanson <levnach@hotmail.com> add lemmas origins Signed-off-by: Lev Nachmanson <levnach@hotmail.com> use lemma_origins to provide correct explanations Signed-off-by: Lev Nachmanson <levnach@hotmail.com> use lemma_origins to provide correct explanations Signed-off-by: Lev Nachmanson <levnach@hotmail.com> store lemmas in a separate vector Signed-off-by: Lev Nachmanson <levnach@hotmail.com> use std::unordered_set for m_dependent_constraints Signed-off-by: Lev Nachmanson <levnach@hotmail.com> use std::unordered_set for m_dependent_constraints Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix bugs with lemmas Signed-off-by: Lev Nachmanson <levnach@hotmail.com> finding conflicting cores Signed-off-by: Lev Nachmanson <levnach@hotmail.com> switch from changed variables to active_set Signed-off-by: Lev Nachmanson <levnach@hotmail.com> less active constraints Signed-off-by: Lev Nachmanson <levnach@hotmail.com> work on cut_solver.h Signed-off-by: Lev Nachmanson <levnach@hotmail.com> propagate simple constraing immediately Signed-off-by: Lev Nachmanson <levnach@hotmail.com> propagate simple constraints immediately Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fixing bugs with active set Signed-off-by: Lev Nachmanson <levnach@hotmail.com> remove const_cast Signed-off-by: Lev Nachmanson <levnach@hotmail.com> towards unbounded variables Signed-off-by: Lev Nachmanson <levnach@hotmail.com> toward unbounded variables Signed-off-by: Lev Nachmanson <levnach@hotmail.com> toward unbounded variables Signed-off-by: Lev Nachmanson <levnach@hotmail.com> make lemmas_origins a set Signed-off-by: Lev Nachmanson <levnach@hotmail.com> use correct hash and equal in m_lemma_origins Signed-off-by: Lev Nachmanson <levnach@hotmail.com> add testing code Signed-off-by: Lev Nachmanson <levnach@hotmail.com> add testing code Signed-off-by: Lev Nachmanson <levnach@hotmail.com> debug Signed-off-by: Lev Nachmanson <levnach@hotmail.com> debug unlimited vars Signed-off-by: Lev Nachmanson <levnach@hotmail.com> take in Nikolaj's comments and improvements Signed-off-by: Lev Nachmanson <levnach@hotmail.com> address the comments Signed-off-by: Lev Nachmanson <levnach@hotmail.com> handle unlimited vars in check_inconsistent Signed-off-by: Lev Nachmanson <levnach@hotmail.com> debug Signed-off-by: Lev Nachmanson <levnach@hotmail.com> detect trivial polynomials in resolve Signed-off-by: Lev Nachmanson <levnach@hotmail.com> Nikolaj's changes Signed-off-by: Lev Nachmanson <levnach@hotmail.com> simplify handling of m_global_bound_var Signed-off-by: Lev Nachmanson <levnach@hotmail.com> decide on m_global_bound_var if it is not fixed Signed-off-by: Lev Nachmanson <levnach@hotmail.com> simplify m_global_bound_var Signed-off-by: Lev Nachmanson <levnach@hotmail.com> remove m_global_bound_var, simplify the indexing of var_infos of cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> do not run cut_solver with vars without any bound Signed-off-by: Lev Nachmanson <levnach@hotmail.com> small changes Signed-off-by: Lev Nachmanson <levnach@hotmail.com> add cancellation in cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> do not pop lemmas during a cut_solver run Signed-off-by: Lev Nachmanson <levnach@hotmail.com> treating cut_solver as an heurisitic Signed-off-by: Lev Nachmanson <levnach@hotmail.com> prepare for cut_solver returning undef Signed-off-by: Lev Nachmanson <levnach@hotmail.com> simplify work with active_set in cut_solver, add stats Signed-off-by: Lev Nachmanson <levnach@hotmail.com> simplify var_info literals Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix a bug in fill_conflict_explanation Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix a bug in the conflict explanation Signed-off-by: Lev Nachmanson <levnach@hotmail.com> add timeout to validate_* in theory_lra.cpp Signed-off-by: Lev Nachmanson <levnach@hotmail.com> simplify cut_solver, no special treatment for simple constraints Signed-off-by: Lev Nachmanson <levnach@hotmail.com> cleanup the cancel story Signed-off-by: Lev Nachmanson <levnach@hotmail.com> cleanup cancelling Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix a bug in push/pop of cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> extract a method in int_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> some progress with the new scheme Signed-off-by: Lev Nachmanson <levnach@hotmail.com> add testing code Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fixes in test and in literal creation Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix a bug in bound propagation in cut_solver.h Signed-off-by: Lev Nachmanson <levnach@hotmail.com> simplify cut_solver Signed-off-by: Lev Nachmanson <levnach@hotmail.com> provide valid conflict explanation Signed-off-by: Lev Nachmanson <levnach@hotmail.com> use a lazy push in stacked_map Signed-off-by: Lev Nachmanson <levnach@hotmail.com> use a lazy push in stacked_map Signed-off-by: Lev Nachmanson <levnach@hotmail.com> optimize stack operations on var_info's domains Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fix a bug in tightening Signed-off-by: Lev Nachmanson <levnach@hotmail.com> use the standard tactics from qflia_tactic Signed-off-by: Lev Nachmanson <levnach@hotmail.com> spread the var domain stack over literals Signed-off-by: Lev Nachmanson <levnach@hotmail.com> spread the var domain stack over literals Signed-off-by: Lev Nachmanson <levnach@hotmail.com> avoid cycling in cut_solver.h and fixes in push/pop Signed-off-by: Lev Nachmanson <levnach@hotmail.com> fixes after rebase Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
		
							parent
							
								
									58ca4518e5
								
							
						
					
					
						commit
						6202b2f2e4
					
				
					 103 changed files with 7035 additions and 5106 deletions
				
			
		|  | @ -259,9 +259,9 @@ public: | |||
|     bool is_uminus(expr const * n) const { return is_app_of(n, m_afid, OP_UMINUS); } | ||||
|     bool is_mul(expr const * n) const { return is_app_of(n, m_afid, OP_MUL); } | ||||
|     bool is_div(expr const * n) const { return is_app_of(n, m_afid, OP_DIV); } | ||||
|     bool is_div0(expr const * n) const { return is_app_of(n, m_afid, OP_DIV_0); } | ||||
|     //bool is_div0(expr const * n) const { return is_app_of(n, m_afid, OP_DIV_0); }
 | ||||
|     bool is_idiv(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV); } | ||||
|     bool is_idiv0(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV_0); } | ||||
|     //bool is_idiv0(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV_0); }
 | ||||
|     bool is_mod(expr const * n) const { return is_app_of(n, m_afid, OP_MOD); } | ||||
|     bool is_rem(expr const * n) const { return is_app_of(n, m_afid, OP_REM); } | ||||
|     bool is_to_real(expr const * n) const { return is_app_of(n, m_afid, OP_TO_REAL); } | ||||
|  | @ -535,3 +535,4 @@ inline app_ref operator>(app_ref const& x, app_ref const& y) { | |||
| } | ||||
| 
 | ||||
| #endif /* ARITH_DECL_PLUGIN_H_ */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -1714,6 +1714,7 @@ ast * ast_manager::register_node_core(ast * n) { | |||
| 
 | ||||
| 
 | ||||
|     n->m_id   = is_decl(n) ? m_decl_id_gen.mk() : m_expr_id_gen.mk(); | ||||
| 
 | ||||
|     TRACE("ast", tout << "Object " << n->m_id << " was created.\n";); | ||||
|     TRACE("mk_var_bug", tout << "mk_ast: " << n->m_id << "\n";); | ||||
|     // increment reference counters
 | ||||
|  |  | |||
|  | @ -800,58 +800,9 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu | |||
|         result = m_util.mk_numeral(div(v1, v2), is_int); | ||||
|         return BR_DONE; | ||||
|     } | ||||
|     if (m_util.is_numeral(arg2, v2, is_int) && v2.is_zero()) { | ||||
|         result = m_util.mk_idiv0(arg1); | ||||
|         return BR_REWRITE1; | ||||
|     } | ||||
|     expr_ref quot(m()); | ||||
|     if (divides(arg1, arg2, quot)) { | ||||
|         result = m_util.mk_mul(quot, m_util.mk_idiv(arg1, arg1)); | ||||
|         return BR_REWRITE2; | ||||
|     } | ||||
|     return BR_FAILED; | ||||
| } | ||||
| 
 | ||||
| bool arith_rewriter::divides(expr* d, expr* n, expr_ref& quot) { | ||||
|     if (d == n) { | ||||
|         quot = m_util.mk_numeral(rational(1), m_util.is_int(d)); | ||||
|         return true; | ||||
|     } | ||||
|     if (m_util.is_mul(n)) { | ||||
|         expr_ref_vector muls(m()); | ||||
|         muls.push_back(n); | ||||
|         expr* n1, *n2; | ||||
|         rational r1, r2; | ||||
|         for (unsigned i = 0; i < muls.size(); ++i) { | ||||
|             if (m_util.is_mul(muls[i].get(), n1, n2)) { | ||||
|                 muls[i] = n1; | ||||
|                 muls.push_back(n2); | ||||
|                 --i; | ||||
|             } | ||||
|         } | ||||
|         if (m_util.is_numeral(d, r1) && !r1.is_zero()) { | ||||
|             for (unsigned i = 0; i < muls.size(); ++i) { | ||||
|                 if (m_util.is_numeral(muls[i].get(), r2) && (r2 / r1).is_int()) { | ||||
|                     muls[i] = m_util.mk_numeral(r2 / r1, m_util.is_int(d)); | ||||
|                     quot = m_util.mk_mul(muls.size(), muls.c_ptr()); | ||||
|                     return true; | ||||
|                 }             | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             for (unsigned i = 0; i < muls.size(); ++i) { | ||||
|                 if (d == muls[i].get()) { | ||||
|                     muls[i] = muls.back(); | ||||
|                     muls.pop_back(); | ||||
|                     quot = m_util.mk_mul(muls.size(), muls.c_ptr()); | ||||
|                     return true; | ||||
|                 }             | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| br_status arith_rewriter::mk_mod_core(expr * arg1, expr * arg2, expr_ref & result) { | ||||
|     set_curr_sort(m().get_sort(arg1)); | ||||
|     numeral v1, v2; | ||||
|  |  | |||
|  | @ -95,7 +95,6 @@ class arith_rewriter : public poly_rewriter<arith_rewriter_core> { | |||
|     expr_ref neg_monomial(expr * e) const; | ||||
|     expr * mk_sin_value(rational const & k); | ||||
|     app * mk_sqrt(rational const & k); | ||||
|     bool divides(expr* d, expr* n, expr_ref& quot); | ||||
| 
 | ||||
| public: | ||||
|     arith_rewriter(ast_manager & m, params_ref const & p = params_ref()): | ||||
|  |  | |||
|  | @ -19,16 +19,17 @@ Notes: | |||
| #ifndef POLYNOMIAL_H_ | ||||
| #define POLYNOMIAL_H_ | ||||
| 
 | ||||
| #include"util/mpz.h" | ||||
| #include"util/rational.h" | ||||
| #include"util/obj_ref.h" | ||||
| #include"util/ref_vector.h" | ||||
| #include"util/z3_exception.h" | ||||
| #include"util/scoped_numeral.h" | ||||
| #include"util/scoped_numeral_vector.h" | ||||
| #include"util/params.h" | ||||
| #include"util/mpbqi.h" | ||||
| #include"util/rlimit.h" | ||||
| #include "util/mpz.h" | ||||
| #include "util/rational.h" | ||||
| #include "util/obj_ref.h" | ||||
| #include "util/ref_vector.h" | ||||
| #include "util/z3_exception.h" | ||||
| #include "util/scoped_numeral.h" | ||||
| #include "util/scoped_numeral_vector.h" | ||||
| #include "util/params.h" | ||||
| #include "util/mpbqi.h" | ||||
| #include "util/rlimit.h" | ||||
| #include "util/lbool.h" | ||||
| 
 | ||||
| class small_object_allocator; | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,10 +21,10 @@ Revision History: | |||
| #ifndef NLSAT_SOLVER_H_ | ||||
| #define NLSAT_SOLVER_H_ | ||||
| 
 | ||||
| #include"nlsat/nlsat_types.h" | ||||
| #include"util/params.h" | ||||
| #include"util/statistics.h" | ||||
| #include"util/rlimit.h" | ||||
| #include "nlsat/nlsat_types.h" | ||||
| #include "util/params.h" | ||||
| #include "util/statistics.h" | ||||
| #include "util/rlimit.h" | ||||
| 
 | ||||
| namespace nlsat { | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,10 +19,10 @@ Revision History: | |||
| #ifndef NLSAT_TYPES_H_ | ||||
| #define NLSAT_TYPES_H_ | ||||
| 
 | ||||
| #include"math/polynomial/polynomial.h" | ||||
| #include"util/buffer.h" | ||||
| #include"sat/sat_types.h" | ||||
| #include"util/z3_exception.h" | ||||
| #include "math/polynomial/polynomial.h" | ||||
| #include "util/buffer.h" | ||||
| #include "sat/sat_types.h" | ||||
| #include "util/z3_exception.h" | ||||
| 
 | ||||
| namespace algebraic_numbers { | ||||
|     class anum; | ||||
|  |  | |||
|  | @ -19,12 +19,12 @@ Revision History: | |||
| #ifndef SAT_TYPES_H_ | ||||
| #define SAT_TYPES_H_ | ||||
| 
 | ||||
| #include"util/debug.h" | ||||
| #include"util/approx_set.h" | ||||
| #include"util/lbool.h" | ||||
| #include"util/z3_exception.h" | ||||
| #include"util/common_msgs.h" | ||||
| #include"util/vector.h" | ||||
| #include "util/debug.h" | ||||
| #include "util/approx_set.h" | ||||
| #include "util/lbool.h" | ||||
| #include "util/z3_exception.h" | ||||
| #include "util/common_msgs.h" | ||||
| #include "util/vector.h" | ||||
| #include<iomanip> | ||||
| 
 | ||||
| namespace sat { | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ Author: | |||
| #include "util/gparams.h" | ||||
| #include <signal.h> | ||||
| 
 | ||||
| static lp::lp_solver<double, double>* g_solver = 0; | ||||
| static lp::lp_solver<double, double>* g_solver = nullptr; | ||||
| 
 | ||||
| static void display_statistics() { | ||||
|     if (g_solver && g_solver->settings().print_statistics) { | ||||
|  | @ -80,7 +80,8 @@ void run_solver(lp_params & params, char const * mps_file_name) { | |||
|     solver->settings().set_message_ostream(&std::cout); | ||||
|     solver->settings().report_frequency = params.rep_freq(); | ||||
|     solver->settings().print_statistics = params.print_stats(); | ||||
|     solver->settings().simplex_strategy() = lp::simplex_strategy_enum::lu; | ||||
|     solver->settings().simplex_strategy() = lp:: simplex_strategy_enum::lu; | ||||
| 
 | ||||
|     solver->find_maximal_solution(); | ||||
| 
 | ||||
|     *(solver->settings().get_message_ostream()) << "status is " << lp_status_to_string(solver->get_status()) << std::endl; | ||||
|  |  | |||
|  | @ -296,6 +296,9 @@ void parse_cmd_line_args(int argc, char ** argv) { | |||
| 
 | ||||
| int STD_CALL main(int argc, char ** argv) { | ||||
|     try{ | ||||
|         DEBUG_CODE( for (int i = 0; i < argc; i++) | ||||
|                         std::cout << argv[i] << " "; | ||||
|                     std::cout << std::endl;); | ||||
|         unsigned return_value = 0; | ||||
|         memory::initialize(0); | ||||
|         memory::exit_when_out_of_memory(true, "ERROR: out of memory"); | ||||
|  |  | |||
|  | @ -979,7 +979,7 @@ namespace smt { | |||
|         if (st.num_theories() == 2 && st.has_uf() && is_arith(st)) { | ||||
|             if (!st.m_has_real) | ||||
|                 setup_QF_UFLIA(st); | ||||
|             else if (!st.m_has_int && st.m_num_non_linear == 0) | ||||
|             else if (!st.m_has_int) | ||||
|                 setup_QF_UFLRA(); | ||||
|             else | ||||
|                 setup_unknown(); | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -11074,8 +11074,8 @@ namespace smt { | |||
|                 ctx.force_phase(lit); | ||||
|             } | ||||
| 
 | ||||
| 			zstring aStr = gen_val_string(len, options[static_cast<int>(i) - static_cast<int>(l)]); | ||||
| 			expr * strAst; | ||||
|             zstring aStr = gen_val_string(len, options[i - l]); | ||||
|             expr * strAst; | ||||
|             if (m_params.m_UseFastValueTesterCache) { | ||||
|                 if (!valueTesterCache.find(aStr, strAst)) { | ||||
|                     strAst = mk_string(aStr); | ||||
|  |  | |||
|  | @ -211,17 +211,35 @@ tactic * mk_qflia_tactic(ast_manager & m, params_ref const & p) { | |||
|      | ||||
|     params_ref no_cut_p; | ||||
|     no_cut_p.set_uint("arith.branch_cut_ratio", 10000000); | ||||
|      | ||||
|      | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     tactic * st = using_params(and_then(preamble_st, | ||||
| #if 0 | ||||
|                                         mk_smt_tactic()), | ||||
| #else | ||||
|                                         or_else(mk_ilp_model_finder_tactic(m), | ||||
|                                                 mk_pb_tactic(m), | ||||
|                                                 and_then(fail_if_not(mk_is_quasi_pb_probe()),  | ||||
|                                                          using_params(mk_lia2sat_tactic(m), quasi_pb_p), | ||||
|                                                          mk_fail_if_undecided_tactic()), | ||||
|                                                 mk_bounded_tactic(m), | ||||
|                                                 mk_psmt_tactic(m, p))), | ||||
|                                                 mk_smt_tactic())), | ||||
| #endif | ||||
|                                main_p); | ||||
| 
 | ||||
|     //
 | ||||
|      | ||||
|      | ||||
|     // tactic * st = using_params(and_then(preamble_st,
 | ||||
|     //                                     or_else(mk_ilp_model_finder_tactic(m),
 | ||||
|     //                                             mk_pb_tactic(m),
 | ||||
|     //                                             and_then(fail_if_not(mk_is_quasi_pb_probe()), 
 | ||||
|     //                                                      using_params(mk_lia2sat_tactic(m), quasi_pb_p),
 | ||||
|     //                                                      mk_fail_if_undecided_tactic()),
 | ||||
|     //                                             mk_bounded_tactic(m),
 | ||||
|     //                                             mk_smt_tactic())),
 | ||||
|     //                            main_p);
 | ||||
|      | ||||
|     st->updt_params(p); | ||||
|     return st; | ||||
|  |  | |||
|  | @ -35,10 +35,10 @@ Revision History: | |||
| #include "util/lp/lp_utils.h" | ||||
| #include "util/lp/lp_primal_simplex.h" | ||||
| #include "util/lp/mps_reader.h" | ||||
| #include "test/smt_reader.h" | ||||
| #include "test/lp/smt_reader.h" | ||||
| #include "util/lp/binary_heap_priority_queue.h" | ||||
| #include "test/argument_parser.h" | ||||
| #include "test/test_file_reader.h" | ||||
| #include "test/lp/argument_parser.h" | ||||
| #include "test/lp/test_file_reader.h" | ||||
| #include "util/lp/indexed_value.h" | ||||
| #include "util/lp/lar_solver.h" | ||||
| #include "util/lp/numeric_pair.h" | ||||
|  | @ -550,7 +550,7 @@ void test_lp_0() { | |||
|     costs[5] = 0; | ||||
|     costs[6] = 0; | ||||
|      | ||||
|     vector<column_type> column_types(7, column_type::low_bound); | ||||
|     vector<column_type> column_types(7, column_type::lower_bound); | ||||
|     vector<double>  upper_bound_values; | ||||
|     lp_settings settings; | ||||
|     simple_column_namer cn; | ||||
|  | @ -596,7 +596,7 @@ void test_lp_1() { | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     vector<column_type> column_types(7, column_type::low_bound); | ||||
|     vector<column_type> column_types(7, column_type::lower_bound); | ||||
|     vector<double>  upper_bound_values; | ||||
| 
 | ||||
|     std::cout << "calling lp\n"; | ||||
|  | @ -1750,7 +1750,7 @@ void solve_rational() { | |||
| 
 | ||||
|     int bounds[] = {8, 6, 4, 15, 2, 10, 10, 3}; | ||||
|     for (unsigned i = 0; i < 8; i++) { | ||||
|         solver.set_low_bound(i, lp::mpq(0)); | ||||
|         solver.set_lower_bound(i, lp::mpq(0)); | ||||
|         solver.set_upper_bound(i, lp::mpq(bounds[i])); | ||||
|     } | ||||
| 
 | ||||
|  | @ -1883,8 +1883,7 @@ void test_replace_column() { | |||
| 
 | ||||
| 
 | ||||
| void setup_args_parser(argument_parser & parser) { | ||||
|     parser.add_option_with_help_string("-dji", "test integer_domain"); | ||||
|     parser.add_option_with_help_string("-cs", "test cut_solver"); | ||||
|     parser.add_option_with_help_string("-intd", "test integer_domain"); | ||||
|     parser.add_option_with_help_string("-xyz_sample", "run a small interactive scenario"); | ||||
|     parser.add_option_with_after_string_with_help("--density", "the percentage of non-zeroes in the matrix below which it is not dense"); | ||||
|     parser.add_option_with_after_string_with_help("--harris_toler", "harris tolerance"); | ||||
|  | @ -2782,7 +2781,7 @@ void test_bound_propagation_one_small_sample1() { | |||
|       got to get a <= c | ||||
|     */ | ||||
|     std::function<bool (unsigned, bool, bool, const mpq & )> bound_is_relevant = | ||||
|         [&](unsigned j, bool is_low_bound, bool strict, const rational& bound_val) { | ||||
|         [&](unsigned j, bool is_lower_bound, bool strict, const rational& bound_val) { | ||||
|         return true;  | ||||
|     };    | ||||
|     lar_solver ls; | ||||
|  | @ -2807,7 +2806,7 @@ void test_bound_propagation_one_small_sample1() { | |||
|     vector<implied_bound> ev; | ||||
|     ls.add_var_bound(a, LE, mpq(1)); | ||||
|     ls.solve(); | ||||
|     lp_bound_propagator bp(ls); | ||||
|     bound_propagator bp(ls); | ||||
|     ls.propagate_bounds_for_touched_rows(bp); | ||||
|     std::cout << " bound ev from test_bound_propagation_one_small_sample1" << std::endl; | ||||
|     for (auto & be : bp.m_ibounds)  { | ||||
|  | @ -2860,7 +2859,7 @@ void test_bound_propagation_one_row() { | |||
|     vector<implied_bound> ev; | ||||
|     ls.add_var_bound(x0, LE, mpq(1)); | ||||
|     ls.solve(); | ||||
|     lp_bound_propagator bp(ls); | ||||
|     bound_propagator bp(ls); | ||||
|     ls.propagate_bounds_for_touched_rows(bp); | ||||
| }  | ||||
| void test_bound_propagation_one_row_with_bounded_vars() { | ||||
|  | @ -2876,7 +2875,7 @@ void test_bound_propagation_one_row_with_bounded_vars() { | |||
|     ls.add_var_bound(x0, LE, mpq(3)); | ||||
|     ls.add_var_bound(x0, LE, mpq(1)); | ||||
|     ls.solve(); | ||||
|     lp_bound_propagator bp(ls); | ||||
|     bound_propagator bp(ls); | ||||
|     ls.propagate_bounds_for_touched_rows(bp); | ||||
| } | ||||
| void test_bound_propagation_one_row_mixed() { | ||||
|  | @ -2890,7 +2889,7 @@ void test_bound_propagation_one_row_mixed() { | |||
|     vector<implied_bound> ev; | ||||
|     ls.add_var_bound(x1, LE, mpq(1)); | ||||
|     ls.solve(); | ||||
|     lp_bound_propagator bp(ls); | ||||
|     bound_propagator bp(ls); | ||||
|     ls.propagate_bounds_for_touched_rows(bp); | ||||
| }  | ||||
| 
 | ||||
|  | @ -2913,7 +2912,7 @@ void test_bound_propagation_two_rows() { | |||
|     vector<implied_bound> ev; | ||||
|     ls.add_var_bound(y, LE, mpq(1)); | ||||
|     ls.solve(); | ||||
|     lp_bound_propagator bp(ls); | ||||
|     bound_propagator bp(ls); | ||||
|     ls.propagate_bounds_for_touched_rows(bp); | ||||
| }  | ||||
| 
 | ||||
|  | @ -2933,7 +2932,7 @@ void test_total_case_u() { | |||
|     vector<implied_bound> ev; | ||||
|     ls.add_var_bound(z, GE, zero_of_type<mpq>()); | ||||
|     ls.solve(); | ||||
|     lp_bound_propagator bp(ls); | ||||
|     bound_propagator bp(ls); | ||||
|     ls.propagate_bounds_for_touched_rows(bp); | ||||
| } | ||||
| bool contains_j_kind(unsigned j, lconstraint_kind kind, const mpq & rs, const vector<implied_bound> & ev) { | ||||
|  | @ -2960,7 +2959,7 @@ void test_total_case_l(){ | |||
|     vector<implied_bound> ev; | ||||
|     ls.add_var_bound(z, LE, zero_of_type<mpq>()); | ||||
|     ls.solve(); | ||||
|     lp_bound_propagator bp(ls); | ||||
|     bound_propagator bp(ls); | ||||
|     ls.propagate_bounds_for_touched_rows(bp); | ||||
|     lp_assert(ev.size() == 4); | ||||
|     lp_assert(contains_j_kind(x, GE, - one_of_type<mpq>(), ev)); | ||||
|  | @ -3113,17 +3112,17 @@ void get_random_interval(bool& neg_inf, bool& pos_inf, int& x, int &y) { | |||
| } | ||||
| 
 | ||||
| void test_integer_domain_intersection(integer_domain<int> & d) { | ||||
|     int x, y; bool neg_inf, pos_inf; | ||||
|     get_random_interval(neg_inf, pos_inf, x, y); | ||||
|     if (neg_inf) { | ||||
|         if (!pos_inf) { | ||||
|             d.intersect_with_upper_bound(y); | ||||
|         } | ||||
|     } | ||||
|     else if (pos_inf) | ||||
|         d.intersect_with_lower_bound(x); | ||||
|     else  | ||||
|         d.intersect_with_interval(x, y); | ||||
|     // int x, y; bool neg_inf, pos_inf;
 | ||||
|     // get_random_interval(neg_inf, pos_inf, x, y);
 | ||||
|     // if (neg_inf) {
 | ||||
|     //     if (!pos_inf) {
 | ||||
|     //         d.intersect_with_upper_bound(y);
 | ||||
|     //     }
 | ||||
|     // }
 | ||||
|     // else if (pos_inf)
 | ||||
|     //     d.intersect_with_lower_bound(x);
 | ||||
|     // else 
 | ||||
|     //     d.intersect_with_interval(x, y);
 | ||||
| } | ||||
| 
 | ||||
| void test_integer_domain_union(integer_domain<int> & d) { | ||||
|  | @ -3154,66 +3153,108 @@ void test_integer_domain_randomly(integer_domain<int> & d) { | |||
| } | ||||
| 
 | ||||
| void test_integer_domain() { | ||||
|     integer_domain<int> d; | ||||
|     vector<integer_domain<int>> stack; | ||||
|     for (int i = 0; i < 10000; i++) { | ||||
|         test_integer_domain_randomly(d); | ||||
|         stack.push_back(d); | ||||
|         d.push(); | ||||
|         if (i > 0 && i%100 == 0) { | ||||
|             if (stack.size() == 0) continue; | ||||
|             unsigned k = my_random() % stack.size(); | ||||
|             if (k == 0) | ||||
|                 k = 1; | ||||
|             d.pop(k); | ||||
|             d.restore_domain(); | ||||
|             for (unsigned j = 0; j + 1 < k; j++) { | ||||
|                 stack.pop_back(); | ||||
|             } | ||||
|             std::cout<<"comparing i = " << i << std::endl; | ||||
|             lp_assert(d ==  *stack.rbegin()); | ||||
|             stack.pop_back(); | ||||
|         } | ||||
|         //d.print(std::cout);
 | ||||
|     } | ||||
|     std::cout << "test_integer_domain\n"; | ||||
|     unsigned e0 = 0; | ||||
|     unsigned e1 = 1; | ||||
|     unsigned e2 = 2; | ||||
|     unsigned e3 = 3; // these are explanations
 | ||||
|     unsigned e4 = 4; | ||||
|     unsigned e5 = 5; | ||||
|     integer_domain<unsigned> d; | ||||
|     unsigned l0 = 0, l1 = 1, l2 = 3; | ||||
|     unsigned u0 = 10, u1 = 9, u2 = 8; | ||||
|     d.push(); | ||||
|     d.intersect_with_lower_bound(l0, e0); | ||||
|     unsigned b; | ||||
|     unsigned e; | ||||
|     bool r = d.get_lower_bound_with_expl(b, e); | ||||
|     lp_assert(r && b == l0 && e == e0); | ||||
|     d.push(); | ||||
|     d.intersect_with_upper_bound(u0, e1); | ||||
|     r = d.get_upper_bound_with_expl(b, e); | ||||
|     lp_assert(r && b == u0 && e == e1); | ||||
|     r = d.get_lower_bound_with_expl(b, e); | ||||
|     lp_assert(r && b == l0 && e == e0); | ||||
|     d.pop(); | ||||
|     r = d.get_upper_bound_with_expl(b, e); | ||||
|     lp_assert(!r); | ||||
|     d.intersect_with_upper_bound(u0, e1); | ||||
|     d.push(); | ||||
|     d.intersect_with_lower_bound(l1, e2); | ||||
|     d.intersect_with_upper_bound(u1, e3); | ||||
|     d.push(); | ||||
|     d.intersect_with_lower_bound(l2, e4); | ||||
|     d.intersect_with_upper_bound(u2, e5); | ||||
|     lp_assert(d.is_empty() == false); | ||||
|     d.print(std::cout); | ||||
|     d.pop(); | ||||
|     r = d.get_lower_bound_with_expl(b, e); | ||||
|     lp_assert(r && b == l1 && e == e2); | ||||
|     d.print(std::cout); | ||||
|     d.pop(2); | ||||
|     d.print(std::cout); | ||||
|     lp_assert(d.has_neg_inf() && d.has_pos_inf()); | ||||
|     // integer_domain<int> d;
 | ||||
|     // std::vector<integer_domain<int>> stack;
 | ||||
|     // for (int i = 0; i < 10000; i++) {
 | ||||
|     //     test_integer_domain_randomly(d);
 | ||||
|     //     stack.push_back(d);
 | ||||
|     //     d.push();
 | ||||
|     //     if (i > 0 && i%100 == 0) {
 | ||||
|     //         if (stack.size() == 0) continue;
 | ||||
|     //         unsigned k = my_random() % stack.size();
 | ||||
|     //         if (k == 0)
 | ||||
|     //             k = 1;
 | ||||
|     //         d.pop(k);
 | ||||
|     //         d.restore_domain();
 | ||||
|     //         for (unsigned j = 0; j + 1 < k; j++) {
 | ||||
|     //             stack.pop_back();
 | ||||
|     //         }
 | ||||
|     //         std::cout<<"comparing i = " << i << std::endl;
 | ||||
|     //         lp_assert(d ==  *stack.rbegin());
 | ||||
|     //         stack.pop_back();
 | ||||
|     //     }
 | ||||
|     //     //d.print(std::cout);
 | ||||
|     // }
 | ||||
| } | ||||
| 
 | ||||
| void test_cut_solver() { | ||||
|     cut_solver<int> cs([](unsigned i) | ||||
|                        { | ||||
|                            if (i == 0) return std::string("x"); | ||||
|                            if (i == 1) return  std::string("y"); | ||||
|                            return std::to_string(i); | ||||
|                        }); | ||||
|     vector<std::pair<int, unsigned>> term; | ||||
|     unsigned x = 0; | ||||
|     unsigned y = 1; | ||||
|     term.push_back(std::make_pair(2, x)); | ||||
|     term.push_back(std::make_pair(-3, y)); | ||||
|     unsigned ineq_index = cs.add_ineq(term, mpq(3)); | ||||
| 
 | ||||
| 
 | ||||
|     cs.print_ineq(ineq_index, std::cout); | ||||
| void test_resolve_with_tight_constraint(cut_solver& cs, | ||||
|                                         lp::cut_solver::polynomial&i , | ||||
|                                         unsigned int j, | ||||
|                                         cut_solver::polynomial& ti) { | ||||
|      | ||||
|     mpq l; | ||||
|     auto ineq = cs.m_ineqs[ineq_index]; | ||||
|     cs.add_lower_bound_for_user_var(x, 1); | ||||
|     cs.add_lower_bound_for_user_var(y, 1); | ||||
|     bool has_lower = cs.lower(ineq.m_poly, l); | ||||
|     if (has_lower) { | ||||
|         std::cout << "lower = " << l << std::endl; | ||||
|     } else { | ||||
|         std::cout << "no lower" << std::endl; | ||||
|     } | ||||
|     cs.add_upper_bound_for_user_var(y, 1); | ||||
|     has_lower = cs.lower(ineq.m_poly, l); | ||||
|     if (has_lower) { | ||||
|         std::cout << "lower = " << l << std::endl; | ||||
|     } else { | ||||
|         std::cout << "no lower" << std::endl; | ||||
|     } | ||||
|     // std::cout << "resolve constraint ";
 | ||||
|     // cs.print_polynomial(std::cout, i);
 | ||||
|     // std::cout << " for " << cs.get_column_name(j) << " by using poly ";
 | ||||
|     // cs.print_polynomial(std::cout, ti);
 | ||||
|     // std::cout << std::endl;
 | ||||
|     // bool j_coeff_is_one = ti.coeff(j) == 1;
 | ||||
|     // cut_solver::polynomial result;
 | ||||
|     // cs.resolve(i, j,  j_coeff_is_one, ti);
 | ||||
|     // std::cout << "resolve result is ";
 | ||||
|     // cs.print_polynomial(std::cout, i);
 | ||||
|     // std::cout << std::endl;
 | ||||
| } | ||||
| 
 | ||||
| typedef cut_solver::monomial mono; | ||||
| 
 | ||||
| void test_resolve(cut_solver& cs, unsigned constraint_index, unsigned i0)  { | ||||
|     var_index x = 0; | ||||
|     var_index y = 1; | ||||
|     var_index z = 2; | ||||
|     std::cout << "test_resolve\n"; | ||||
|      | ||||
|     cut_solver::polynomial i; i += mono(2, x);i += mono(-3,y); | ||||
|     i+= mono(4, z); | ||||
|     i.m_a = 5; | ||||
|     cut_solver::polynomial ti; ti += mono(1, x); ti+= mono(1,y);ti.m_a = 3; | ||||
|     test_resolve_with_tight_constraint(cs, i, x, ti); | ||||
|     test_resolve_with_tight_constraint(cs, i, y ,ti); | ||||
|  } | ||||
| 
 | ||||
| 
 | ||||
| void test_lp_local(int argn, char**argv) { | ||||
|      | ||||
|     // initialize_util_module();
 | ||||
|  | @ -3230,14 +3271,11 @@ void test_lp_local(int argn, char**argv) { | |||
| 
 | ||||
|     args_parser.print(); | ||||
| 
 | ||||
|     if (args_parser.option_is_used("-dji")) { | ||||
|     if (args_parser.option_is_used("-intd")) { | ||||
|         test_integer_domain(); | ||||
|         return finalize(0); | ||||
|     } | ||||
|     if (args_parser.option_is_used("-cs")) { | ||||
|         test_cut_solver(); | ||||
|         return finalize(0); | ||||
|     } | ||||
| 
 | ||||
|     if (args_parser.option_is_used("--test_mpq")) { | ||||
|         test_rationals(); | ||||
|         return finalize(0); | ||||
|  |  | |||
|  | @ -1,35 +1,35 @@ | |||
| z3_add_component(lp | ||||
|   SOURCES | ||||
|     lp_utils.cpp | ||||
|     binary_heap_priority_queue_instances.cpp | ||||
|     binary_heap_upair_queue_instances.cpp | ||||
|     binary_heap_priority_queue.cpp | ||||
|     binary_heap_upair_queue.cpp | ||||
|     bound_propagator.cpp | ||||
|     cut_solver.cpp | ||||
|     core_solver_pretty_printer_instances.cpp | ||||
|     dense_matrix_instances.cpp | ||||
|     eta_matrix_instances.cpp | ||||
|     indexed_vector_instances.cpp | ||||
|     core_solver_pretty_printer.cpp | ||||
|     dense_matrix.cpp | ||||
|     eta_matrix.cpp | ||||
|     indexed_vector.cpp | ||||
|     int_solver.cpp | ||||
|     lar_solver_instances.cpp | ||||
|     lar_core_solver_instances.cpp | ||||
|     lp_core_solver_base_instances.cpp | ||||
|     lp_dual_core_solver_instances.cpp | ||||
|     lp_dual_simplex_instances.cpp | ||||
|     lp_primal_core_solver_instances.cpp | ||||
|     lp_primal_simplex_instances.cpp | ||||
|     lp_settings_instances.cpp | ||||
|     lp_solver_instances.cpp | ||||
|     lu_instances.cpp | ||||
|     matrix_instances.cpp | ||||
|     lar_solver.cpp | ||||
|     lar_core_solver.cpp | ||||
|     lp_core_solver_base.cpp | ||||
|     lp_dual_core_solver.cpp | ||||
|     lp_dual_simplex.cpp | ||||
|     lp_primal_core_solver.cpp | ||||
|     lp_primal_simplex.cpp | ||||
|     lp_settings.cpp | ||||
|     lp_solver.cpp | ||||
|     lu.cpp | ||||
|     matrix.cpp | ||||
|     nra_solver.cpp | ||||
|     permutation_matrix_instances.cpp | ||||
|     permutation_matrix.cpp | ||||
|     quick_xplain.cpp | ||||
|     row_eta_matrix_instances.cpp | ||||
|     scaler_instances.cpp | ||||
|     sparse_matrix_instances.cpp | ||||
|     square_dense_submatrix_instances.cpp | ||||
|     static_matrix_instances.cpp | ||||
|     random_updater_instances.cpp       | ||||
|     row_eta_matrix.cpp | ||||
|     scaler.cpp | ||||
|     sparse_matrix.cpp | ||||
|     square_dense_submatrix.cpp | ||||
|     static_matrix.cpp | ||||
|     random_updater.cpp       | ||||
|   COMPONENT_DEPENDENCIES | ||||
|     util | ||||
|     polynomial | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ Revision History: | |||
| 
 | ||||
| --*/ | ||||
| #include "util/lp/numeric_pair.h" | ||||
| #include "util/lp/binary_heap_priority_queue.hpp" | ||||
| #include "util/lp/binary_heap_priority_queue_def.h" | ||||
| namespace lp { | ||||
| template binary_heap_priority_queue<int>::binary_heap_priority_queue(unsigned int); | ||||
| template unsigned binary_heap_priority_queue<int>::dequeue(); | ||||
|  | @ -17,7 +17,7 @@ Revision History: | |||
| 
 | ||||
| 
 | ||||
| --*/ | ||||
| #include "util/lp/binary_heap_upair_queue.hpp" | ||||
| #include "util/lp/binary_heap_upair_queue_def.h" | ||||
| namespace lp { | ||||
| template binary_heap_upair_queue<int>::binary_heap_upair_queue(unsigned int); | ||||
| template binary_heap_upair_queue<unsigned int>::binary_heap_upair_queue(unsigned int); | ||||
|  | @ -20,10 +20,9 @@ Revision History: | |||
| #pragma once | ||||
| #include "util/vector.h" | ||||
| #include "util/lp/linear_combination_iterator.h" | ||||
| #include "util/lp/implied_bound.h" | ||||
| #include "util/lp/test_bound_analyzer.h" | ||||
| #include <functional> | ||||
| #include "util/lp/lp_bound_propagator.h" | ||||
| #include "implied_bound.h" | ||||
| #include "test_bound_analyzer.h" | ||||
| #include "util/lp/bound_propagator.h" | ||||
| // We have an equality : sum by j of row[j]*x[j] = rs
 | ||||
| // We try to pin a var by pushing the total by using the variable bounds
 | ||||
| // In a loop we drive the partial sum down, denoting the variables of this process by _u.
 | ||||
|  | @ -31,22 +30,22 @@ Revision History: | |||
| namespace lp { | ||||
| 
 | ||||
| class bound_analyzer_on_row { | ||||
| 
 | ||||
|      | ||||
|     linear_combination_iterator<mpq> & m_it; | ||||
|     lp_bound_propagator &                 m_bp; | ||||
|     bound_propagator &                 m_bp; | ||||
|     unsigned           m_row_or_term_index; | ||||
|     int                m_column_of_u; // index of an unlimited from above monoid
 | ||||
|                                // -1 means that such a value is not found, -2 means that at least two of such monoids were found
 | ||||
|     // -1 means that such a value is not found, -2 means that at least two of such monoids were found
 | ||||
|     int                m_column_of_l; // index of an unlimited from below monoid
 | ||||
|     impq               m_rs; | ||||
| 
 | ||||
| public : | ||||
|     // constructor
 | ||||
|     bound_analyzer_on_row( | ||||
|                           linear_combination_iterator<mpq> &it, | ||||
|                           const numeric_pair<mpq>& rs, | ||||
|                           unsigned row_or_term_index, | ||||
|                           lp_bound_propagator & bp | ||||
|         linear_combination_iterator<mpq> &it, | ||||
|         const numeric_pair<mpq>& rs, | ||||
|         unsigned row_or_term_index, | ||||
|         bound_propagator & bp | ||||
|                           ) | ||||
|         : | ||||
|         m_it(it), | ||||
|  | @ -60,7 +59,7 @@ public : | |||
| 
 | ||||
|     unsigned j; | ||||
|     void analyze() { | ||||
| 
 | ||||
|          | ||||
|         mpq a; unsigned j; | ||||
|         while (((m_column_of_l != -2) || (m_column_of_u != -2)) && m_it.next(a, j)) | ||||
|             analyze_bound_on_var_on_coeff(j, a); | ||||
|  | @ -76,33 +75,33 @@ public : | |||
|             limit_all_monoids_from_above(); | ||||
|     } | ||||
| 
 | ||||
|     bool bound_is_available(unsigned j, bool low_bound) { | ||||
|         return (low_bound && low_bound_is_available(j)) || | ||||
|             (!low_bound && upper_bound_is_available(j)); | ||||
|     bool bound_is_available(unsigned j, bool lower_bound) { | ||||
|         return (lower_bound && lower_bound_is_available(j)) || | ||||
|             (!lower_bound && upper_bound_is_available(j)); | ||||
|     } | ||||
| 
 | ||||
|     bool upper_bound_is_available(unsigned j) const { | ||||
|         switch (m_bp.get_column_type(j)) | ||||
|         { | ||||
|         case column_type::fixed: | ||||
|         case column_type::boxed: | ||||
|         case column_type::upper_bound: | ||||
|             return true; | ||||
|         default: | ||||
|             return false; | ||||
|         } | ||||
|             { | ||||
|             case column_type::fixed: | ||||
|             case column_type::boxed: | ||||
|             case column_type::upper_bound: | ||||
|                 return true; | ||||
|             default: | ||||
|                 return false; | ||||
|             } | ||||
|     } | ||||
| 
 | ||||
|     bool low_bound_is_available(unsigned j) const { | ||||
|     bool lower_bound_is_available(unsigned j) const { | ||||
|         switch (m_bp.get_column_type(j)) | ||||
|         { | ||||
|         case column_type::fixed: | ||||
|         case column_type::boxed: | ||||
|         case column_type::low_bound: | ||||
|             return true; | ||||
|         default: | ||||
|             return false; | ||||
|         } | ||||
|             { | ||||
|             case column_type::fixed: | ||||
|             case column_type::boxed: | ||||
|             case column_type::lower_bound: | ||||
|                 return true; | ||||
|             default: | ||||
|                 return false; | ||||
|             } | ||||
|     } | ||||
| 
 | ||||
|     const impq & ub(unsigned j) const { | ||||
|  | @ -110,8 +109,8 @@ public : | |||
|         return m_bp.get_upper_bound(j); | ||||
|     } | ||||
|     const impq & lb(unsigned j) const { | ||||
|         lp_assert(low_bound_is_available(j)); | ||||
|         return m_bp.get_low_bound(j); | ||||
|         lp_assert(lower_bound_is_available(j)); | ||||
|         return m_bp.get_lower_bound(j); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -151,7 +150,7 @@ public : | |||
|             strict = !is_zero(ub(j).y); | ||||
|             return a * ub(j).x; | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|         strict = !is_zero(lb(j).y); | ||||
|         return a * lb(j).x; | ||||
|     } | ||||
|  | @ -160,10 +159,10 @@ public : | |||
|         if (is_neg(a)) { | ||||
|             return a * ub(j).x; | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|         return a * lb(j).x; | ||||
|     } | ||||
| 
 | ||||
|      | ||||
| 
 | ||||
|     void limit_all_monoids_from_above() { | ||||
|         int strict = 0; | ||||
|  | @ -209,7 +208,7 @@ public : | |||
|             bool str; | ||||
|             bool a_is_pos = is_pos(a); | ||||
|             mpq bound = total / a + monoid_max_no_mult(a_is_pos, j, str); | ||||
|             bool astrict = strict - static_cast<int>(str) > 0; | ||||
|             bool astrict = strict - static_cast<int>(str) > 0;  | ||||
|             if (a_is_pos) { | ||||
|                 limit_j(j, bound, true, true, astrict); | ||||
|             } | ||||
|  | @ -219,7 +218,7 @@ public : | |||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|      | ||||
|     void limit_monoid_u_from_below() { | ||||
|         // we are going to limit from below the monoid m_column_of_u,
 | ||||
|         // every other monoid is impossible to limit from below
 | ||||
|  | @ -240,7 +239,7 @@ public : | |||
|         } | ||||
| 
 | ||||
|         bound /= u_coeff; | ||||
| 
 | ||||
|          | ||||
|         if (numeric_traits<impq>::is_pos(u_coeff)) { | ||||
|             limit_j(m_column_of_u, bound, true, true, strict); | ||||
|         } else { | ||||
|  | @ -275,51 +274,51 @@ public : | |||
|             limit_j(m_column_of_l, bound, false, true, strict); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     // // it is the coefficent before the bounded column
 | ||||
|     // void provide_evidence(bool coeff_is_pos) {
 | ||||
|     //     /*
 | ||||
|     //     auto & be = m_ibounds.back();
 | ||||
|     //     bool low_bound = be.m_low_bound;
 | ||||
|     //     bool lower_bound = be.m_lower_bound;
 | ||||
|     //     if (!coeff_is_pos)
 | ||||
|     //         low_bound = !low_bound;
 | ||||
|     //         lower_bound = !lower_bound;
 | ||||
|     //     auto it = m_it.clone();
 | ||||
|     //     mpq a; unsigned j;
 | ||||
|     //     while (it->next(a, j)) {
 | ||||
|     //         if (be.m_j == j) continue;
 | ||||
|     //         lp_assert(bound_is_available(j, is_neg(a) ? low_bound : !low_bound));
 | ||||
|     //         lp_assert(bound_is_available(j, is_neg(a) ? lower_bound : !lower_bound));
 | ||||
|     //         be.m_vector_of_bound_signatures.emplace_back(a, j, numeric_traits<impq>::
 | ||||
|     //                                                      is_neg(a)? low_bound: !low_bound);
 | ||||
|     //                                                      is_neg(a)? lower_bound: !lower_bound);
 | ||||
|     //     }
 | ||||
|     //     delete it;
 | ||||
|     //     */
 | ||||
|     // }
 | ||||
| 
 | ||||
|     void limit_j(unsigned j, const mpq& u, bool coeff_before_j_is_pos, bool is_low_bound, bool strict){ | ||||
|         m_bp.try_add_bound(u, j, is_low_bound, coeff_before_j_is_pos, m_row_or_term_index, strict); | ||||
|     void limit_j(unsigned j, const mpq& u, bool coeff_before_j_is_pos, bool is_lower_bound, bool strict){ | ||||
|         m_bp.try_add_bound(u, j, is_lower_bound, coeff_before_j_is_pos, m_row_or_term_index, strict); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|      | ||||
|     void advance_u(unsigned j) { | ||||
|         if (m_column_of_u == -1) | ||||
|             m_column_of_u = j; | ||||
|         else | ||||
|             m_column_of_u = -2; | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     void advance_l(unsigned j) { | ||||
|         if (m_column_of_l == -1) | ||||
|             m_column_of_l = j; | ||||
|         else | ||||
|             m_column_of_l = -2; | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     void analyze_bound_on_var_on_coeff(int j, const mpq &a) { | ||||
|         switch (m_bp.get_column_type(j)) { | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             if (numeric_traits<mpq>::is_pos(a)) | ||||
|                 advance_u(j); | ||||
|             else | ||||
|             else  | ||||
|                 advance_l(j); | ||||
|             break; | ||||
|         case column_type::upper_bound: | ||||
|  | @ -340,7 +339,7 @@ public : | |||
|     static void analyze_row(linear_combination_iterator<mpq> &it, | ||||
|                             const numeric_pair<mpq>& rs, | ||||
|                             unsigned row_or_term_index, | ||||
|                             lp_bound_propagator & bp | ||||
|                             bound_propagator & bp | ||||
|                             ) { | ||||
|         bound_analyzer_on_row a(it, rs, row_or_term_index, bp); | ||||
|         a.analyze(); | ||||
|  |  | |||
|  | @ -9,8 +9,8 @@ bound_propagator::bound_propagator(lar_solver & ls): | |||
| column_type bound_propagator::get_column_type(unsigned j) const { | ||||
|     return m_lar_solver.m_mpq_lar_core_solver.m_column_types()[j]; | ||||
| } | ||||
| const impq & bound_propagator::get_low_bound(unsigned j) const { | ||||
|     return m_lar_solver.m_mpq_lar_core_solver.m_r_low_bounds()[j]; | ||||
| const impq & bound_propagator::get_lower_bound(unsigned j) const { | ||||
|     return m_lar_solver.m_mpq_lar_core_solver.m_r_lower_bounds()[j]; | ||||
| } | ||||
| const impq & bound_propagator::get_upper_bound(unsigned j) const { | ||||
|     return m_lar_solver.m_mpq_lar_core_solver.m_r_upper_bounds()[j]; | ||||
|  | @ -30,14 +30,14 @@ void bound_propagator::try_add_bound(mpq  v, unsigned j, bool is_low, bool coeff | |||
|         return; | ||||
|      unsigned k; // index to ibounds
 | ||||
|      if (is_low) { | ||||
|          if (try_get_value(m_improved_low_bounds, j, k)) { | ||||
|          if (try_get_value(m_improved_lower_bounds, j, k)) { | ||||
|              auto & found_bound = m_ibounds[k]; | ||||
|              if (v > found_bound.m_bound || (v == found_bound.m_bound && found_bound.m_strict == false && strict)) { | ||||
|                  found_bound = implied_bound(v, j, is_low, coeff_before_j_is_pos, row_or_term_index, strict); | ||||
|                  TRACE("try_add_bound", m_lar_solver.print_implied_bound(found_bound, tout);); | ||||
|              } | ||||
|          } else { | ||||
|              m_improved_low_bounds[j] = m_ibounds.size(); | ||||
|              m_improved_lower_bounds[j] = m_ibounds.size(); | ||||
|              m_ibounds.push_back(implied_bound(v, j, is_low, coeff_before_j_is_pos, row_or_term_index, strict)); | ||||
|              TRACE("try_add_bound", m_lar_solver.print_implied_bound(m_ibounds.back(), tout);); | ||||
|          } | ||||
|  |  | |||
							
								
								
									
										27
									
								
								src/util/lp/bound_propagator.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/util/lp/bound_propagator.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| /*
 | ||||
|   Copyright (c) 2017 Microsoft Corporation | ||||
|   Author: Lev Nachmanson | ||||
| */ | ||||
| #pragma once | ||||
| #include "util/lp/lp_settings.h" | ||||
| namespace lp { | ||||
| class lar_solver; | ||||
| class bound_propagator { | ||||
|     std::unordered_map<unsigned, unsigned> m_improved_lower_bounds; // these maps map a column index to the corresponding index in ibounds
 | ||||
|     std::unordered_map<unsigned, unsigned> m_improved_upper_bounds; | ||||
|     lar_solver & m_lar_solver; | ||||
| public: | ||||
|     vector<implied_bound> m_ibounds; | ||||
| public: | ||||
|     bound_propagator(lar_solver & ls); | ||||
|     column_type get_column_type(unsigned) const; | ||||
|     const impq & get_lower_bound(unsigned) const; | ||||
|     const impq & get_upper_bound(unsigned) const; | ||||
|     void try_add_bound(mpq  v, unsigned j, bool is_low, bool coeff_before_j_is_pos, unsigned row_or_term_index, bool strict); | ||||
|     virtual bool bound_is_interesting(unsigned vi, | ||||
|                                       lp::lconstraint_kind kind, | ||||
|                                       const rational & bval) {return true;} | ||||
|     unsigned number_of_found_bounds() const { return m_ibounds.size(); } | ||||
|     virtual void consume(mpq const& v, unsigned j) { std::cout << "doh\n"; } | ||||
| }; | ||||
| } | ||||
|  | @ -30,11 +30,11 @@ inline bool is_valid(unsigned j) { return static_cast<int>(j) >= 0;} | |||
| template <typename T> | ||||
| class column_info { | ||||
|     std::string m_name; | ||||
|     bool        m_low_bound_is_set; | ||||
|     bool        m_low_bound_is_strict; | ||||
|     bool        m_lower_bound_is_set; | ||||
|     bool        m_lower_bound_is_strict; | ||||
|     bool        m_upper_bound_is_set; | ||||
|     bool        m_upper_bound_is_strict; | ||||
|     T           m_low_bound; | ||||
|     T           m_lower_bound; | ||||
|     T           m_upper_bound; | ||||
|     T           m_fixed_value; | ||||
|     bool        m_is_fixed; | ||||
|  | @ -43,11 +43,11 @@ class column_info { | |||
| public: | ||||
|     bool operator==(const column_info & c) const { | ||||
|         return m_name == c.m_name && | ||||
|             m_low_bound_is_set == c.m_low_bound_is_set && | ||||
|             m_low_bound_is_strict == c.m_low_bound_is_strict && | ||||
|             m_lower_bound_is_set == c.m_lower_bound_is_set && | ||||
|             m_lower_bound_is_strict == c.m_lower_bound_is_strict && | ||||
|             m_upper_bound_is_set == c.m_upper_bound_is_set&& | ||||
|             m_upper_bound_is_strict == c.m_upper_bound_is_strict&& | ||||
|             (!m_low_bound_is_set || m_low_bound == c.m_low_bound) && | ||||
|             (!m_lower_bound_is_set || m_lower_bound == c.m_low_bound) && | ||||
|             (!m_upper_bound_is_set || m_upper_bound == c.m_upper_bound) && | ||||
|             m_cost == c.m_cost && | ||||
|             m_is_fixed == c.m_is_fixed && | ||||
|  | @ -60,8 +60,8 @@ public: | |||
|     } | ||||
|     // the default constructor
 | ||||
|     column_info(): | ||||
|         m_low_bound_is_set(false), | ||||
|         m_low_bound_is_strict(false), | ||||
|         m_lower_bound_is_set(false), | ||||
|         m_lower_bound_is_strict(false), | ||||
|         m_upper_bound_is_set (false), | ||||
|         m_upper_bound_is_strict (false), | ||||
|         m_is_fixed(false), | ||||
|  | @ -70,8 +70,8 @@ public: | |||
|     {} | ||||
|      | ||||
|     column_info(unsigned column_index) : | ||||
|         m_low_bound_is_set(false), | ||||
|         m_low_bound_is_strict(false), | ||||
|         m_lower_bound_is_set(false), | ||||
|         m_lower_bound_is_strict(false), | ||||
|         m_upper_bound_is_set (false), | ||||
|         m_upper_bound_is_strict (false), | ||||
|         m_is_fixed(false), | ||||
|  | @ -81,11 +81,11 @@ public: | |||
| 
 | ||||
|     column_info(const column_info & ci) { | ||||
|         m_name = ci.m_name; | ||||
|         m_low_bound_is_set = ci.m_low_bound_is_set; | ||||
|         m_low_bound_is_strict = ci.m_low_bound_is_strict; | ||||
|         m_lower_bound_is_set = ci.m_lower_bound_is_set; | ||||
|         m_lower_bound_is_strict = ci.m_lower_bound_is_strict; | ||||
|         m_upper_bound_is_set = ci.m_upper_bound_is_set; | ||||
|         m_upper_bound_is_strict = ci.m_upper_bound_is_strict; | ||||
|         m_low_bound = ci.m_low_bound; | ||||
|         m_lower_bound = ci.m_lower_bound; | ||||
|         m_upper_bound = ci.m_upper_bound; | ||||
|         m_cost = ci.m_cost; | ||||
|         m_fixed_value = ci.m_fixed_value; | ||||
|  | @ -98,7 +98,7 @@ public: | |||
|     } | ||||
| 
 | ||||
|     column_type get_column_type() const { | ||||
|         return m_is_fixed? column_type::fixed : (m_low_bound_is_set? (m_upper_bound_is_set? column_type::boxed : column_type::low_bound) : (m_upper_bound_is_set? column_type::upper_bound: column_type::free_column)); | ||||
|         return m_is_fixed? column_type::fixed : (m_lower_bound_is_set? (m_upper_bound_is_set? column_type::boxed : column_type::lower_bound) : (m_upper_bound_is_set? column_type::upper_bound: column_type::free_column)); | ||||
|     } | ||||
| 
 | ||||
|     column_type get_column_type_no_flipping() const { | ||||
|  | @ -106,25 +106,25 @@ public: | |||
|             return column_type::fixed; | ||||
|         } | ||||
| 
 | ||||
|         if (m_low_bound_is_set) { | ||||
|             return m_upper_bound_is_set? column_type::boxed: column_type::low_bound; | ||||
|         if (m_lower_bound_is_set) { | ||||
|             return m_upper_bound_is_set? column_type::boxed: column_type::lower_bound; | ||||
|         } | ||||
|         // we are flipping the bounds!
 | ||||
|         return m_upper_bound_is_set? column_type::upper_bound | ||||
|             : column_type::free_column; | ||||
|     } | ||||
| 
 | ||||
|     T get_low_bound() const { | ||||
|         lp_assert(m_low_bound_is_set); | ||||
|         return m_low_bound; | ||||
|     T get_lower_bound() const { | ||||
|         lp_assert(m_lower_bound_is_set); | ||||
|         return m_lower_bound; | ||||
|     } | ||||
|     T get_upper_bound() const { | ||||
|         lp_assert(m_upper_bound_is_set); | ||||
|         return m_upper_bound; | ||||
|     } | ||||
| 
 | ||||
|     bool low_bound_is_set() const { | ||||
|         return m_low_bound_is_set; | ||||
|     bool lower_bound_is_set() const { | ||||
|         return m_lower_bound_is_set; | ||||
|     } | ||||
| 
 | ||||
|     bool upper_bound_is_set() const { | ||||
|  | @ -138,23 +138,23 @@ public: | |||
|         if (is_flipped()){ | ||||
|             return m_upper_bound; | ||||
|         } | ||||
|         return m_low_bound_is_set? m_low_bound : numeric_traits<T>::zero(); | ||||
|         return m_lower_bound_is_set? m_lower_bound : numeric_traits<T>::zero(); | ||||
|     } | ||||
| 
 | ||||
|     bool is_flipped() { | ||||
|         return m_upper_bound_is_set && !m_low_bound_is_set; | ||||
|         return m_upper_bound_is_set && !m_lower_bound_is_set; | ||||
|     } | ||||
| 
 | ||||
|     bool adjusted_low_bound_is_set() { | ||||
|         return !is_flipped()? low_bound_is_set(): upper_bound_is_set(); | ||||
|     bool adjusted_lower_bound_is_set() { | ||||
|         return !is_flipped()? lower_bound_is_set(): upper_bound_is_set(); | ||||
|     } | ||||
| 
 | ||||
|     bool adjusted_upper_bound_is_set() { | ||||
|         return !is_flipped()? upper_bound_is_set(): low_bound_is_set(); | ||||
|         return !is_flipped()? upper_bound_is_set(): lower_bound_is_set(); | ||||
|     } | ||||
| 
 | ||||
|     T  get_adjusted_upper_bound() { | ||||
|         return get_upper_bound() - get_low_bound(); | ||||
|         return get_upper_bound() - get_lower_bound(); | ||||
|     } | ||||
| 
 | ||||
|     bool is_fixed() const { | ||||
|  | @ -162,7 +162,7 @@ public: | |||
|     } | ||||
| 
 | ||||
|     bool is_free() { | ||||
|         return !m_low_bound_is_set && !m_upper_bound_is_set; | ||||
|         return !m_lower_bound_is_set && !m_upper_bound_is_set; | ||||
|     } | ||||
| 
 | ||||
|     void set_fixed_value(T v) { | ||||
|  | @ -191,9 +191,9 @@ public: | |||
|         return m_name; | ||||
|     } | ||||
| 
 | ||||
|     void set_low_bound(T const & l) { | ||||
|         m_low_bound = l; | ||||
|         m_low_bound_is_set = true; | ||||
|     void set_lower_bound(T const & l) { | ||||
|         m_lower_bound = l; | ||||
|         m_lower_bound_is_set = true; | ||||
|     } | ||||
| 
 | ||||
|     void set_upper_bound(T const & l) { | ||||
|  | @ -201,8 +201,8 @@ public: | |||
|         m_upper_bound_is_set = true; | ||||
|     } | ||||
| 
 | ||||
|     void unset_low_bound() { | ||||
|         m_low_bound_is_set = false; | ||||
|     void unset_lower_bound() { | ||||
|         m_lower_bound_is_set = false; | ||||
|     } | ||||
| 
 | ||||
|     void unset_upper_bound() { | ||||
|  | @ -213,8 +213,8 @@ public: | |||
|         m_is_fixed = false; | ||||
|     } | ||||
| 
 | ||||
|     bool low_bound_holds(T v) { | ||||
|         return !low_bound_is_set() || v >= m_low_bound -T(0.0000001); | ||||
|     bool lower_bound_holds(T v) { | ||||
|         return !lower_bound_is_set() || v >= m_lower_bound -T(0.0000001); | ||||
|     } | ||||
| 
 | ||||
|     bool upper_bound_holds(T v) { | ||||
|  | @ -222,36 +222,36 @@ public: | |||
|     } | ||||
| 
 | ||||
|     bool bounds_hold(T v) { | ||||
|         return low_bound_holds(v) && upper_bound_holds(v); | ||||
|         return lower_bound_holds(v) && upper_bound_holds(v); | ||||
|     } | ||||
| 
 | ||||
|     bool adjusted_bounds_hold(T v) { | ||||
|         return adjusted_low_bound_holds(v) && adjusted_upper_bound_holds(v); | ||||
|         return adjusted_lower_bound_holds(v) && adjusted_upper_bound_holds(v); | ||||
|     } | ||||
| 
 | ||||
|     bool adjusted_low_bound_holds(T v) { | ||||
|         return !adjusted_low_bound_is_set() || v >= -T(0.0000001); | ||||
|     bool adjusted_lower_bound_holds(T v) { | ||||
|         return !adjusted_lower_bound_is_set() || v >= -T(0.0000001); | ||||
|     } | ||||
| 
 | ||||
|     bool adjusted_upper_bound_holds(T v) { | ||||
|         return !adjusted_upper_bound_is_set() || v <= get_adjusted_upper_bound() + T(0.000001); | ||||
|     } | ||||
|     bool is_infeasible() { | ||||
|         if ((!upper_bound_is_set()) || (!low_bound_is_set())) | ||||
|         if ((!upper_bound_is_set()) || (!lower_bound_is_set())) | ||||
|             return false; | ||||
|         // ok, both bounds are set
 | ||||
|         bool at_least_one_is_strict = upper_bound_is_strict() || low_bound_is_strict(); | ||||
|         bool at_least_one_is_strict = upper_bound_is_strict() || lower_bound_is_strict(); | ||||
|         if (!at_least_one_is_strict) | ||||
|             return get_upper_bound() < get_low_bound(); | ||||
|             return get_upper_bound() < get_lower_bound(); | ||||
|         // at least on bound is strict
 | ||||
|         return get_upper_bound() <= get_low_bound(); // the equality is impossible
 | ||||
|         return get_upper_bound() <= get_lower_bound(); // the equality is impossible
 | ||||
|     } | ||||
|     bool low_bound_is_strict() const { | ||||
|         return m_low_bound_is_strict; | ||||
|     bool lower_bound_is_strict() const { | ||||
|         return m_lower_bound_is_strict; | ||||
|     } | ||||
| 
 | ||||
|     void set_low_bound_strict(bool val) { | ||||
|         m_low_bound_is_strict = val; | ||||
|     void set_lower_bound_strict(bool val) { | ||||
|         m_lower_bound_is_strict = val; | ||||
|     } | ||||
| 
 | ||||
|     bool upper_bound_is_strict() const { | ||||
|  |  | |||
|  | @ -68,7 +68,31 @@ public: | |||
|             out << "v" << it.second; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     template <typename T> | ||||
|     void print_linear_combination_of_column_indices_std(const vector<std::pair<T, unsigned>> & coeffs, std::ostream & out) const { | ||||
|         bool first = true; | ||||
|         for (const auto & it : coeffs) { | ||||
|             auto val = it.first; | ||||
|             if (first) { | ||||
|                 first = false; | ||||
|             } else { | ||||
|                 if (numeric_traits<T>::is_pos(val)) { | ||||
|                     out << " + "; | ||||
|                 } else { | ||||
|                     out << " - "; | ||||
|                     val = -val; | ||||
|                 } | ||||
|             } | ||||
|             if (val == -numeric_traits<T>::one()) | ||||
|                 out << " - "; | ||||
|             else if (val != numeric_traits<T>::one()) | ||||
|                 out << val; | ||||
|          | ||||
|             out << get_column_name(it.second); | ||||
|         } | ||||
|     } | ||||
|     template <typename T> | ||||
|     void print_linear_combination_of_column_indices(const vector<std::pair<T, unsigned>> & coeffs, std::ostream & out) const { | ||||
|         bool first = true; | ||||
|  |  | |||
|  | @ -22,8 +22,8 @@ Revision History: | |||
| namespace lp { | ||||
| template <typename V> | ||||
| struct conversion_helper { | ||||
|     static V get_low_bound(const column_info<mpq> & ci) { | ||||
|         return V(ci.get_low_bound(), ci.low_bound_is_strict()? 1 : 0); | ||||
|     static V get_lower_bound(const column_info<mpq> & ci) { | ||||
|         return V(ci.get_lower_bound(), ci.lower_bound_is_strict()? 1 : 0); | ||||
|     } | ||||
| 
 | ||||
|     static V get_upper_bound(const column_info<mpq> & ci) { | ||||
|  | @ -37,20 +37,20 @@ struct conversion_helper <double> { | |||
|         if (!ci.upper_bound_is_strict()) | ||||
|             return ci.get_upper_bound().get_double(); | ||||
|         double eps = 0.00001; | ||||
|         if (!ci.low_bound_is_set()) | ||||
|         if (!ci.lower_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_lower_bound()).get_double() / 1000, eps); | ||||
|         return ci.get_upper_bound().get_double() - eps; | ||||
|     } | ||||
| 
 | ||||
|     static double get_low_bound(const column_info<mpq> & ci) { | ||||
|         if (!ci.low_bound_is_strict()) | ||||
|             return ci.get_low_bound().get_double(); | ||||
|     static double get_lower_bound(const column_info<mpq> & ci) { | ||||
|         if (!ci.lower_bound_is_strict()) | ||||
|             return ci.get_lower_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); | ||||
|         return ci.get_low_bound().get_double() + eps; | ||||
|             return ci.get_lower_bound().get_double() + eps; | ||||
|         eps = std::min((ci.get_upper_bound() - ci.get_lower_bound()).get_double() / 1000, eps); | ||||
|         return ci.get_lower_bound().get_double() + eps; | ||||
|     } | ||||
| 
 | ||||
| }; | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ Revision History: | |||
| 
 | ||||
| --*/ | ||||
| #include "util/lp/numeric_pair.h" | ||||
| #include "util/lp/core_solver_pretty_printer.hpp" | ||||
| #include "util/lp/core_solver_pretty_printer_def.h" | ||||
| template lp::core_solver_pretty_printer<double, double>::core_solver_pretty_printer(lp::lp_core_solver_base<double, double> &, std::ostream & out); | ||||
| template void lp::core_solver_pretty_printer<double, double>::print(); | ||||
| template lp::core_solver_pretty_printer<double, double>::~core_solver_pretty_printer(); | ||||
|  | @ -48,7 +48,7 @@ class core_solver_pretty_printer { | |||
|     std::string m_cost_title; | ||||
|     std::string m_basis_heading_title; | ||||
|     std::string m_x_title; | ||||
|     std::string m_low_bounds_title; | ||||
|     std::string m_lower_bounds_title; | ||||
|     std::string m_upp_bounds_title; | ||||
|     std::string m_exact_norm_title; | ||||
|     std::string m_approx_norm_title; | ||||
|  | @ -75,7 +75,7 @@ public: | |||
| 
 | ||||
|     void init_column_widths(); | ||||
| 
 | ||||
|     void adjust_width_with_low_bound(unsigned column, unsigned & w); | ||||
|     void adjust_width_with_lower_bound(unsigned column, unsigned & w); | ||||
|     void adjust_width_with_upper_bound(unsigned column, unsigned & w); | ||||
| 
 | ||||
|     void adjust_width_with_bounds(unsigned column, unsigned & w); | ||||
|  | @ -97,7 +97,7 @@ public: | |||
| 
 | ||||
|     void print_x(); | ||||
| 
 | ||||
|     std::string get_low_bound_string(unsigned j); | ||||
|     std::string get_lower_bound_string(unsigned j); | ||||
| 
 | ||||
|     std::string get_upp_bound_string(unsigned j); | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ core_solver_pretty_printer<T, X>::core_solver_pretty_printer(lp_core_solver_base | |||
|     m_rs(ncols(), zero_of_type<X>()), | ||||
|     m_w_buff(core_solver.m_w), | ||||
|     m_ed_buff(core_solver.m_ed) { | ||||
|     m_low_bounds_title = "low"; | ||||
|     m_lower_bounds_title = "low"; | ||||
|     m_upp_bounds_title = "upp"; | ||||
|     m_exact_norm_title = "exact cn"; | ||||
|     m_approx_norm_title = "approx cn"; | ||||
|  | @ -139,9 +139,9 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::init_co | |||
|     } | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename X> void core_solver_pretty_printer<T, X>::adjust_width_with_low_bound(unsigned column, unsigned & w) { | ||||
|     if (!m_core_solver.low_bounds_are_set()) return; | ||||
|     w = std::max(w, (unsigned)T_to_string(m_core_solver.low_bound_value(column)).size()); | ||||
| template <typename T, typename X> void core_solver_pretty_printer<T, X>::adjust_width_with_lower_bound(unsigned column, unsigned & w) { | ||||
|     if (!m_core_solver.lower_bounds_are_set()) return; | ||||
|     w = std::max(w, (unsigned)T_to_string(m_core_solver.lower_bound_value(column)).size()); | ||||
| } | ||||
| template <typename T, typename X> void core_solver_pretty_printer<T, X>::adjust_width_with_upper_bound(unsigned column, unsigned & w) { | ||||
|     w = std::max(w, (unsigned)T_to_string(m_core_solver.upper_bound_value(column)).size()); | ||||
|  | @ -151,11 +151,11 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::adjust_ | |||
|     switch (m_core_solver.get_column_type(column)) { | ||||
|     case column_type::fixed: | ||||
|     case column_type::boxed: | ||||
|         adjust_width_with_low_bound(column, w); | ||||
|         adjust_width_with_lower_bound(column, w); | ||||
|         adjust_width_with_upper_bound(column, w); | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|         adjust_width_with_low_bound(column, w); | ||||
|     case column_type::lower_bound: | ||||
|         adjust_width_with_lower_bound(column, w); | ||||
|         break; | ||||
|     case column_type::upper_bound: | ||||
|         adjust_width_with_upper_bound(column, w); | ||||
|  | @ -236,13 +236,13 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::print_x | |||
|     m_out << std::endl; | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename X> std::string core_solver_pretty_printer<T, X>::get_low_bound_string(unsigned j) { | ||||
| template <typename T, typename X> std::string core_solver_pretty_printer<T, X>::get_lower_bound_string(unsigned j) { | ||||
|     switch (m_core_solver.get_column_type(j)){ | ||||
|     case column_type::boxed: | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|     case column_type::fixed: | ||||
|         if (m_core_solver.low_bounds_are_set()) | ||||
|             return T_to_string(m_core_solver.low_bound_value(j)); | ||||
|         if (m_core_solver.lower_bounds_are_set()) | ||||
|             return T_to_string(m_core_solver.lower_bound_value(j)); | ||||
|         else | ||||
|             return std::string("0"); | ||||
|         break; | ||||
|  | @ -268,12 +268,12 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::print_l | |||
|     if (ncols() == 0) { | ||||
|         return; | ||||
|     } | ||||
|     int blanks = m_title_width + 1 - static_cast<unsigned>(m_low_bounds_title.size()); | ||||
|     m_out << m_low_bounds_title; | ||||
|     int blanks = m_title_width + 1 - static_cast<unsigned>(m_lower_bounds_title.size()); | ||||
|     m_out << m_lower_bounds_title; | ||||
|     print_blanks(blanks, m_out); | ||||
| 
 | ||||
|     for (unsigned i = 0; i < ncols(); i++) { | ||||
|         string s = get_low_bound_string(i); | ||||
|         string s = get_lower_bound_string(i); | ||||
|         int blanks = m_column_widths[i] - static_cast<unsigned>(s.size()); | ||||
|         print_blanks(blanks, m_out); | ||||
|         m_out << s << "   "; // the column interval
 | ||||
|  | @ -4,5 +4,21 @@ | |||
| */ | ||||
| #include "util/lp/cut_solver.h" | ||||
| namespace lp { | ||||
|     mpq polynomial::m_local_zero = zero_of_type<mpq>(); | ||||
| 
 | ||||
|     size_t constraint_hash::operator() (const constraint* c) const { return c->id(); } | ||||
|      | ||||
|     bool constraint_equal::operator() (const constraint* a, const constraint * b) const { return a->id() == b->id(); } | ||||
| 
 | ||||
|     std::ostream& operator<<(std::ostream& out, pp_poly const& p) { | ||||
|         p.s.print_polynomial(out, p.p); | ||||
|         return out; | ||||
|     } | ||||
| 
 | ||||
|     std::ostream& operator<<(std::ostream& out, pp_constraint const& c) { | ||||
|         c.s.print_constraint(out, c.c); | ||||
|         return out; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -18,7 +18,7 @@ Revision History: | |||
| 
 | ||||
| --*/ | ||||
| #include "util/lp/lp_settings.h" | ||||
| #include "util/lp/dense_matrix.hpp" | ||||
| #include "util/lp/dense_matrix_def.h" | ||||
| #ifdef Z3DEBUG | ||||
| #include "util/vector.h" | ||||
| template lp::dense_matrix<double, double> lp::operator*<double, double>(lp::matrix<double, double>&, lp::matrix<double, double>&); | ||||
|  | @ -100,7 +100,7 @@ public: | |||
|     void swap_rows(unsigned a, unsigned b); | ||||
| 
 | ||||
|     void multiply_row_by_constant(unsigned row, T & t); | ||||
| 
 | ||||
|      | ||||
| }; | ||||
| template <typename T, typename X> | ||||
| dense_matrix<T, X> operator* (matrix<T, X> & a, matrix<T, X> & b); | ||||
|  |  | |||
|  | @ -20,8 +20,8 @@ Revision History: | |||
| #include <memory> | ||||
| #include "util/vector.h" | ||||
| #include "util/lp/numeric_pair.h" | ||||
| #include "util/lp/eta_matrix.hpp" | ||||
| #ifdef LEAN_DEBUG | ||||
| #include "util/lp/eta_matrix_def.h" | ||||
| #ifdef Z3DEBUG | ||||
| template double lp::eta_matrix<double, double>::get_elem(unsigned int, unsigned int) const; | ||||
| template lp::mpq lp::eta_matrix<lp::mpq, lp::mpq>::get_elem(unsigned int, unsigned int) const; | ||||
| template lp::mpq lp::eta_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::get_elem(unsigned int, unsigned int) const; | ||||
|  | @ -24,31 +24,31 @@ namespace lp { | |||
| struct implied_bound { | ||||
|     mpq m_bound; | ||||
|     unsigned m_j; // the column for which the bound has been found
 | ||||
|     bool m_is_low_bound; | ||||
|     bool m_is_lower_bound; | ||||
|     bool m_coeff_before_j_is_pos; | ||||
|     unsigned m_row_or_term_index; | ||||
|     bool m_strict; | ||||
|     lconstraint_kind kind() const { | ||||
|         lconstraint_kind k = m_is_low_bound? GE : LE; | ||||
|         lconstraint_kind k = m_is_lower_bound? GE : LE; | ||||
|         if (m_strict) | ||||
|             k = static_cast<lconstraint_kind>(k / 2); | ||||
|         return k; | ||||
|     } | ||||
|     bool operator==(const implied_bound & o) const { | ||||
|         return m_j == o.m_j && m_is_low_bound == o.m_is_low_bound && m_bound == o.m_bound && | ||||
|         return m_j == o.m_j && m_is_lower_bound == o.m_is_lower_bound && m_bound == o.m_bound && | ||||
|             m_coeff_before_j_is_pos == o.m_coeff_before_j_is_pos && | ||||
|             m_row_or_term_index == o.m_row_or_term_index && m_strict == o.m_strict; | ||||
|     } | ||||
|     implied_bound(){} | ||||
|     implied_bound(const mpq & a, | ||||
|                   unsigned j, | ||||
|                   bool low_bound, | ||||
|                   bool lower_bound, | ||||
|                   bool coeff_before_j_is_pos, | ||||
|                   unsigned row_or_term_index, | ||||
|                   bool strict): | ||||
|         m_bound(a), | ||||
|         m_j(j), | ||||
|         m_is_low_bound(low_bound), | ||||
|         m_is_lower_bound(lower_bound), | ||||
|         m_coeff_before_j_is_pos(coeff_before_j_is_pos), | ||||
|         m_row_or_term_index(row_or_term_index), | ||||
|         m_strict(strict) { | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ Revision History: | |||
| 
 | ||||
| --*/ | ||||
| #include "util/vector.h" | ||||
| #include "util/lp/indexed_vector.hpp" | ||||
| #include "util/lp/indexed_vector_def.h" | ||||
| namespace lp { | ||||
| template void indexed_vector<double>::clear(); | ||||
| template void indexed_vector<double>::clear_all(); | ||||
|  | @ -90,15 +90,6 @@ public: | |||
|     } | ||||
| 
 | ||||
|     void set_value(const T& value, unsigned index); | ||||
|     void set_value_as_in_dictionary(unsigned index) { | ||||
|         SASSERT(index < m_data.size()); | ||||
|         T & loc = m_data[index]; | ||||
|         if (is_zero(loc)) { | ||||
|             m_index.push_back(index); | ||||
|             loc = one_of_type<T>(); // use as a characteristic function
 | ||||
|         }  | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     void clear(); | ||||
|     void clear_all(); | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #include "util/lp/int_solver.h" | ||||
| #include "util/lp/lar_solver.h" | ||||
| #include "util/lp/cut_solver.h" | ||||
| #include "util/lp/lp_utils.h" | ||||
| #include <utility> | ||||
| namespace lp { | ||||
| 
 | ||||
|  | @ -78,7 +79,7 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { | |||
|         lp_assert(!is_fixed(j)); | ||||
|         if (!is_boxed(j)) | ||||
|             continue; | ||||
|         new_range  = lcs.m_r_upper_bounds()[j].x - lcs.m_r_low_bounds()[j].x; | ||||
|         new_range  = lcs.m_r_upper_bounds()[j].x - lcs.m_r_lower_bounds()[j].x; | ||||
|         if (new_range > small_range_thresold)  | ||||
|             continue; | ||||
|         if (result == -1) { | ||||
|  | @ -136,9 +137,9 @@ void int_solver::real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, l | |||
|             new_a  =  a / f_0; | ||||
|             new_a.neg(); | ||||
|         } | ||||
|         k.addmul(new_a, low_bound(x_j).x); // is it a faster operation than
 | ||||
|         k.addmul(new_a, lower_bound(x_j).x); // is it a faster operation than
 | ||||
|         // k += lower_bound(x_j).x * new_a;  
 | ||||
|         expl.push_justification(column_low_bound_constraint(x_j), new_a); | ||||
|         expl.push_justification(column_lower_bound_constraint(x_j), new_a); | ||||
|     } | ||||
|     else { | ||||
|         lp_assert(at_upper(x_j)); | ||||
|  | @ -160,8 +161,8 @@ constraint_index int_solver::column_upper_bound_constraint(unsigned j) const { | |||
|     return m_lar_solver->get_column_upper_bound_witness(j); | ||||
| } | ||||
| 
 | ||||
| constraint_index int_solver::column_low_bound_constraint(unsigned j) const { | ||||
|     return m_lar_solver->get_column_low_bound_witness(j); | ||||
| constraint_index int_solver::column_lower_bound_constraint(unsigned j) const { | ||||
|     return m_lar_solver->get_column_lower_bound_witness(j); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -188,8 +189,8 @@ void int_solver::int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, la | |||
|         else { | ||||
|             new_a = (1 - f_j) / f_0; | ||||
|         } | ||||
|         k.addmul(new_a, low_bound(x_j).x); | ||||
|         expl.push_justification(column_low_bound_constraint(x_j), new_a); | ||||
|         k.addmul(new_a, lower_bound(x_j).x); | ||||
|         expl.push_justification(column_lower_bound_constraint(x_j), new_a); | ||||
|     } | ||||
|     else { | ||||
|         lp_assert(at_upper(x_j)); | ||||
|  | @ -400,34 +401,36 @@ unsigned int_solver::row_of_basic_column(unsigned j) const { | |||
|     return m_lar_solver->m_mpq_lar_core_solver.m_r_heading[j]; | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| void int_solver::fill_cut_solver(cut_solver<T> & cs) { | ||||
|     for (lar_base_constraint * c : m_lar_solver->constraints()) | ||||
|         fill_cut_solver_for_constraint(c, cs); | ||||
| } | ||||
| // template <typename T>
 | ||||
| // void int_solver::fill_cut_solver_for_constraint(constraint_index ci, cut_solver<T> & cs) {
 | ||||
| //     const lar_base_constraint* c = m_lar_solver->constraints()[ci];
 | ||||
| //     vector<std::pair<T, var_index>> coeffs;
 | ||||
| //     T rs;
 | ||||
| //     get_int_coeffs_from_constraint(c, coeffs, rs);
 | ||||
| //     vector<constraint_index> explanation;
 | ||||
| //     explanation.push_back(ci);
 | ||||
| //     cs.add_ineq(coeffs, -rs, explanation);
 | ||||
| // }
 | ||||
| 
 | ||||
| template <typename T> | ||||
| void int_solver::fill_cut_solver_for_constraint(const lar_base_constraint* c, cut_solver<T> & cs) { | ||||
|     vector<std::pair<T, var_index>> coeffs; | ||||
|     T rs; | ||||
|     get_int_coeffs_from_constraint(c, coeffs, rs); | ||||
|     cs.add_ineq(coeffs, rs); | ||||
| } | ||||
| 
 | ||||
| typedef cut_solver::monomial mono; | ||||
| 
 | ||||
| // it produces an inequality coeff*x <= rs
 | ||||
| template <typename T> | ||||
| void int_solver::get_int_coeffs_from_constraint(const lar_base_constraint* c, vector<std::pair<T, var_index>>& coeffs, T & rs) { | ||||
| void int_solver::get_int_coeffs_from_constraint(const lar_base_constraint* c, | ||||
|                                                 vector<mono>& coeffs, T & rs) { | ||||
|     lp_assert(c->m_kind != EQ); // it is not implemented, we need to create two inequalities in this case
 | ||||
|     int sign = ((int)c->m_kind > 0) ? -1 : 1; | ||||
|     vector<std::pair<T, var_index>> lhs = c->get_left_side_coefficients(); | ||||
|     T den = denominator(c->m_right_side); | ||||
|     for (auto & kv : lhs) { | ||||
|         lp_assert(!is_term(kv.second)); | ||||
|         lp_assert(is_int(kv.second)); // not implemented for real vars!
 | ||||
|         den = lcm(den, denominator(kv.first)); | ||||
|     } | ||||
|     lp_assert(den > 0); | ||||
|     for (auto& kv : lhs) { | ||||
|         coeffs.push_back(std::make_pair(den * kv.first * sign, kv.second)); | ||||
|         coeffs.push_back(mono(den * kv.first * sign, kv.second)); | ||||
|     } | ||||
|     rs = den * c->m_right_side * sign; | ||||
|     if (kind_is_strict(c->m_kind)) | ||||
|  | @ -452,12 +455,35 @@ struct pivoted_rows_tracking_control { | |||
|     } | ||||
| }; | ||||
| 
 | ||||
| void int_solver::copy_explanations_from_cut_solver(explanation &ex) { | ||||
|     TRACE("propagate_and_backjump_step_int", | ||||
|           for (unsigned j: m_cut_solver.m_explanation) | ||||
|               m_lar_solver->print_constraint(m_lar_solver->constraints()[j], tout);); | ||||
| 
 | ||||
|     for (unsigned j : m_cut_solver.m_explanation) { | ||||
|         ex.push_justification(j); | ||||
|      } | ||||
|     m_cut_solver.m_explanation.clear(); | ||||
| } | ||||
| 
 | ||||
| void int_solver::copy_values_from_cut_solver() { | ||||
|     for (unsigned j = 0; j < m_lar_solver->A_r().column_count() && j < m_cut_solver.number_of_vars(); j++) { | ||||
|         if (!m_cut_solver.var_is_active(j)) | ||||
|             continue; | ||||
|         if (!is_int(j)) { | ||||
|             continue; | ||||
|         } | ||||
|         m_lar_solver->m_mpq_lar_core_solver.m_r_x[j] = m_cut_solver.var_value(j); | ||||
|         lp_assert(m_lar_solver->column_value_is_int(j)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { | ||||
|     init_check_data(); | ||||
|     lp_assert(inf_int_set_is_correct()); | ||||
|     // it is mostly a reimplementation of
 | ||||
|     // it is a reimplementation of 
 | ||||
|     // final_check_status theory_arith<Ext>::check_int_feasibility()
 | ||||
|     // from theory_arith_int.h
 | ||||
|     // from theory_arith_int.h with the addition of cut_solver
 | ||||
|     if (!has_inf_int())  | ||||
|         return lia_move::ok; | ||||
|     if (settings().m_run_gcd_test) | ||||
|  | @ -470,26 +496,43 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { | |||
|     if (!has_inf_int()) | ||||
|         return lia_move::ok; | ||||
| 
 | ||||
|     // lp_assert(non_basic_columns_are_at_bounds());
 | ||||
|     TRACE("gomory_cut", tout << m_branch_cut_counter+1 << ", " << settings().m_int_branch_cut_gomory_threshold << std::endl;); | ||||
|     if (++m_branch_cut_counter > 0) { // testing cut_solver
 | ||||
|         cut_solver<mpq> cs([this](unsigned j) {return m_lar_solver->get_column_name(j);}); | ||||
|         fill_cut_solver(cs); | ||||
|     } else  | ||||
|         if ((++m_branch_cut_counter) % settings().m_int_branch_cut_gomory_threshold == 0) { | ||||
|             if (move_non_basic_columns_to_bounds()) { | ||||
|                 lp_status st = m_lar_solver->find_feasible_solution(); | ||||
|                 lp_assert(non_basic_columns_are_at_bounds()); | ||||
|                 if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) { | ||||
|                     TRACE("arith_int", tout << "give_up\n";); | ||||
|                     return lia_move::give_up; | ||||
|                 } | ||||
|             } | ||||
|             int j = find_inf_int_base_column(); | ||||
|             if (j == -1) return lia_move::ok; | ||||
|             TRACE("arith_int", tout << "j = " << j << " does not have an integer assignment: " << get_value(j) << "\n";); | ||||
|             return proceed_with_gomory_cut(t, k, ex, j); | ||||
|     if ((++m_branch_cut_counter) % settings().m_int_branch_cut_solver == 0) { | ||||
|         TRACE("check_main_int", tout<<"cut_solver";); | ||||
|         auto check_res = m_cut_solver.check(); | ||||
|         settings().st().m_cut_solver_calls++; | ||||
|         switch (check_res) { | ||||
|         case lbool::l_false: | ||||
|             copy_explanations_from_cut_solver(ex);  | ||||
|             settings().st().m_cut_solver_false++; | ||||
|             return lia_move::conflict; | ||||
|         case lbool::l_true: | ||||
|             settings().st().m_cut_solver_true++; | ||||
|             copy_values_from_cut_solver(); | ||||
|             return lia_move::ok; | ||||
|         case lbool::l_undef: | ||||
|             settings().st().m_cut_solver_undef++; | ||||
|             settings().m_int_branch_cut_solver *= (settings().m_int_branch_cut_solver); // take a square
 | ||||
|             break; | ||||
|         default: | ||||
|             return lia_move::give_up; | ||||
|         } | ||||
|     } | ||||
|     if ((m_branch_cut_counter) % settings().m_int_branch_cut_gomory_threshold == 0) { | ||||
|         TRACE("check_main_int", tout << "gomory";); | ||||
|         if (move_non_basic_columns_to_bounds()) { | ||||
|             lp_status st = m_lar_solver->find_feasible_solution(); | ||||
|             lp_assert(non_basic_columns_are_at_bounds()); | ||||
|             if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) { | ||||
|                 TRACE("arith_int", tout << "give_up\n";); | ||||
|                 return lia_move::give_up; | ||||
|             } | ||||
|         } | ||||
|         int j = find_inf_int_base_column(); | ||||
|         if (j == -1) return lia_move::ok; | ||||
|         TRACE("arith_int", tout << "j = " << j << " does not have an integer assignment: " << get_value(j) << "\n";); | ||||
|         return proceed_with_gomory_cut(t, k, ex, j); | ||||
|     } | ||||
|     TRACE("check_main_int", tout << "branch"; ); | ||||
|     return create_branch_on_column(find_inf_int_base_column(), t, k, false); | ||||
| } | ||||
| 
 | ||||
|  | @ -498,17 +541,17 @@ bool int_solver::move_non_basic_column_to_bounds(unsigned j) { | |||
|     auto & val = lcs.m_r_x[j]; | ||||
|     switch (lcs.m_column_types()[j]) { | ||||
|     case column_type::boxed: | ||||
|         if (val != lcs.m_r_low_bounds()[j] && val != lcs.m_r_upper_bounds()[j]) { | ||||
|         if (val != lcs.m_r_lower_bounds()[j] && val != lcs.m_r_upper_bounds()[j]) { | ||||
|             if (random() % 2 == 0) | ||||
|                 set_value_for_nbasic_column(j, lcs.m_r_low_bounds()[j]); | ||||
|                 set_value_for_nbasic_column(j, lcs.m_r_lower_bounds()[j]); | ||||
|             else | ||||
|                 set_value_for_nbasic_column(j, lcs.m_r_upper_bounds()[j]); | ||||
|             return true; | ||||
|         } | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|         if (val != lcs.m_r_low_bounds()[j]) { | ||||
|             set_value_for_nbasic_column(j, lcs.m_r_low_bounds()[j]); | ||||
|     case column_type::lower_bound: | ||||
|         if (val != lcs.m_r_lower_bounds()[j]) { | ||||
|             set_value_for_nbasic_column(j, lcs.m_r_lower_bounds()[j]); | ||||
|             return true; | ||||
|         } | ||||
|         break; | ||||
|  | @ -647,7 +690,7 @@ bool int_solver::gcd_test_for_row(static_matrix<mpq, numeric_pair<mpq>> & A, uns | |||
|     while (it.next(a, j)) { | ||||
|         if (m_lar_solver->column_is_fixed(j)) { | ||||
|             mpq aux = lcm_den * a; | ||||
|             consts += aux * m_lar_solver->column_low_bound(j).x; | ||||
|             consts += aux * m_lar_solver->column_lower_bound(j).x; | ||||
|         } | ||||
|         else if (m_lar_solver->column_is_real(j)) { | ||||
|             return true; | ||||
|  | @ -744,16 +787,16 @@ bool int_solver::ext_gcd_test(iterator_on_row<mpq> & it, | |||
|         if (abs_ncoeff == least_coeff) { | ||||
|             SASSERT(m_lar_solver->column_is_bounded(j)); | ||||
|             if (ncoeff.is_pos()) { | ||||
|                 // l += ncoeff * m_lar_solver->column_low_bound(j).x;
 | ||||
|                 l.addmul(ncoeff, m_lar_solver->column_low_bound(j).x); | ||||
|                 // l += ncoeff * m_lar_solver->column_lower_bound(j).x;
 | ||||
|                 l.addmul(ncoeff, m_lar_solver->column_lower_bound(j).x); | ||||
|                 // u += ncoeff * m_lar_solver->column_upper_bound(j).x;
 | ||||
|                 u.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x); | ||||
|             } | ||||
|             else { | ||||
|                 // l += ncoeff * upper_bound(j).get_rational();
 | ||||
|                 l.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x); | ||||
|                 // u += ncoeff * low_bound(j).get_rational();
 | ||||
|                 u.addmul(ncoeff, m_lar_solver->column_low_bound(j).x); | ||||
|                 // u += ncoeff * lower_bound(j).get_rational();
 | ||||
|                 u.addmul(ncoeff, m_lar_solver->column_lower_bound(j).x); | ||||
|             } | ||||
|             add_to_explanation_from_fixed_or_boxed_column(j, ex); | ||||
|         } | ||||
|  | @ -791,7 +834,12 @@ linear_combination_iterator<mpq> * int_solver::get_column_iterator(unsigned j) { | |||
| 
 | ||||
| int_solver::int_solver(lar_solver* lar_slv) : | ||||
|     m_lar_solver(lar_slv), | ||||
|     m_branch_cut_counter(0) { | ||||
|     m_branch_cut_counter(0), | ||||
|     m_cut_solver([this](unsigned j) {return m_lar_solver->get_column_name(j);}, | ||||
|                  [this](unsigned j, std::ostream &o) {m_lar_solver->print_constraint(j, o);}, | ||||
|                  [this]() {return m_lar_solver->A_r().column_count();}, | ||||
|                  [this](unsigned j) {return get_value(j);}, | ||||
|                  settings()) { | ||||
|     lp_assert(m_old_values_set.size() == 0); | ||||
|     m_old_values_set.resize(lar_slv->A_r().column_count()); | ||||
|     m_old_values_data.resize(lar_slv->A_r().column_count(), zero_of_type<impq>()); | ||||
|  | @ -802,7 +850,7 @@ bool int_solver::has_low(unsigned j) const { | |||
|     switch (m_lar_solver->m_mpq_lar_core_solver.m_column_types()[j]) { | ||||
|     case column_type::fixed: | ||||
|     case column_type::boxed: | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|         return true; | ||||
|     default: | ||||
|         return false; | ||||
|  | @ -853,7 +901,7 @@ bool int_solver::get_freedom_interval_for_column(unsigned j, bool & inf_l, impq | |||
|     m = mpq(1); | ||||
| 
 | ||||
|     if (has_low(j)) { | ||||
|         set_lower(l, inf_l, low_bound(j)); | ||||
|         set_lower(l, inf_l, lower_bound(j)); | ||||
|     } | ||||
|     if (has_upper(j)) { | ||||
|         set_upper(u, inf_u, upper_bound(j)); | ||||
|  | @ -868,7 +916,7 @@ bool int_solver::get_freedom_interval_for_column(unsigned j, bool & inf_l, impq | |||
|             m = lcm(m, denominator(a)); | ||||
|         if (a.is_neg()) { | ||||
|             if (has_low(i)) | ||||
|                 set_lower(l, inf_l, xj + (xi - lcs.m_r_low_bounds()[i]) / a); | ||||
|                 set_lower(l, inf_l, xj + (xi - lcs.m_r_lower_bounds()[i]) / a); | ||||
| 
 | ||||
|             if (has_upper(i)) | ||||
|                 set_upper(u, inf_u, xj + (xi - lcs.m_r_upper_bounds()[i]) / a); | ||||
|  | @ -877,7 +925,7 @@ bool int_solver::get_freedom_interval_for_column(unsigned j, bool & inf_l, impq | |||
|             if (has_upper(i)) | ||||
|                 set_lower(l, inf_l, xj + (xi - lcs.m_r_upper_bounds()[i]) / a); | ||||
|             if (has_low(i)) | ||||
|                 set_upper(u, inf_u, xj + (xi - lcs.m_r_low_bounds()[i]) / a); | ||||
|                 set_upper(u, inf_u, xj + (xi - lcs.m_r_lower_bounds()[i]) / a); | ||||
|         } | ||||
|         if (!inf_l && !inf_u && l == u) break;;                 | ||||
|     } | ||||
|  | @ -971,10 +1019,10 @@ bool int_solver::at_bound(unsigned j) const { | |||
|     case column_type::fixed: | ||||
|     case column_type::boxed: | ||||
|         return | ||||
|             mpq_solver.m_low_bounds[j] == get_value(j) || | ||||
|             mpq_solver.m_lower_bounds[j] == get_value(j) || | ||||
|             mpq_solver.m_upper_bounds[j] == get_value(j); | ||||
|     case column_type::low_bound: | ||||
|         return mpq_solver.m_low_bounds[j] == get_value(j); | ||||
|     case column_type::lower_bound: | ||||
|         return mpq_solver.m_lower_bounds[j] == get_value(j); | ||||
|     case column_type::upper_bound: | ||||
|         return  mpq_solver.m_upper_bounds[j] == get_value(j); | ||||
|     default: | ||||
|  | @ -987,8 +1035,8 @@ bool int_solver::at_low(unsigned j) const { | |||
|     switch (mpq_solver.m_column_types[j] ) { | ||||
|     case column_type::fixed: | ||||
|     case column_type::boxed: | ||||
|     case column_type::low_bound: | ||||
|         return mpq_solver.m_low_bounds[j] == get_value(j); | ||||
|     case column_type::lower_bound: | ||||
|         return mpq_solver.m_lower_bounds[j] == get_value(j); | ||||
|     default: | ||||
|         return false; | ||||
|     } | ||||
|  | @ -1099,11 +1147,11 @@ bool int_solver::non_basic_columns_are_at_bounds() const { | |||
|         auto & val = lcs.m_r_x[j]; | ||||
|         switch (lcs.m_column_types()[j]) { | ||||
|         case column_type::boxed: | ||||
|             if (val != lcs.m_r_low_bounds()[j] && val != lcs.m_r_upper_bounds()[j]) | ||||
|             if (val != lcs.m_r_lower_bounds()[j] && val != lcs.m_r_upper_bounds()[j]) | ||||
|                 return false; | ||||
|             break; | ||||
|         case column_type::low_bound: | ||||
|             if (val != lcs.m_r_low_bounds()[j]) | ||||
|         case column_type::lower_bound: | ||||
|             if (val != lcs.m_r_lower_bounds()[j]) | ||||
|                 return false; | ||||
|             break; | ||||
|         case column_type::upper_bound: | ||||
|  | @ -1119,8 +1167,8 @@ bool int_solver::non_basic_columns_are_at_bounds() const { | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| const impq& int_solver::low_bound(unsigned j) const { | ||||
|     return m_lar_solver->column_low_bound(j); | ||||
| const impq& int_solver::lower_bound(unsigned j) const { | ||||
|     return m_lar_solver->column_lower_bound(j); | ||||
| } | ||||
| 
 | ||||
| lia_move int_solver::create_branch_on_column(int j, lar_term& t, mpq& k, bool free_column) const { | ||||
|  | @ -1149,4 +1197,31 @@ void int_solver::display_inf_or_int_inf_columns(std::ostream & out) const { | |||
|         display_column(out, j); | ||||
|     } | ||||
| } | ||||
| bool int_solver::is_term(unsigned j) const { | ||||
|     return m_lar_solver->column_corresponds_to_term(j); | ||||
| } | ||||
| 
 | ||||
| void int_solver::add_constraint_to_cut_solver(unsigned ci, const lar_base_constraint * c) { | ||||
|     vector<mono> coeffs; | ||||
|     mpq rs; | ||||
|     get_int_coeffs_from_constraint<mpq>(c, coeffs, rs); | ||||
|     svector<constraint_index> explanation; | ||||
|     explanation.push_back(ci); | ||||
|     m_cut_solver.add_ineq(coeffs, -rs, explanation); | ||||
| } | ||||
| 
 | ||||
| void int_solver::notify_on_last_added_constraint() { | ||||
|     unsigned ci = m_lar_solver->constraints().size() - 1; | ||||
|     const lar_base_constraint* c = m_lar_solver->constraints()[ci]; | ||||
|     add_constraint_to_cut_solver(ci, c); | ||||
| } | ||||
| 
 | ||||
| void int_solver::pop(unsigned k) { | ||||
|     m_cut_solver.pop(k); | ||||
| } | ||||
| 
 | ||||
| void int_solver::push() { | ||||
|     m_cut_solver.push(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -16,18 +16,23 @@ class lar_solver; | |||
| template <typename T, typename X> | ||||
| struct lp_constraint; | ||||
| enum class lia_move { | ||||
|         ok, | ||||
|     ok, | ||||
|         branch, | ||||
|         cut, | ||||
|         conflict, | ||||
|         give_up | ||||
| }; | ||||
|         continue_with_check, | ||||
|         give_up, | ||||
|         unsat | ||||
|         }; | ||||
| 
 | ||||
| struct explanation { | ||||
|     vector<std::pair<mpq, constraint_index>> m_explanation; | ||||
|     void push_justification(constraint_index j, const mpq& v) { | ||||
|         m_explanation.push_back(std::make_pair(v, j)); | ||||
|     } | ||||
|     void push_justification(constraint_index j) { | ||||
|         m_explanation.push_back(std::make_pair(one_of_type<mpq>(), j)); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| class int_solver { | ||||
|  | @ -37,15 +42,15 @@ public: | |||
|     int_set m_old_values_set; | ||||
|     vector<impq> m_old_values_data; | ||||
|     unsigned m_branch_cut_counter; | ||||
|      | ||||
|     cut_solver m_cut_solver; | ||||
|     // methods
 | ||||
|     int_solver(lar_solver* lp); | ||||
|     int_set& inf_int_set(); | ||||
|     const int_set& inf_int_set() const; | ||||
|     // main function to check that solution provided by lar_solver is valid for integral values,
 | ||||
|     // main function to check that the solution provided by lar_solver is valid for integral values,
 | ||||
|     // or provide a way of how it can be adjusted.
 | ||||
|     lia_move check(lar_term& t, mpq& k, explanation& ex); | ||||
| 	bool move_non_basic_column_to_bounds(unsigned j); | ||||
|     bool move_non_basic_column_to_bounds(unsigned j); | ||||
|     lia_move check_wrapper(lar_term& t, mpq& k, explanation& ex); | ||||
| private: | ||||
| 
 | ||||
|  | @ -78,11 +83,11 @@ private: | |||
|                       explanation & ex); | ||||
|     void fill_explanation_from_fixed_columns(iterator_on_row<mpq> & it, explanation &); | ||||
|     void add_to_explanation_from_fixed_or_boxed_column(unsigned j, explanation &); | ||||
| 	void patch_int_infeasible_non_basic_column(unsigned j); | ||||
| 	void patch_int_infeasible_nbasic_columns(); | ||||
|     void patch_int_infeasible_non_basic_column(unsigned j); | ||||
|     void patch_int_infeasible_nbasic_columns(); | ||||
|     bool get_freedom_interval_for_column(unsigned j, bool & inf_l, impq & l, bool & inf_u, impq & u, mpq & m); | ||||
|     linear_combination_iterator<mpq> * get_column_iterator(unsigned j); | ||||
|     const impq & low_bound(unsigned j) const; | ||||
|     const impq & lower_bound(unsigned j) const; | ||||
|     const impq & upper_bound(unsigned j) const; | ||||
|     bool is_int(unsigned j) const; | ||||
|     bool is_real(unsigned j) const; | ||||
|  | @ -110,7 +115,7 @@ private: | |||
|     lia_move mk_gomory_cut(lar_term& t, mpq& k,explanation & ex, unsigned inf_col, linear_combination_iterator<mpq>& iter); | ||||
|     lia_move report_conflict_from_gomory_cut(mpq & k); | ||||
|     void adjust_term_and_k_for_some_ints_case_gomory(lar_term& t, mpq& k, mpq& lcm_den); | ||||
| 	void init_check_data(); | ||||
|     void init_check_data(); | ||||
|     bool constrain_free_vars(linear_combination_iterator<mpq> *  r); | ||||
|     lia_move proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex, unsigned j); | ||||
|     int find_free_var_in_gomory_row(linear_combination_iterator<mpq>& iter); | ||||
|  | @ -133,7 +138,7 @@ private: | |||
|     void real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& t, explanation & ex, unsigned inf_column); | ||||
|     void int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& t, explanation& ex, mpq & lcm_den, unsigned inf_column); | ||||
|     constraint_index column_upper_bound_constraint(unsigned j) const; | ||||
|     constraint_index column_low_bound_constraint(unsigned j) const; | ||||
|     constraint_index column_lower_bound_constraint(unsigned j) const; | ||||
|     void display_row_info(std::ostream & out, unsigned row_index) const; | ||||
|     void gomory_cut_adjust_t_and_k(vector<std::pair<mpq, unsigned>> & pol, lar_term & t, mpq &k, bool num_ints, mpq &lcm_den); | ||||
|     bool current_solution_is_inf_on_cut(const lar_term& t, const mpq& k) const; | ||||
|  | @ -146,11 +151,15 @@ private: | |||
| public: | ||||
|     void display_inf_or_int_inf_columns(std::ostream & out) const; | ||||
|     template <typename T> | ||||
|     void fill_cut_solver(cut_solver<T> & cs); | ||||
|     void fill_cut_solver_vars(); | ||||
|     template <typename T> | ||||
|     void fill_cut_solver_for_constraint(const lar_base_constraint*, cut_solver<T>& ); | ||||
|     template <typename T> | ||||
|     void get_int_coeffs_from_constraint(const lar_base_constraint* c, vector<std::pair<T, var_index>>& coeff, T & rs); | ||||
| 
 | ||||
|     void get_int_coeffs_from_constraint(const lar_base_constraint* c, vector<cut_solver::monomial>& coeff, T & rs); | ||||
|     bool is_term(unsigned j) const; | ||||
|     void notify_on_last_added_constraint(); | ||||
|     void add_constraint_to_cut_solver(unsigned,const lar_base_constraint*); | ||||
|     void copy_explanations_from_cut_solver(explanation &); | ||||
|     void pop(unsigned); | ||||
|     void push(); | ||||
|     void copy_values_from_cut_solver(); | ||||
| }; | ||||
| } | ||||
|  |  | |||
|  | @ -8,17 +8,51 @@ | |||
| #include "util/lp/stacked_value.h" | ||||
| #include "util/lp/stacked_map.h" | ||||
| namespace lp { | ||||
| enum class endpoint_kind { START, END, STEND };  | ||||
| // represents the set of disjoint intervals of integer number
 | ||||
| template <typename T> | ||||
| class integer_domain { | ||||
| #ifdef Z3DEBUG | ||||
|     std::set<int> m_domain; | ||||
| #endif  | ||||
|     typedef typename std::map<T, char>::iterator iter; | ||||
|     typedef typename std::map<T, char>::const_iterator const_iter; | ||||
|     typedef typename std::map<T, char>::reverse_iterator riter; | ||||
|     stacked_map<T, char> m_endpoints; // 0 means start, 1 means end, 2 means both - for a point interval
 | ||||
|     stacked_value<bool> m_empty; | ||||
|     //    std::set<int> m_domain;
 | ||||
| #endif | ||||
|     struct endpoint { int m_start_expl; int m_end_expl; | ||||
|         endpoint() : m_start_expl(-1), m_end_expl(-1) {} | ||||
|         endpoint(int s, int e) : m_start_expl(s), m_end_expl(e) {} | ||||
|         endpoint_kind kind() const { | ||||
|             lp_assert(m_start_expl != -1 || m_end_expl != -1); | ||||
|             if (m_end_expl == -1) { | ||||
|                 return endpoint_kind::START; | ||||
|             } | ||||
|             if (m_start_expl == -1) { | ||||
|                 return endpoint_kind::END; | ||||
|             } | ||||
|              | ||||
|             return endpoint_kind::STEND; | ||||
|         } | ||||
|         bool operator==(const endpoint& e) const { | ||||
|             return m_start_expl == e.m_start_expl && m_end_expl == e.m_end_expl; | ||||
|         } | ||||
|         bool operator!=(const endpoint & e) const { return !(*this == e); } | ||||
| 
 | ||||
|         void print(std::ostream & out) const { | ||||
|             if (m_start_expl != -1 && m_end_expl != -1) | ||||
|                 out << "(" <<  m_start_expl << ", " << m_end_expl << ")"; | ||||
|             else { | ||||
|                 if (m_start_expl != -1) { | ||||
|                     out << "(" << m_start_expl << ")"; | ||||
|                 } | ||||
|                 else if (m_end_expl != -1) { | ||||
|                     out << "(" << m_end_expl << ")"; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|     stacked_map<T, endpoint>                 m_endpoints; | ||||
|     stacked_value<bool>                      m_empty; | ||||
|     typedef typename std::map<T, endpoint>::iterator iter; | ||||
|     typedef typename std::map<T, endpoint>::const_iterator const_iter; | ||||
|     typedef typename std::map<T, endpoint>::reverse_iterator riter; | ||||
|      | ||||
| public: | ||||
|     // the default constructor creates a set containing all integer numbers
 | ||||
|     integer_domain() : integer_domain(false) {} | ||||
|  | @ -28,10 +62,10 @@ public: | |||
|     // otherwise it creates an empty set
 | ||||
|     integer_domain(bool is_empty) : m_empty(is_empty) { | ||||
| #if Z3DEBUG | ||||
|         if (!is_empty) { | ||||
|             for (int i = 0; i <= 100; i++) | ||||
|                 m_domain.insert(i); | ||||
|         } | ||||
|         // if (!is_empty) {
 | ||||
|         //     for (int i = 0; i <= 100; i++)
 | ||||
|         //         m_domain.insert(i);
 | ||||
|         // }
 | ||||
| #endif | ||||
|     } | ||||
|      | ||||
|  | @ -39,15 +73,15 @@ public: | |||
|         m_empty = false; | ||||
|         m_endpoints.clear(); | ||||
| #if Z3DEBUG | ||||
|         for (int i = 0; i <= 100; i++) | ||||
|             m_domain.insert(i); | ||||
|         // for (int i = 0; i <= 100; i++)
 | ||||
|         //     m_domain.insert(i);
 | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
|     // copy constructor 
 | ||||
|     integer_domain(const integer_domain<T> & t) : | ||||
| #if Z3DEBUG | ||||
|         m_domain(t.m_domain), | ||||
|         //        m_domain(t.m_domain),
 | ||||
| #endif | ||||
|         m_endpoints(t.m_endpoints), | ||||
|         m_empty(t.m_empty) | ||||
|  | @ -57,11 +91,11 @@ public: | |||
|     // needed for debug only
 | ||||
|     void restore_domain() { | ||||
| #if Z3DEBUG | ||||
|         for (int i = 0; i <= 100; i++) | ||||
|             if (contains(i)) | ||||
|                 m_domain.insert(i); | ||||
|             else | ||||
|                 m_domain.erase(i); | ||||
|         // for (int i = 0; i <= 100; i++)
 | ||||
|         //     if (contains(i))
 | ||||
|         //         m_domain.insert(i);
 | ||||
|         //     else
 | ||||
|         //         m_domain.erase(i);
 | ||||
| #endif | ||||
|     } | ||||
|      | ||||
|  | @ -86,6 +120,7 @@ public: | |||
|             return true; | ||||
|         return is_proper_start(l); | ||||
|     } | ||||
| 
 | ||||
|     void handle_right_point_in_union(const_iter &r, const T &y) { | ||||
|         if (pos(r) == y) { | ||||
|             if (is_proper_start(r)) | ||||
|  | @ -130,97 +165,98 @@ public: | |||
|     } | ||||
| 
 | ||||
|     void unite_with_interval(const T& x, const T& y) { | ||||
|         TRACE("disj_intervals", tout << "unite_with_interval(" << x << ", " << y << ")\n";); | ||||
| #if Z3DEBUG | ||||
|         for (int i = std::max(x, 0); i <= std::min(100, y); i++) | ||||
|             m_domain.insert(i); | ||||
| #endif | ||||
|         lp_assert(false); | ||||
|         //         TRACE("disj_intervals", tout << "unite_with_interval(" << x << ", " << y << ")\n";);
 | ||||
|         // #if Z3DEBUG
 | ||||
|         //         // for (int i = std::max(x, 0); i <= std::min(100, y); i++)
 | ||||
|         //         //     m_domain.insert(i);
 | ||||
|         // #endif
 | ||||
| 
 | ||||
|         lp_assert(x <= y); | ||||
|         if (x == y) { | ||||
|             unite_with_one_point_interval(x); | ||||
|             return; | ||||
|         } | ||||
|         //         lp_assert(x <= y);
 | ||||
|         //         if (x == y) {
 | ||||
|         //             unite_with_one_point_interval(x);
 | ||||
|         //             return;
 | ||||
|         //         }
 | ||||
| 
 | ||||
|         const_iter l, r; | ||||
|         bool neg_inf, pos_inf; | ||||
|         bool found_left_point = get_left_point(x, neg_inf, l); | ||||
|         bool found_right_point = get_right_point(y, pos_inf, r); | ||||
|         m_empty = false; | ||||
|         //         const_iter l, r;
 | ||||
|         //         bool neg_inf, pos_inf;
 | ||||
|         //         bool found_left_point = get_left_point(x, neg_inf, l);
 | ||||
|         //         bool found_right_point = get_right_point(y, pos_inf, r);
 | ||||
|         //         m_empty = false;
 | ||||
| 
 | ||||
|         if (!found_left_point) { | ||||
|             if (!found_right_point) { | ||||
|                 m_endpoints.clear(); | ||||
|                 set_start(x); | ||||
|                 set_end(y); | ||||
|                 return; | ||||
|             } | ||||
|             // found_right_point is true
 | ||||
|             if (pos_inf) { | ||||
|                 m_endpoints.clear(); | ||||
|                 set_start(x); | ||||
|                 return; | ||||
|             } | ||||
|             remove_from_the_left(y); | ||||
|         //         if (!found_left_point) {
 | ||||
|         //             if (!found_right_point) {
 | ||||
|         //                 m_endpoints.clear();
 | ||||
|         //                 set_start(x);
 | ||||
|         //                 set_end(y);
 | ||||
|         //                 return;
 | ||||
|         //             }
 | ||||
|         //             // found_right_point is true
 | ||||
|         //             if (pos_inf) {
 | ||||
|         //                 m_endpoints.clear();
 | ||||
|         //                 set_start(x);
 | ||||
|         //                 return;
 | ||||
|         //             }
 | ||||
|         //             remove_from_the_left(y);
 | ||||
|                          | ||||
|             if (pos(m_endpoints.begin()) == y || pos(m_endpoints.begin()) == y + 1) { | ||||
|                 if (is_proper_start(m_endpoints.begin())) | ||||
|                     m_endpoints.erase(m_endpoints.begin()); | ||||
|                 else  | ||||
|                     set_end(pos(m_endpoints.begin())); | ||||
|                 set_start(x); | ||||
|             } | ||||
|             else { | ||||
|                 lp_assert(pos(m_endpoints.begin()) > y + 1); | ||||
|                 if (is_start(m_endpoints.begin())) | ||||
|                     set_end(y); | ||||
|                 set_start(x); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         //             if (pos(m_endpoints.begin()) == y || pos(m_endpoints.begin()) == y + 1) {
 | ||||
|         //                 if (is_proper_start(m_endpoints.begin()))
 | ||||
|         //                     m_endpoints.erase(m_endpoints.begin());
 | ||||
|         //                 else 
 | ||||
|         //                     set_end(pos(m_endpoints.begin()));
 | ||||
|         //                 set_start(x);
 | ||||
|         //             }
 | ||||
|         //             else {
 | ||||
|         //                 lp_assert(pos(m_endpoints.begin()) > y + 1);
 | ||||
|         //                 if (is_start(m_endpoints.begin()))
 | ||||
|         //                     set_end(y);
 | ||||
|         //                 set_start(x);
 | ||||
|         //             }
 | ||||
|         //             return;
 | ||||
|         //         }
 | ||||
| 
 | ||||
|         lp_assert(found_left_point); | ||||
|         if (!found_right_point) { | ||||
|             bool neg_inf = has_neg_inf(); | ||||
|             remove_from_the_right(x); | ||||
|             if (m_endpoints.empty()) { | ||||
|                 if (!neg_inf) | ||||
|                     set_start_end(x, y); | ||||
|                 else | ||||
|                     set_end(y); | ||||
|                 return; | ||||
|             } | ||||
|             if (pos(m_endpoints.rbegin()) == x || pos(m_endpoints.rbegin()) == x - 1) { | ||||
|                 if (is_proper_end(m_endpoints.rbegin())) { | ||||
|                     m_endpoints.erase(m_endpoints.rbegin()); | ||||
|                 } | ||||
|                 else if (is_one_point_interval(m_endpoints.rbegin())) { | ||||
|                     set_start(pos(m_endpoints.rbegin())); | ||||
|                 } | ||||
|                 set_end(y); | ||||
|             } | ||||
|             else { | ||||
|                 if (is_end(m_endpoints.rbegin())) { | ||||
|                     set_start(x); | ||||
|                     set_end(y); | ||||
|                 } | ||||
|                 else { | ||||
|                     set_end(y); | ||||
|                 } | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         //         lp_assert(found_left_point);
 | ||||
|         //         if (!found_right_point) {
 | ||||
|         //             bool neg_inf = has_neg_inf();
 | ||||
|         //             remove_from_the_right(x);
 | ||||
|         //             if (m_endpoints.empty()) {
 | ||||
|         //                 if (!neg_inf)
 | ||||
|         //                     set_start_end(x, y);
 | ||||
|         //                 else
 | ||||
|         //                     set_end(y);
 | ||||
|         //                 return;
 | ||||
|         //             }
 | ||||
|         //             if (pos(m_endpoints.rbegin()) == x || pos(m_endpoints.rbegin()) == x - 1) {
 | ||||
|         //                 if (is_proper_end(m_endpoints.rbegin())) {
 | ||||
|         //                     m_endpoints.erase(m_endpoints.rbegin());
 | ||||
|         //                 }
 | ||||
|         //                 else if (is_one_point_interval(m_endpoints.rbegin())) {
 | ||||
|         //                     set_start(pos(m_endpoints.rbegin()));
 | ||||
|         //                 }
 | ||||
|         //                 set_end(y);
 | ||||
|         //             }
 | ||||
|         //             else {
 | ||||
|         //                 if (is_end(m_endpoints.rbegin())) {
 | ||||
|         //                     set_start(x);
 | ||||
|         //                     set_end(y);
 | ||||
|         //                 }
 | ||||
|         //                 else {
 | ||||
|         //                     set_end(y);
 | ||||
|         //                 }
 | ||||
|         //             }
 | ||||
|         //             return;
 | ||||
|         //         }
 | ||||
| 
 | ||||
|         // found_right_point and found_left_point
 | ||||
|         if (!neg_inf) | ||||
|             handle_left_point_in_union(l, x, y); | ||||
|         else { | ||||
|             remove_from_the_left(y); | ||||
|         } | ||||
|         if (!pos_inf) | ||||
|             handle_right_point_in_union(r, y); | ||||
|         else | ||||
|             remove_from_the_right(x); | ||||
|         //         // found_right_point and found_left_point
 | ||||
|         //         if (!neg_inf)
 | ||||
|         //             handle_left_point_in_union(l, x, y);
 | ||||
|         //         else {
 | ||||
|         //             remove_from_the_left(y);
 | ||||
|         //         }
 | ||||
|         //         if (!pos_inf)
 | ||||
|         //             handle_right_point_in_union(r, y);
 | ||||
|         //         else
 | ||||
|         //             remove_from_the_right(x);
 | ||||
|     } | ||||
| 
 | ||||
|     bool has_pos_inf() const { | ||||
|  | @ -231,7 +267,7 @@ public: | |||
|             return true; | ||||
|          | ||||
|         lp_assert(m_endpoints.rbegin() != m_endpoints.rend()); | ||||
|         return m_endpoints.rbegin()->second == 0; | ||||
|         return m_endpoints.rbegin()->second.kind() == endpoint_kind::START; | ||||
|     } | ||||
| 
 | ||||
|     bool has_neg_inf() const { | ||||
|  | @ -241,7 +277,7 @@ public: | |||
|         if (m_endpoints.empty()) | ||||
|             return true; | ||||
|         auto it = m_endpoints.begin(); | ||||
|         return is_proper_end(it->second);//m_endpoints.begin());
 | ||||
|         return is_proper_end(it->second.kind());//m_endpoints.begin());
 | ||||
|     } | ||||
|      | ||||
|     bool is_correct() const { | ||||
|  | @ -272,7 +308,7 @@ public: | |||
|                     return false; | ||||
|                 } | ||||
|             }  | ||||
|             if (t.second == 2) { | ||||
|             if (t.second.kind() == endpoint_kind::STEND) { | ||||
|                 expect_end = false; // swallow a point interval
 | ||||
|             } | ||||
|             else { | ||||
|  | @ -285,12 +321,12 @@ public: | |||
|             prev_x = t.first; | ||||
|         } | ||||
| #if Z3DEBUG | ||||
|         for (int i = 0; i <= 100; i++ ) { | ||||
|             if ( (m_domain.find(i) != m_domain.end()) != contains(i)) { | ||||
|                 TRACE("disj_intervals", tout << "incorrect value of contains(" << i << ") is = " << contains(i) << std::endl;); | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         // for (int i = 0; i <= 100; i++ ) {
 | ||||
|         //     if ( (m_domain.find(i) != m_domain.end()) != contains(i)) {
 | ||||
|         //         TRACE("disj_intervals", tout << "incorrect value of contains(" << i << ") is = " << contains(i) << std::endl;);
 | ||||
|         //         return false;
 | ||||
|         //     }
 | ||||
|         // }
 | ||||
| #endif | ||||
|         return true; | ||||
|     } | ||||
|  | @ -307,45 +343,54 @@ public: | |||
|         bool first = true; | ||||
|         for (auto t : m_endpoints()) { | ||||
|             if (first) { | ||||
|                 if (t.second == 1) { | ||||
|                     out << "[-oo," << t.first << "]"; | ||||
|                 if (t.second.kind() == endpoint_kind::END) { | ||||
|                     out << "[-oo," << t.first; t.second.print(out); out << "]"; | ||||
|                 } | ||||
|                 else if (t.second.kind() == endpoint_kind::START) { | ||||
|                     out << "[" << t.first; t.second.print(out); out << ","; | ||||
|                 } else if (t.second.kind() == endpoint_kind::STEND) { | ||||
|                     out << "[" << t.first; t.second.print(out); out << "]"; | ||||
|                 } | ||||
|                 else if (t.second == 0) | ||||
|                     out << "[" << t.first << ","; | ||||
|                 else if (t.second == 2) | ||||
|                     out << "[" << t.first << "]"; | ||||
|                 first = false; | ||||
|             } else { | ||||
|                 if (t.second==0) | ||||
|                     out << "[" << t.first << ","; | ||||
|                 else if (t.second == 1) | ||||
|                     out << t.first << "]"; | ||||
|                 else if (t.second == 2) | ||||
|                     out << "[" << t.first << "]"; | ||||
|                 if (t.second.kind() == endpoint_kind::START) { | ||||
|                     out << "[" << t.first; t.second.print(out); out << ","; | ||||
|                 } | ||||
|                 else if (t.second.kind() == endpoint_kind::END) { | ||||
|                     out << t.first; t.second.print(out); out << "]"; | ||||
|                 } | ||||
|                 else if (t.second.kind() == endpoint_kind::STEND) { | ||||
|                     out << "[" << t.first; t.second.print(out); out << "]";; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if (has_pos_inf()) | ||||
|             out << "oo]"; | ||||
|          | ||||
|         out << "\n"; | ||||
|     } | ||||
|      | ||||
|     void push() { m_endpoints.push(); m_empty.push(); } | ||||
|     void pop() { m_endpoints.pop(); m_empty.pop(); } | ||||
|     void pop(unsigned k) { while(k--) pop(); } | ||||
|      | ||||
| 
 | ||||
|     bool intersect_with_bound(const T & x, bool is_lower, unsigned explanation) { | ||||
|         return is_lower? intersect_with_lower_bound(x, explanation) : intersect_with_upper_bound(x, explanation); | ||||
|     } | ||||
|     // we intersect the existing set with the half open to the right interval
 | ||||
|     void intersect_with_lower_bound(const T& x) { | ||||
|     // returns true if the domain changes
 | ||||
|     bool intersect_with_lower_bound(const T& x, unsigned explanation) { | ||||
| #ifdef Z3DEBUG | ||||
|         for (int i = 0; i < x; i++) | ||||
|             m_domain.erase(i); | ||||
|         // for (int i = 0; i < x; i++)
 | ||||
|         //     m_domain.erase(i);
 | ||||
| #endif | ||||
|         TRACE("disj_intervals", tout << "intersect_with_lower_bound(" << x << ")\n";); | ||||
| 
 | ||||
|         if (m_empty) | ||||
|             return; | ||||
|             return false; | ||||
|         if (m_endpoints.empty()) { | ||||
|             set_start(x); | ||||
|             return; | ||||
|             set_start(x, explanation); | ||||
|             return true; | ||||
|         } | ||||
|         bool pos_inf = has_pos_inf(); | ||||
|         auto it = m_endpoints.begin(); | ||||
|  | @ -356,70 +401,104 @@ public: | |||
|         if (m_endpoints.empty()) { | ||||
|             if (!pos_inf) { | ||||
|                 m_empty = true; | ||||
|                 return; | ||||
|                 return true; | ||||
|             }  | ||||
|             set_start(x); | ||||
|             return; | ||||
|             set_start(x, explanation); | ||||
|             return true; | ||||
|         } | ||||
|         lp_assert(pos(it) >= x); | ||||
|         if (pos(it) == x) { | ||||
|             if (is_proper_end(it)) | ||||
|                 set_one_point_interval(x);			 | ||||
|             if (is_proper_end(it)) { | ||||
|                 set_start(x, explanation); | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         else { // x(it) > x
 | ||||
|             if (is_proper_end(it)) { | ||||
|                 set_start(x); | ||||
|                 set_start(x, explanation); | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| public: | ||||
|     bool intersection_with_upper_bound_is_empty(const T& x) const { | ||||
|         if (has_neg_inf()) | ||||
|             return false; | ||||
|         if (m_empty) | ||||
|             return true; | ||||
|         T b; | ||||
|         lp_assert(get_lower_bound(b)); | ||||
|         get_lower_bound(b); | ||||
|         return x < b; | ||||
|     } | ||||
| 
 | ||||
|     bool intersection_with_lower_bound_is_empty(const T& x) const { | ||||
|         if (has_pos_inf()) | ||||
|             return false; | ||||
|         if (m_empty) | ||||
|             return true; | ||||
|         T b; | ||||
|         lp_assert(get_upper_bound(b)); | ||||
|         get_upper_bound(b); | ||||
|         return x > b; | ||||
|     } | ||||
| 
 | ||||
|     // we intersect the existing set with the half open interval
 | ||||
|     void intersect_with_upper_bound(const T& x) { | ||||
|     // returns true if there is a change
 | ||||
|     bool intersect_with_upper_bound(const T& x, unsigned explanation) { | ||||
| #ifdef Z3DEBUG | ||||
|         for (int i = 100; i > x; i--) | ||||
|             m_domain.erase(i); | ||||
|         // for (int i = 100; i > x; i--)
 | ||||
|         //     m_domain.erase(i);
 | ||||
| #endif | ||||
|         TRACE("disj_intervals", tout << "intersect_with_upper_bound(" << x << ")\n";); | ||||
|         if (m_empty) | ||||
|             return; | ||||
|             return false; | ||||
|         if (m_endpoints.empty()) { | ||||
|             set_end(x); | ||||
|             return; | ||||
|             set_end(x, explanation); | ||||
|             return true; | ||||
|         } | ||||
|         bool neg_inf = has_neg_inf(); | ||||
|         auto it = m_endpoints.rbegin(); | ||||
| 
 | ||||
|         bool change = false; | ||||
|         while (!m_endpoints.empty() && pos(it) > x) { | ||||
|             m_endpoints.erase(std::prev(m_endpoints.end())); | ||||
|             it = m_endpoints.rbegin(); | ||||
|             change = true; | ||||
|         } | ||||
|         if (m_endpoints.empty()) { | ||||
|             if (!neg_inf) { | ||||
|                 m_empty = true; | ||||
|                 return; | ||||
|                 return true; | ||||
|             } | ||||
|             set_end(x); | ||||
|             set_end(x, explanation); | ||||
|             change = true; | ||||
|         } | ||||
|         lp_assert(pos(it) <= x); | ||||
|         if (pos(it) == x) { | ||||
|             if (is_one_point_interval(it)) {}  | ||||
|             else if (is_proper_end(it)) {} | ||||
|             else {// is_proper_start(it->second)
 | ||||
|                 set_one_point_interval(x); | ||||
|                 set_end(x, explanation); | ||||
|                 change = true; | ||||
|             } | ||||
|         } | ||||
|         else { // pos(it) < x} 
 | ||||
|             if (is_proper_start(it)) | ||||
|                 set_end(x); | ||||
|             if (is_proper_start(it)) { | ||||
|                 set_end(x, explanation); | ||||
|                 change = true; | ||||
|             } | ||||
|         } | ||||
|         lp_assert(is_correct()); | ||||
|         return change; | ||||
|     } | ||||
| public: | ||||
|     void intersect_with_interval(const T& x, const T & y) { | ||||
| #ifdef Z3DEBUG | ||||
|         for (int i = 0; i <= 100; i++) | ||||
|             if (i < x || i > y) | ||||
|                 m_domain.erase(i); | ||||
|         // for (int i = 0; i <= 100; i++)
 | ||||
|         //     if (i < x || i > y)
 | ||||
|         //         m_domain.erase(i);
 | ||||
| #endif | ||||
| 
 | ||||
|         TRACE("disj_intervals", tout << "intersect_with_interval(" << x << ", " << y <<")\n";); | ||||
|  | @ -432,110 +511,108 @@ public: | |||
| 
 | ||||
|     // add an intervar [x, inf]
 | ||||
|     void unite_with_interval_x_pos_inf(const T& x) { | ||||
|         if (contains_all()) | ||||
|             return; | ||||
| #if Z3DEBUG | ||||
|         for (int i = x; i <= 100; i++) | ||||
|             m_domain.insert(i); | ||||
| #endif | ||||
|         TRACE("disj_intervals", tout << "unite_with_interval_x_pos_inf(" << x << ")\n";); | ||||
|         if (m_empty) { | ||||
|             set_start(x); | ||||
|             m_empty = false; | ||||
|             return; | ||||
|         } | ||||
|         bool neg_inf = has_neg_inf(); | ||||
|         remove_from_the_right(x); | ||||
|         if (m_endpoints.empty()) { | ||||
|             if (!neg_inf) | ||||
|                 set_start(x); | ||||
|             return; | ||||
|         } | ||||
|         auto it = m_endpoints.rbegin(); | ||||
|         lp_assert(pos(it) <= x); | ||||
|         if (pos(it) == x) { | ||||
|             if (is_proper_end(it)) { | ||||
|                 m_endpoints.erase(x); | ||||
|             } else { | ||||
|                 set_start(x); | ||||
|             } | ||||
|         } else if (pos(it) == x - 1 && is_end(it)) { | ||||
|             if (is_proper_start(it)) { | ||||
|                 // do nothing
 | ||||
|             } | ||||
|             else if (is_proper_end(it)) { | ||||
|                 m_endpoints.erase(it); | ||||
|             } | ||||
|             else { | ||||
|                 lp_assert(is_one_point_interval(it)); | ||||
|                 set_start(it); | ||||
|             } | ||||
|         } else { | ||||
|             if (!has_pos_inf()) | ||||
|                 set_start(x); | ||||
|         } | ||||
|         lp_assert(false); | ||||
|         //         if (contains_all())
 | ||||
|         //             return;
 | ||||
|         // #if Z3DEBUG
 | ||||
|         //         // for (int i = x; i <= 100; i++)
 | ||||
|         //         //     m_domain.insert(i);
 | ||||
|         // #endif
 | ||||
|         //         TRACE("disj_intervals", tout << "unite_with_interval_x_pos_inf(" << x << ")\n";);
 | ||||
|         //         if (m_empty) {
 | ||||
|         //             set_start(x);
 | ||||
|         //             m_empty = false;
 | ||||
|         //             return;
 | ||||
|         //         }
 | ||||
|         //         bool neg_inf = has_neg_inf();
 | ||||
|         //         remove_from_the_right(x);
 | ||||
|         //         if (m_endpoints.empty()) {
 | ||||
|         //             if (!neg_inf)
 | ||||
|         //                 set_start(x);
 | ||||
|         //             return;
 | ||||
|         //         }
 | ||||
|         //         auto it = m_endpoints.rbegin();
 | ||||
|         //         lp_assert(pos(it) <= x);
 | ||||
|         //         if (pos(it) == x) {
 | ||||
|         //             if (is_proper_end(it)) {
 | ||||
|         //                 m_endpoints.erase(x);
 | ||||
|         //             } else {
 | ||||
|         //                 set_start(x);
 | ||||
|         //             }
 | ||||
|         //         } else if (pos(it) == x - 1 && is_end(it)) {
 | ||||
|         //             if (is_proper_start(it)) {
 | ||||
|         //                 // do nothing
 | ||||
|         //             }
 | ||||
|         //             else if (is_proper_end(it)) {
 | ||||
|         //                 m_endpoints.erase(it);
 | ||||
|         //             }
 | ||||
|         //             else {
 | ||||
|         //                 lp_assert(is_one_point_interval(it));
 | ||||
|         //                 set_start(it);
 | ||||
|         //             }
 | ||||
|         //         } else {
 | ||||
|         //             if (!has_pos_inf())
 | ||||
|         //                 set_start(x);
 | ||||
|         //         }
 | ||||
|     } | ||||
| 
 | ||||
|     // add an interval [-inf, x]
 | ||||
|     void unite_with_interval_neg_inf_x(const T& x) { | ||||
| #if Z3DEBUG | ||||
|         for (int i = 0; i <= x; i++) | ||||
|             m_domain.insert(i); | ||||
| #endif | ||||
|         TRACE("disj_intervals", tout << "unite_with_interval_neg_inf_x(" << x << ")\n";); | ||||
|         if (m_empty) { | ||||
|             set_end(x); | ||||
|             m_empty = false; | ||||
|             return; | ||||
|         } | ||||
|         bool pos_inf; | ||||
|         const_iter r; | ||||
|         bool found_right_point = get_right_point(x, pos_inf, r); | ||||
|         if (!found_right_point) { | ||||
|             m_endpoints.clear(); | ||||
|             set_end(x); | ||||
|             return; | ||||
|         } | ||||
|         if (pos_inf) { | ||||
|             m_endpoints.clear(); | ||||
|             return; | ||||
|         } | ||||
|         lp_assert(pos(r) >= x); | ||||
|         if (pos(r) == x || pos(r) == x + 1) { | ||||
|             if (is_proper_start(r)) | ||||
|                 erase(r); | ||||
|             else if (is_one_point_interval(r)) { | ||||
|                 set_end(pos(r)); | ||||
|             } // do nothing for the proper end
 | ||||
|         } else { | ||||
|             if (!is_proper_end(r)) | ||||
|                 set_end(x); | ||||
|         } | ||||
|         lp_assert(false); // not implemented
 | ||||
|         // #if Z3DEBUG
 | ||||
|         //         // for (int i = 0; i <= x; i++)
 | ||||
|         //         //     m_domain.insert(i);
 | ||||
|         // #endif
 | ||||
|         //         TRACE("disj_intervals", tout << "unite_with_interval_neg_inf_x(" << x << ")\n";);
 | ||||
|         //         if (m_empty) {
 | ||||
|         //             set_end(x);
 | ||||
|         //             m_empty = false;
 | ||||
|         //             return;
 | ||||
|         //         }
 | ||||
|         //         bool pos_inf;
 | ||||
|         //         const_iter r;
 | ||||
|         //         bool found_right_point = get_right_point(x, pos_inf, r);
 | ||||
|         //         if (!found_right_point) {
 | ||||
|         //             m_endpoints.clear();
 | ||||
|         //             set_end(x);
 | ||||
|         //             return;
 | ||||
|         //         }
 | ||||
|         //         if (pos_inf) {
 | ||||
|         //             m_endpoints.clear();
 | ||||
|         //             return;
 | ||||
|         //         }
 | ||||
|         //         lp_assert(pos(r) >= x);
 | ||||
|         //         if (pos(r) == x || pos(r) == x + 1) {
 | ||||
|         //             if (is_proper_start(r))
 | ||||
|         //                 erase(r);
 | ||||
|         //             else if (is_one_point_interval(r)) {
 | ||||
|         //                 set_end(pos(r));
 | ||||
|         //             } // do nothing for the proper end
 | ||||
|         //         } else {
 | ||||
|         //             if (!is_proper_end(r))
 | ||||
|         //                 set_end(x);
 | ||||
|         //         }
 | ||||
|          | ||||
|         while (!m_endpoints.empty() && m_endpoints.begin()->first < x) { | ||||
|             m_endpoints.erase(m_endpoints.begin()); | ||||
|         } | ||||
|         lp_assert(is_correct()); | ||||
|         //         while (!m_endpoints.empty() && m_endpoints.begin()->first < x) {
 | ||||
|         //             m_endpoints.erase(m_endpoints.begin());
 | ||||
|         //         }
 | ||||
|         //         lp_assert(is_correct());
 | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     bool is_start(char x) const { return x == 0 || x == 2; } | ||||
|     bool is_start(endpoint_kind x) const { return x == endpoint_kind::START || x == endpoint_kind::STEND; } | ||||
|     bool is_start(const iter & it) const { return is_start(it->second);  } | ||||
|     bool is_start(const const_iter & it) const { return is_start(it->second);  } | ||||
|     bool is_start(const riter & it) const { | ||||
|         return is_start(it->second); | ||||
|     } | ||||
|     bool is_end(char x) const { return x == 1 || x == 2; } | ||||
|     bool is_end(const iter & it) const { | ||||
|         return is_end(it->second); | ||||
|     } | ||||
|     bool is_end(const const_iter & it) const { | ||||
|         return is_end(it->second); | ||||
|     } | ||||
|     bool is_end(const riter & it) const { | ||||
|         return is_end(it->second); | ||||
|     } | ||||
|     bool is_start(const riter & it) const { return is_start(it->second);  } | ||||
|     bool is_start(const endpoint & e) const { return is_start(e.kind());  } | ||||
|     | ||||
|     bool is_end(endpoint_kind x) const { return x == endpoint_kind::END || x == endpoint_kind::STEND; } | ||||
|     bool is_end(const iter & it) const { return is_end(it->second);  } | ||||
|     bool is_end(const const_iter & it) const { return is_end(it->second); } | ||||
|     bool is_end(const riter & it) const {  return is_end(it->second); } | ||||
|     bool is_end(const endpoint& e) const {  return is_end(e.kind()); } | ||||
| 
 | ||||
|      | ||||
|     T pos(const iter & it) const { | ||||
|         return it->first; | ||||
|     } | ||||
|  | @ -554,22 +631,21 @@ private: | |||
|         return it->second; | ||||
|     } | ||||
| 
 | ||||
|     bool is_proper_start(char x) const { return x == 0; } | ||||
|     bool is_proper_start(endpoint_kind x) const { return x == endpoint_kind::START; } | ||||
|     bool is_proper_start(const riter &x) const { return is_proper_start(x->second);} | ||||
|     bool is_proper_start(const iter &x) const { return is_proper_start(x->second);} | ||||
|     bool is_proper_start(const const_iter &x) const { return is_proper_start(x->second);} | ||||
|     bool is_proper_start(const endpoint &x) const { return is_proper_start(x.kind());} | ||||
|          | ||||
|     bool is_proper_end(char x) const { return x == 1; } | ||||
|     bool is_proper_end(const iter & it) const { return is_proper_end(it->second); } | ||||
|     bool is_proper_end(endpoint_kind x) const { return x == endpoint_kind::END; } | ||||
|     bool is_proper_end(const iter & it) const { return is_proper_end(it->second.kind()); } | ||||
|     bool is_proper_end(const const_iter & it) const { return is_proper_end(it->second); } | ||||
|     bool is_proper_end(const riter & it) const { | ||||
|         return is_proper_end(it->second); | ||||
|     } | ||||
|     bool is_proper_end(const riter & it) const { return is_proper_end(it->second); } | ||||
|     bool is_proper_end(const endpoint & x) const { return is_proper_end(x.kind()); } | ||||
| 
 | ||||
|     bool is_one_point_interval(char x) const { return x == 2; } | ||||
|     bool is_one_point_interval(const iter & it) const { | ||||
|         return is_one_point_interval(it->second); | ||||
|     } | ||||
|     bool is_one_point_interval(const endpoint & x) const { return is_one_point_interval(x.kind()); } | ||||
|     bool is_one_point_interval(endpoint_kind x) const { return x == endpoint_kind::STEND; } | ||||
|     bool is_one_point_interval(const iter & it) const { return is_one_point_interval(it->second); } | ||||
|     bool is_one_point_interval(const const_iter & it) const { | ||||
|         return is_one_point_interval(it->second); | ||||
|     } | ||||
|  | @ -592,41 +668,54 @@ private: | |||
|         m_endpoints.erase(x); | ||||
|     } | ||||
|      | ||||
|     void set_one_point_interval(const T& x) { | ||||
|         m_endpoints[x] = 2; | ||||
|     /*    void set_one_point_interval(const T& x, unsigned explanation) {
 | ||||
|           auto it = m_endpoints().find(x); | ||||
|           set_one_point_interval(it, explanation); | ||||
|           }*/ | ||||
| 
 | ||||
|     void set_start(const_iter &t, unsigned explanation) { | ||||
|         lp_assert(t != m_endpoints.end()); | ||||
|         endpoint e = t->second; | ||||
|         e.m_start_expl = explanation; | ||||
|         m_endpoints[t->first] = e; | ||||
|     } | ||||
| 
 | ||||
|     void set_start(const T& x) { | ||||
|         m_endpoints[x] = 0; | ||||
|     void set_start(const T& x, unsigned explanation) { | ||||
|         endpoint e = get_endpoint(x); | ||||
|         e.m_start_expl = explanation; | ||||
|         m_endpoints[x] = e; | ||||
|     } | ||||
| 
 | ||||
|     void set_start(const iter &t ) { | ||||
|         t->second = 0; | ||||
|     endpoint get_endpoint(const T& x) const { | ||||
|         auto it = m_endpoints().find(x); | ||||
|         if (it == m_endpoints().end()) | ||||
|             return endpoint(); | ||||
|         return it->second; | ||||
|     } | ||||
|      | ||||
|     void set_end(const T& x, unsigned expl) { | ||||
|         endpoint e = get_endpoint(x); | ||||
|         e.m_end_expl = expl; | ||||
|         m_endpoints[x] = e; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void set_start(riter &t ) { | ||||
|         t->second = 0; | ||||
|     void set_end(const_iter& t, unsigned expl) { | ||||
|         endpoint e = t->second; | ||||
|         e.m_end_expl = expl; | ||||
|         m_endpoints[t->first] =  e; | ||||
|     } | ||||
| 
 | ||||
|     void set_end(const T& x) { | ||||
|         m_endpoints[x] = 1; | ||||
|     void set_end(riter& t, unsigned explanation) { | ||||
|         endpoint e = t->second; | ||||
|         e.m_end_expl = expl; | ||||
|         m_endpoints[t->first] =  e; | ||||
|     } | ||||
|     void set_end(const iter& t) { | ||||
|         t->second = 1; | ||||
|     } | ||||
| 
 | ||||
|     void set_end(riter& t) { | ||||
|         t->second = 1; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| private: | ||||
|     void set_start_end(const T& x, const T & y) { | ||||
|         set_start(x); | ||||
|         set_end(y); | ||||
|     } | ||||
|     /*    void set_start_end(const T& x, const T & y, unsigned expl) {
 | ||||
|           set_start(x, expl); | ||||
|           set_end(y, expl); | ||||
|           }*/ | ||||
| 
 | ||||
|     void unite_with_one_point_interval(const T &x) { | ||||
|         TRACE("disj_intervals", tout << "unite_with_one_point_interval(" << x << ")\n";); | ||||
|  | @ -855,6 +944,18 @@ private: | |||
|         } | ||||
|     } | ||||
| public: | ||||
|     bool get_lower_bound_with_expl(T& b, unsigned & expl) const { | ||||
|         if (m_empty) | ||||
|             return false; | ||||
|         if (has_neg_inf()) | ||||
|             return false; | ||||
|         expl = m_endpoints.begin()->second.m_start_expl; | ||||
|         if (expl == static_cast<unsigned>(-1)) | ||||
|             return false; | ||||
|         b = pos(m_endpoints.begin()); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     bool get_lower_bound(T& b) const { | ||||
|         if (m_empty) | ||||
|             return false; | ||||
|  | @ -864,6 +965,45 @@ public: | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     int get_lower_bound_expl() const { | ||||
|         if (m_empty) | ||||
|             return -1; | ||||
|         if (has_neg_inf()) | ||||
|             return -1; | ||||
|         return m_endpoints.begin()->second.m_start_expl; | ||||
|     } | ||||
| 
 | ||||
|     int get_upper_bound_expl() const { | ||||
|         if (m_empty) | ||||
|             return -1; | ||||
|         if (has_pos_inf()) | ||||
|             return -1; | ||||
|         return m_endpoints.rbegin()->second.m_end_expl; | ||||
|     } | ||||
|      | ||||
|     bool get_upper_bound_with_expl(T& b, unsigned & expl) const { | ||||
|         if (m_empty) | ||||
|             return false; | ||||
|         if (has_pos_inf()) | ||||
|             return false; | ||||
|         expl = m_endpoints.rbegin()->second.m_end_expl; | ||||
|         if (expl == static_cast<unsigned>(-1)) | ||||
|             return false; | ||||
|         b = m_endpoints.rbegin()->first; | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     bool get_upper_bound_and_kind_with_expl(T& b, endpoint_kind & kind, unsigned & expl) const { | ||||
|         if (m_empty) | ||||
|             return false; | ||||
|         if (has_pos_inf()) | ||||
|             return false; | ||||
|         b = m_endpoints.rbegin()->first; | ||||
|         kind = m_endpoints.rbegin()->second.kind(); | ||||
|         expl = m_endpoints.rbegin()->second.m_explanation; | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     bool get_upper_bound(T& b) const { | ||||
|         if (m_empty) | ||||
|             return false; | ||||
|  | @ -872,5 +1012,39 @@ public: | |||
|         b = m_endpoints.rbegin()->first; | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     bool is_empty() const { return m_empty; } | ||||
| 
 | ||||
|     bool is_fixed() const { | ||||
|         if (has_pos_inf() || has_neg_inf()) | ||||
|             return false; | ||||
|         T l; | ||||
|         get_lower_bound(l); | ||||
|         T u; | ||||
|         get_upper_bound(u); | ||||
|         return l==u; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     bool improves_with_lower_bound(const T & v) const { | ||||
|         T b; | ||||
|         bool lower_bound_exists = get_lower_bound(b); | ||||
|         return (!lower_bound_exists || v > b) && | ||||
|             !intersection_with_lower_bound_is_empty(v); | ||||
|     } | ||||
| 
 | ||||
|     bool improves_with_upper_bound(const T & v) const { | ||||
|         T b; | ||||
|         bool upper_bound_exists = get_upper_bound(b); | ||||
|         return (!upper_bound_exists || v < b) && | ||||
|             !intersection_with_upper_bound_is_empty(v); | ||||
|     } | ||||
|      | ||||
|     // returns true if adding the bound b narrows the domain, but does not make it empty
 | ||||
|     bool improves(const T & v, bool is_lower_bound) const { | ||||
|         if (is_lower_bound) | ||||
|             return improves_with_lower_bound(v); | ||||
|         return improves_with_upper_bound(v); | ||||
|     } | ||||
| }; | ||||
| } | ||||
|  |  | |||
|  | @ -22,4 +22,4 @@ Revision History: | |||
| #include <string> | ||||
| #include "util/vector.h" | ||||
| #include <functional> | ||||
| #include "util/lp/lar_core_solver.hpp" | ||||
| #include "util/lp/lar_core_solver_def.h" | ||||
|  | @ -50,7 +50,7 @@ public: | |||
|     stacked_vector<column_type> m_column_types; | ||||
|     // r - solver fields, for rational numbers
 | ||||
|     vector<numeric_pair<mpq>> m_r_x; // the solution
 | ||||
|     stacked_vector<numeric_pair<mpq>> m_r_low_bounds; | ||||
|     stacked_vector<numeric_pair<mpq>> m_r_lower_bounds; | ||||
|     stacked_vector<numeric_pair<mpq>> m_r_upper_bounds; | ||||
|     static_matrix<mpq, numeric_pair<mpq>> m_r_A; | ||||
|     stacked_vector<unsigned> m_r_pushed_basis; | ||||
|  | @ -62,7 +62,7 @@ public: | |||
|      | ||||
|     // d - solver fields, for doubles
 | ||||
|     vector<double> m_d_x; // the solution in doubles
 | ||||
|     vector<double> m_d_low_bounds; | ||||
|     vector<double> m_d_lower_bounds; | ||||
|     vector<double> m_d_upper_bounds; | ||||
|     static_matrix<double, double> m_d_A; | ||||
|     stacked_vector<unsigned> m_d_pushed_basis; | ||||
|  | @ -159,7 +159,7 @@ public: | |||
| 
 | ||||
|     void solve(); | ||||
| 
 | ||||
|     bool low_bounds_are_set() const { return true; } | ||||
|     bool lower_bounds_are_set() const { return true; } | ||||
| 
 | ||||
|     const indexed_vector<mpq> & get_pivot_row() const { | ||||
|         return m_r_solver.m_pivot_row; | ||||
|  | @ -192,7 +192,7 @@ public: | |||
|         // rational
 | ||||
|         if (!settings().use_tableau())  | ||||
|             m_r_A.push(); | ||||
|         m_r_low_bounds.push(); | ||||
|         m_r_lower_bounds.push(); | ||||
|         m_r_upper_bounds.push(); | ||||
|         if (!settings().use_tableau()) { | ||||
|             push_vector(m_r_pushed_basis, m_r_basis); | ||||
|  | @ -234,7 +234,7 @@ public: | |||
|         // rationals
 | ||||
|         if (!settings().use_tableau())  | ||||
|             m_r_A.pop(k); | ||||
|         m_r_low_bounds.pop(k); | ||||
|         m_r_lower_bounds.pop(k); | ||||
|         m_r_upper_bounds.pop(k); | ||||
|         m_column_types.pop(k); | ||||
|          | ||||
|  | @ -276,11 +276,11 @@ public: | |||
|     bool update_xj_and_get_delta(unsigned j, non_basic_column_value_position pos_type, numeric_pair<mpq> & delta) { | ||||
|         auto & x = m_r_x[j]; | ||||
|         switch (pos_type) { | ||||
|         case at_low_bound: | ||||
|             if (x == m_r_solver.m_low_bounds[j]) | ||||
|         case at_lower_bound: | ||||
|             if (x == m_r_solver.m_lower_bounds[j]) | ||||
|                 return false; | ||||
|             delta = m_r_solver.m_low_bounds[j] - x; | ||||
|             m_r_solver.m_x[j] = m_r_solver.m_low_bounds[j]; | ||||
|             delta = m_r_solver.m_lower_bounds[j] - x; | ||||
|             m_r_solver.m_x[j] = m_r_solver.m_lower_bounds[j]; | ||||
|             break; | ||||
|         case at_fixed: | ||||
|         case at_upper_bound: | ||||
|  | @ -300,22 +300,22 @@ public: | |||
|                 delta = m_r_solver.m_upper_bounds[j] - x; | ||||
|                 x = m_r_solver.m_upper_bounds[j]; | ||||
|                 break; | ||||
|             case column_type::low_bound: | ||||
|                 delta = m_r_solver.m_low_bounds[j] - x; | ||||
|                 x = m_r_solver.m_low_bounds[j]; | ||||
|             case column_type::lower_bound: | ||||
|                 delta = m_r_solver.m_lower_bounds[j] - x; | ||||
|                 x = m_r_solver.m_lower_bounds[j]; | ||||
|                 break; | ||||
|             case column_type::boxed: | ||||
|                 if (x > m_r_solver.m_upper_bounds[j]) { | ||||
|                     delta = m_r_solver.m_upper_bounds[j] - x; | ||||
|                     x += m_r_solver.m_upper_bounds[j]; | ||||
|                 } else { | ||||
|                     delta = m_r_solver.m_low_bounds[j] - x; | ||||
|                     x = m_r_solver.m_low_bounds[j]; | ||||
|                     delta = m_r_solver.m_lower_bounds[j] - x; | ||||
|                     x = m_r_solver.m_lower_bounds[j]; | ||||
|                 } | ||||
|                 break; | ||||
|             case column_type::fixed: | ||||
|                 delta = m_r_solver.m_low_bounds[j] - x; | ||||
|                 x = m_r_solver.m_low_bounds[j]; | ||||
|                 delta = m_r_solver.m_lower_bounds[j] - x; | ||||
|                 x = m_r_solver.m_lower_bounds[j]; | ||||
|                 break; | ||||
| 
 | ||||
|             default: | ||||
|  | @ -359,8 +359,8 @@ public: | |||
|             lp_assert(m_r_heading[j] < 0); | ||||
|             auto pos_type = t.second; | ||||
|             switch (pos_type) { | ||||
|             case at_low_bound: | ||||
|                 s.m_x[j] = s.m_low_bounds[j]; | ||||
|             case at_lower_bound: | ||||
|                 s.m_x[j] = s.m_lower_bounds[j]; | ||||
|                 break; | ||||
|             case at_fixed: | ||||
|             case at_upper_bound: | ||||
|  | @ -377,18 +377,18 @@ public: | |||
|                   case column_type::upper_bound: | ||||
|                       s.m_x[j] = s.m_upper_bounds[j]; | ||||
|                       break; | ||||
|                   case column_type::low_bound: | ||||
|                       s.m_x[j] = s.m_low_bounds[j]; | ||||
|                   case column_type::lower_bound: | ||||
|                       s.m_x[j] = s.m_lower_bounds[j]; | ||||
|                       break; | ||||
|                   case column_type::boxed: | ||||
|                       if (settings().random_next() % 2) { | ||||
|                           s.m_x[j] = s.m_low_bounds[j]; | ||||
|                           s.m_x[j] = s.m_lower_bounds[j]; | ||||
|                       } else { | ||||
|                           s.m_x[j] = s.m_upper_bounds[j]; | ||||
|                       } | ||||
|                       break; | ||||
|                   case column_type::fixed: | ||||
|                       s.m_x[j] = s.m_low_bounds[j]; | ||||
|                       s.m_x[j] = s.m_lower_bounds[j]; | ||||
|                       break; | ||||
|                   default: | ||||
|                       lp_assert(false); | ||||
|  | @ -665,27 +665,27 @@ public: | |||
| 
 | ||||
|     void get_bounds_for_double_solver() { | ||||
|         unsigned n = m_n(); | ||||
|         m_d_low_bounds.resize(n); | ||||
|         m_d_lower_bounds.resize(n); | ||||
|         m_d_upper_bounds.resize(n); | ||||
|         double delta = find_delta_for_strict_boxed_bounds().get_double(); | ||||
|         if (delta > 0.000001) | ||||
|             delta = 0.000001; | ||||
|         for (unsigned j = 0; j < n; j++) { | ||||
|             if (low_bound_is_set(j)) { | ||||
|                 const auto & lb = m_r_solver.m_low_bounds[j]; | ||||
|                 m_d_low_bounds[j] = lb.x.get_double() + delta * lb.y.get_double(); | ||||
|             if (lower_bound_is_set(j)) { | ||||
|                 const auto & lb = m_r_solver.m_lower_bounds[j]; | ||||
|                 m_d_lower_bounds[j] = lb.x.get_double() + delta * lb.y.get_double(); | ||||
|             } | ||||
|             if (upper_bound_is_set(j)) { | ||||
|                 const auto & ub = m_r_solver.m_upper_bounds[j]; | ||||
|                 m_d_upper_bounds[j] = ub.x.get_double() + delta * ub.y.get_double(); | ||||
|                 lp_assert(!low_bound_is_set(j) || (m_d_upper_bounds[j] >= m_d_low_bounds[j])); | ||||
|                 lp_assert(!lower_bound_is_set(j) || (m_d_upper_bounds[j] >= m_d_lower_bounds[j])); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void scale_problem_for_doubles( | ||||
|                         static_matrix<double, double>& A,         | ||||
|                         vector<double> & low_bounds, | ||||
|                         vector<double> & lower_bounds, | ||||
|                         vector<double> & upper_bounds) { | ||||
|         vector<double> column_scale_vector; | ||||
|         vector<double> right_side_vector(A.column_count()); | ||||
|  | @ -705,8 +705,8 @@ public: | |||
|                 if (m_r_solver.column_has_upper_bound(j)) { | ||||
|                     upper_bounds[j] /= column_scale_vector[j]; | ||||
|                 } | ||||
|                 if (m_r_solver.column_has_low_bound(j)) { | ||||
|                     low_bounds[j] /= column_scale_vector[j]; | ||||
|                 if (m_r_solver.column_has_lower_bound(j)) { | ||||
|                     lower_bounds[j] /= column_scale_vector[j]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | @ -733,12 +733,12 @@ public: | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     bool low_bound_is_set(unsigned j) const { | ||||
|     bool lower_bound_is_set(unsigned j) const { | ||||
|         switch (m_column_types[j]) { | ||||
|         case column_type::free_column: | ||||
|         case column_type::upper_bound: | ||||
|             return false; | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|         case column_type::boxed: | ||||
|         case column_type::fixed: | ||||
|             return true; | ||||
|  | @ -751,7 +751,7 @@ public: | |||
|     bool upper_bound_is_set(unsigned j) const { | ||||
|         switch (m_column_types[j]) { | ||||
|         case column_type::free_column: | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             return false; | ||||
|         case column_type::upper_bound: | ||||
|         case column_type::boxed: | ||||
|  | @ -780,7 +780,7 @@ public: | |||
|         for (unsigned j = 0; j < m_r_A.column_count(); j++ ) { | ||||
|             if (m_column_types()[j] != column_type::boxed) | ||||
|                 continue; | ||||
|             update_delta(delta, m_r_low_bounds[j], m_r_upper_bounds[j]); | ||||
|             update_delta(delta, m_r_lower_bounds[j], m_r_upper_bounds[j]); | ||||
|         } | ||||
|         return delta; | ||||
|     } | ||||
|  | @ -789,8 +789,8 @@ public: | |||
|     mpq find_delta_for_strict_bounds(const mpq & initial_delta) const{ | ||||
|         mpq delta = initial_delta; | ||||
|         for (unsigned j = 0; j < m_r_A.column_count(); j++ ) { | ||||
|             if (low_bound_is_set(j)) | ||||
|                 update_delta(delta, m_r_low_bounds[j], m_r_x[j]); | ||||
|             if (lower_bound_is_set(j)) | ||||
|                 update_delta(delta, m_r_lower_bounds[j], m_r_x[j]); | ||||
|             if (upper_bound_is_set(j)) | ||||
|                 update_delta(delta, m_r_x[j], m_r_upper_bounds[j]); | ||||
|         } | ||||
|  | @ -813,14 +813,14 @@ public: | |||
|     bool column_is_fixed(unsigned j) const { | ||||
|         return m_column_types()[j] == column_type::fixed || | ||||
|             ( m_column_types()[j] == column_type::boxed && | ||||
|               m_r_solver.m_low_bounds[j] == m_r_solver.m_upper_bounds[j]); | ||||
|               m_r_solver.m_lower_bounds[j] == m_r_solver.m_upper_bounds[j]); | ||||
|     } | ||||
| 
 | ||||
|     const impq & low_bound(unsigned j) const { | ||||
|     const impq & lower_bound(unsigned j) const { | ||||
|         lp_assert(m_column_types()[j] == column_type::fixed || | ||||
|                     m_column_types()[j] == column_type::boxed || | ||||
|                     m_column_types()[j] == column_type::low_bound); | ||||
|         return m_r_low_bounds[j]; | ||||
|                     m_column_types()[j] == column_type::lower_bound); | ||||
|         return m_r_lower_bounds[j]; | ||||
|     } | ||||
| 
 | ||||
|     const impq & upper_bound(unsigned j) const { | ||||
|  |  | |||
|  | @ -54,7 +54,7 @@ lar_core_solver::lar_core_solver( | |||
|                     m_r_heading, | ||||
|                     m_costs_dummy, | ||||
|                     m_column_types(), | ||||
|                     m_r_low_bounds(), | ||||
|                     m_r_lower_bounds(), | ||||
|                     m_r_upper_bounds(), | ||||
|                     settings, | ||||
|                column_names), | ||||
|  | @ -66,7 +66,7 @@ lar_core_solver::lar_core_solver( | |||
|                     m_d_heading, | ||||
|                     m_d_costs_dummy, | ||||
|                     m_column_types(), | ||||
|                     m_d_low_bounds, | ||||
|                     m_d_lower_bounds, | ||||
|                     m_d_upper_bounds, | ||||
|                     settings, | ||||
|                     column_names){} | ||||
|  | @ -108,17 +108,17 @@ void lar_core_solver::init_cost_for_column(unsigned j) { | |||
|         if (x > this->m_upper_bounds[j]) { | ||||
|             this->m_costs[j] = 1; | ||||
|             this->m_infeasibility += x - this->m_upper_bounds[j]; | ||||
|         } else if (x < this->m_low_bounds[j]) { | ||||
|             this->m_infeasibility += this->m_low_bounds[j] - x; | ||||
|         } else if (x < this->m_lower_bounds[j]) { | ||||
|             this->m_infeasibility += this->m_lower_bounds[j] - x; | ||||
|             this->m_costs[j] = -1; | ||||
|         } else { | ||||
|             this->m_costs[j] = numeric_traits<T>::zero(); | ||||
|         } | ||||
|         break; | ||||
|     case low_bound: | ||||
|         if (x < this->m_low_bounds[j]) { | ||||
|     case lower_bound: | ||||
|         if (x < this->m_lower_bounds[j]) { | ||||
|             this->m_costs[j] = -1; | ||||
|             this->m_infeasibility += this->m_low_bounds[j] - x; | ||||
|             this->m_infeasibility += this->m_lower_bounds[j] - x; | ||||
|         } else { | ||||
|             this->m_costs[j] = numeric_traits<T>::zero(); | ||||
|         } | ||||
|  | @ -154,7 +154,7 @@ int lar_core_solver::column_is_out_of_bounds(unsigned j) { | |||
|             return 1; | ||||
|         } | ||||
|         return 0; | ||||
|     case low_bound: | ||||
|     case lower_bound: | ||||
|         if (this->x_below_low_bound(j)) { | ||||
|             return -1; | ||||
|         } | ||||
|  | @ -219,13 +219,13 @@ void lar_solver::propagate_bounds_on_a_term(const lar_term& t, bound_propagator | |||
| 
 | ||||
| void lar_solver::explain_implied_bound(implied_bound & ib, bound_propagator & bp) { | ||||
|     unsigned i = ib.m_row_or_term_index; | ||||
|     int bound_sign = ib.m_is_low_bound? 1: -1; | ||||
|     int bound_sign = ib.m_is_lower_bound? 1: -1; | ||||
|     int j_sign = (ib.m_coeff_before_j_is_pos ? 1 :-1) * bound_sign; | ||||
|     unsigned m_j = ib.m_j; | ||||
|     if (is_term(m_j)) { | ||||
|         auto it = m_ext_vars_to_columns.find(m_j); | ||||
|         lp_assert(it != m_ext_vars_to_columns.end()); | ||||
|         m_j = it->second.ext_j(); | ||||
|         m_j = it->second.internal_j(); | ||||
|     } | ||||
|     for (auto const& r : A_r().m_rows[i]) { | ||||
|         unsigned j = r.m_j; | ||||
|  | @ -234,12 +234,12 @@ void lar_solver::explain_implied_bound(implied_bound & ib, bound_propagator & bp | |||
|         if (is_term(j)) { | ||||
|             auto it = m_ext_vars_to_columns.find(j); | ||||
|             lp_assert(it != m_ext_vars_to_columns.end()); | ||||
|             j = it->second.ext_j(); | ||||
|             j = it->second.internal_j(); | ||||
|         }  | ||||
|         int a_sign = is_pos(a)? 1: -1; | ||||
|         int sign = j_sign * a_sign; | ||||
|         const ul_pair & ul =  m_columns_to_ul_pairs[j]; | ||||
|         auto witness = sign > 0? ul.upper_bound_witness(): ul.low_bound_witness(); | ||||
|         auto witness = sign > 0? ul.upper_bound_witness(): ul.lower_bound_witness(); | ||||
|         lp_assert(is_valid(witness)); | ||||
|         bp.consume(a, witness); | ||||
|     } | ||||
|  | @ -269,6 +269,8 @@ void lar_solver::propagate_bounds_for_touched_rows(bound_propagator & bp) { | |||
|      | ||||
|     for (unsigned i : m_rows_with_changed_bounds.m_index) { | ||||
|         calculate_implied_bounds_for_row(i, bp); | ||||
|         if (settings().get_cancel_flag()) | ||||
|             return; | ||||
|     } | ||||
|     m_rows_with_changed_bounds.clear(); | ||||
|     if (!use_tableau()) { | ||||
|  | @ -326,7 +328,7 @@ void lar_solver::fill_explanation_from_infeasible_column(vector<std::pair<mpq, c | |||
|     // this is the case when the lower bound is in conflict with the upper one
 | ||||
|     const ul_pair & ul =  m_columns_to_ul_pairs[m_infeasible_column_index]; | ||||
|     evidence.push_back(std::make_pair(numeric_traits<mpq>::one(), ul.upper_bound_witness())); | ||||
|     evidence.push_back(std::make_pair(-numeric_traits<mpq>::one(), ul.low_bound_witness())); | ||||
|     evidence.push_back(std::make_pair(-numeric_traits<mpq>::one(), ul.lower_bound_witness())); | ||||
| } | ||||
| 
 | ||||
|      | ||||
|  | @ -347,6 +349,7 @@ void lar_solver::push() { | |||
|     m_term_count.push(); | ||||
|     m_constraint_count = m_constraints.size(); | ||||
|     m_constraint_count.push(); | ||||
|     m_int_solver->push(); | ||||
| } | ||||
| 
 | ||||
| void lar_solver::clean_popped_elements(unsigned n, int_set& set) { | ||||
|  | @ -411,6 +414,8 @@ void lar_solver::pop(unsigned k) { | |||
|     m_settings.simplex_strategy() = m_simplex_strategy; | ||||
|     lp_assert(sizes_are_correct()); | ||||
|     lp_assert((!m_settings.use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); | ||||
|     m_status = m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()? lp_status::OPTIMAL: lp_status::UNKNOWN; | ||||
|     m_int_solver->pop(k); | ||||
| } | ||||
|      | ||||
| vector<constraint_index> lar_solver::get_all_constraint_indices() const { | ||||
|  | @ -557,9 +562,9 @@ void lar_solver::set_upper_bound_witness(var_index j, constraint_index ci) { | |||
|     m_columns_to_ul_pairs[j] = ul; | ||||
| } | ||||
| 
 | ||||
| void lar_solver::set_low_bound_witness(var_index j, constraint_index ci) { | ||||
| void lar_solver::set_lower_bound_witness(var_index j, constraint_index ci) { | ||||
|     ul_pair ul = m_columns_to_ul_pairs[j]; | ||||
|     ul.low_bound_witness() = ci; | ||||
|     ul.lower_bound_witness() = ci; | ||||
|     m_columns_to_ul_pairs[j] = ul; | ||||
| } | ||||
| 
 | ||||
|  | @ -884,7 +889,7 @@ void lar_solver::copy_from_mpq_matrix(static_matrix<U, V> & matr) { | |||
| 
 | ||||
| 
 | ||||
| bool lar_solver::try_to_set_fixed(column_info<mpq> & ci) { | ||||
|     if (ci.upper_bound_is_set() && ci.low_bound_is_set() && ci.get_upper_bound() == ci.get_low_bound() && !ci.is_fixed()) { | ||||
|     if (ci.upper_bound_is_set() && ci.lower_bound_is_set() && ci.get_upper_bound() == ci.get_lower_bound() && !ci.is_fixed()) { | ||||
|         ci.set_fixed_value(ci.get_upper_bound()); | ||||
|         return true; | ||||
|     } | ||||
|  | @ -894,7 +899,7 @@ bool lar_solver::try_to_set_fixed(column_info<mpq> & ci) { | |||
| column_type lar_solver::get_column_type(const column_info<mpq> & ci) { | ||||
|     auto ret = ci.get_column_type_no_flipping(); | ||||
|     if (ret == column_type::boxed) { // changing boxed to fixed because of the no span
 | ||||
|         if (ci.get_low_bound() == ci.get_upper_bound()) | ||||
|         if (ci.get_lower_bound() == ci.get_upper_bound()) | ||||
|             ret = column_type::fixed; | ||||
|     } | ||||
|     return ret; | ||||
|  | @ -1069,9 +1074,9 @@ bool lar_solver::has_lower_bound(var_index var, constraint_index& ci, mpq& value | |||
|         return false; | ||||
|     } | ||||
|     const ul_pair & ul = m_columns_to_ul_pairs[var]; | ||||
|     ci = ul.low_bound_witness(); | ||||
|     ci = ul.lower_bound_witness(); | ||||
|     if (ci != static_cast<constraint_index>(-1)) { | ||||
|         auto& p = m_mpq_lar_core_solver.m_r_low_bounds()[var]; | ||||
|         auto& p = m_mpq_lar_core_solver.m_r_lower_bounds()[var]; | ||||
|         value = p.x; | ||||
|         is_strict = p.y.is_pos(); | ||||
|         return true; | ||||
|  | @ -1130,7 +1135,7 @@ void lar_solver::get_infeasibility_explanation_for_inf_sign( | |||
|         int adj_sign = coeff.is_pos() ? inf_sign : -inf_sign; | ||||
|         const ul_pair & ul = m_columns_to_ul_pairs[j]; | ||||
| 
 | ||||
|         constraint_index bound_constr_i = adj_sign < 0 ? ul.upper_bound_witness() : ul.low_bound_witness(); | ||||
|         constraint_index bound_constr_i = adj_sign < 0 ? ul.upper_bound_witness() : ul.lower_bound_witness(); | ||||
|         lp_assert(bound_constr_i < m_constraints.size()); | ||||
|         explanation.push_back(std::make_pair(coeff, bound_constr_i)); | ||||
|     }  | ||||
|  | @ -1481,7 +1486,16 @@ bool lar_solver::strategy_is_undecided() const { | |||
|     return m_settings.simplex_strategy() == simplex_strategy_enum::undecided; | ||||
| } | ||||
| 
 | ||||
| void lar_solver::catch_up_in_updating_int_solver() { | ||||
|     for (unsigned i = 0; i < constraints().size(); i++) { | ||||
|         m_int_solver->add_constraint_to_cut_solver(i, constraints()[i]); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| var_index lar_solver::add_var(unsigned ext_j, bool is_int) { | ||||
|     if (is_int && !has_int_var()) | ||||
|         catch_up_in_updating_int_solver(); | ||||
|          | ||||
|     TRACE("add_var", tout << "adding var " << ext_j << (is_int? " int" : " nonint") << std::endl;); | ||||
|     var_index i; | ||||
|     lp_assert(ext_j < m_terms_start_index); | ||||
|  | @ -1490,7 +1504,7 @@ var_index lar_solver::add_var(unsigned ext_j, bool is_int) { | |||
|         throw 0; // todo : what is the right way to exit?
 | ||||
|     auto it = m_ext_vars_to_columns.find(ext_j); | ||||
|     if (it != m_ext_vars_to_columns.end()) { | ||||
|         return it->second.ext_j(); | ||||
|         return it->second.internal_j(); | ||||
|     } | ||||
|     lp_assert(m_columns_to_ul_pairs.size() == A_r().column_count()); | ||||
|     i = A_r().column_count(); | ||||
|  | @ -1526,9 +1540,9 @@ void lar_solver::add_new_var_to_core_fields_for_doubles(bool register_in_basis) | |||
|     unsigned j = A_d().column_count(); | ||||
|     A_d().add_column(); | ||||
|     lp_assert(m_mpq_lar_core_solver.m_d_x.size() == j); | ||||
|     //        lp_assert(m_mpq_lar_core_solver.m_d_low_bounds.size() == j && m_mpq_lar_core_solver.m_d_upper_bounds.size() == j);  // restore later
 | ||||
|     //        lp_assert(m_mpq_lar_core_solver.m_d_lower_bounds.size() == j && m_mpq_lar_core_solver.m_d_upper_bounds.size() == j);  // restore later
 | ||||
|     m_mpq_lar_core_solver.m_d_x.resize(j + 1); | ||||
|     m_mpq_lar_core_solver.m_d_low_bounds.resize(j + 1); | ||||
|     m_mpq_lar_core_solver.m_d_lower_bounds.resize(j + 1); | ||||
|     m_mpq_lar_core_solver.m_d_upper_bounds.resize(j + 1); | ||||
|     lp_assert(m_mpq_lar_core_solver.m_d_heading.size() == j); // as A().column_count() on the entry to the method
 | ||||
|     if (register_in_basis) { | ||||
|  | @ -1546,9 +1560,9 @@ void lar_solver::add_new_var_to_core_fields_for_mpq(bool register_in_basis) { | |||
|     unsigned j = A_r().column_count(); | ||||
|     A_r().add_column(); | ||||
|     lp_assert(m_mpq_lar_core_solver.m_r_x.size() == j); | ||||
|     //        lp_assert(m_mpq_lar_core_solver.m_r_low_bounds.size() == j && m_mpq_lar_core_solver.m_r_upper_bounds.size() == j);  // restore later
 | ||||
|     //        lp_assert(m_mpq_lar_core_solver.m_r_lower_bounds.size() == j && m_mpq_lar_core_solver.m_r_upper_bounds.size() == j);  // restore later
 | ||||
|     m_mpq_lar_core_solver.m_r_x.resize(j + 1); | ||||
|     m_mpq_lar_core_solver.m_r_low_bounds.increase_size_by_one(); | ||||
|     m_mpq_lar_core_solver.m_r_lower_bounds.increase_size_by_one(); | ||||
|     m_mpq_lar_core_solver.m_r_upper_bounds.increase_size_by_one(); | ||||
|     m_mpq_lar_core_solver.m_r_solver.m_inf_set.increase_size_by_one(); | ||||
|     m_mpq_lar_core_solver.m_r_solver.m_costs.resize(j + 1); | ||||
|  | @ -1626,7 +1640,7 @@ void lar_solver::add_basic_var_to_core_fields() { | |||
|         add_new_var_to_core_fields_for_doubles(true); | ||||
| } | ||||
| 
 | ||||
| bool lar_solver::bound_is_integer_if_needed(unsigned j, const mpq & right_side) const { | ||||
| bool lar_solver::bound_is_integer_for_integer_column(unsigned j, const mpq & right_side) const { | ||||
|     if (!column_is_int(j)) | ||||
|         return true; | ||||
|     return right_side.is_int(); | ||||
|  | @ -1636,9 +1650,12 @@ constraint_index lar_solver::add_var_bound(var_index j, lconstraint_kind kind, c | |||
|     TRACE("lar_solver", tout << "j = " << j << std::endl;); | ||||
|     constraint_index ci = m_constraints.size(); | ||||
|     if (!is_term(j)) { // j is a var
 | ||||
|         lp_assert(bound_is_integer_if_needed(j, right_side)); | ||||
|         lp_assert(bound_is_integer_for_integer_column(j, right_side)); | ||||
|         auto vc = new lar_var_constraint(j, kind, right_side); | ||||
|         m_constraints.push_back(vc); | ||||
|         if (has_int_var()) { | ||||
|             m_int_solver->notify_on_last_added_constraint(); | ||||
|         } | ||||
|         update_column_type_and_bound(j, kind, right_side, ci); | ||||
|     } | ||||
|     else { | ||||
|  | @ -1657,8 +1674,8 @@ void lar_solver::update_column_type_and_bound(var_index j, lconstraint_kind kind | |||
|     case column_type::boxed: | ||||
|         update_boxed_column_type_and_bound(j, kind, right_side, constr_index); | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|         update_low_bound_column_type_and_bound(j, kind, right_side, constr_index); | ||||
|     case column_type::lower_bound: | ||||
|         update_lower_bound_column_type_and_bound(j, kind, right_side, constr_index); | ||||
|         break; | ||||
|     case column_type::upper_bound: | ||||
|         update_upper_bound_column_type_and_bound(j, kind, right_side, constr_index); | ||||
|  | @ -1677,9 +1694,11 @@ void lar_solver::add_var_bound_on_constraint_for_term(var_index j, lconstraint_k | |||
|     lp_assert(!term_is_int(m_terms[adjusted_term_index]) || right_side.is_int()); | ||||
|     auto it = m_ext_vars_to_columns.find(j); | ||||
|     if (it != m_ext_vars_to_columns.end()) { | ||||
|         unsigned term_j = it->second.ext_j(); | ||||
|         unsigned term_j = it->second.internal_j(); | ||||
|         mpq rs = right_side - m_terms[adjusted_term_index]->m_v; | ||||
|         m_constraints.push_back(new lar_term_constraint(m_terms[adjusted_term_index], kind, right_side)); | ||||
|         if (has_int_var()) | ||||
|             m_int_solver->notify_on_last_added_constraint(); | ||||
|         update_column_type_and_bound(term_j, kind, rs, ci); | ||||
|     } | ||||
|     else { | ||||
|  | @ -1738,7 +1757,7 @@ void lar_solver::adjust_initial_state_for_lu() { | |||
|     copy_from_mpq_matrix(A_d()); | ||||
|     unsigned n = A_d().column_count(); | ||||
|     m_mpq_lar_core_solver.m_d_x.resize(n); | ||||
|     m_mpq_lar_core_solver.m_d_low_bounds.resize(n); | ||||
|     m_mpq_lar_core_solver.m_d_lower_bounds.resize(n); | ||||
|     m_mpq_lar_core_solver.m_d_upper_bounds.resize(n); | ||||
|     m_mpq_lar_core_solver.m_d_heading = m_mpq_lar_core_solver.m_r_heading; | ||||
|     m_mpq_lar_core_solver.m_d_basis = m_mpq_lar_core_solver.m_r_basis; | ||||
|  | @ -1747,9 +1766,9 @@ void lar_solver::adjust_initial_state_for_lu() { | |||
|       unsigned j = A_d().column_count(); | ||||
|       A_d().add_column(); | ||||
|       lp_assert(m_mpq_lar_core_solver.m_d_x.size() == j); | ||||
|       //        lp_assert(m_mpq_lar_core_solver.m_d_low_bounds.size() == j && m_mpq_lar_core_solver.m_d_upper_bounds.size() == j);  // restore later
 | ||||
|       //        lp_assert(m_mpq_lar_core_solver.m_d_lower_bounds.size() == j && m_mpq_lar_core_solver.m_d_upper_bounds.size() == j);  // restore later
 | ||||
|       m_mpq_lar_core_solver.m_d_x.resize(j + 1 ); | ||||
|       m_mpq_lar_core_solver.m_d_low_bounds.resize(j + 1); | ||||
|       m_mpq_lar_core_solver.m_d_lower_bounds.resize(j + 1); | ||||
|       m_mpq_lar_core_solver.m_d_upper_bounds.resize(j + 1); | ||||
|       lp_assert(m_mpq_lar_core_solver.m_d_heading.size() == j); // as A().column_count() on the entry to the method
 | ||||
|       if (register_in_basis) { | ||||
|  | @ -1805,19 +1824,19 @@ void lar_solver::update_free_column_type_and_bound(var_index j, lconstraint_kind | |||
|     case GT: | ||||
|         y_of_bound = 1; | ||||
|     case GE: | ||||
|         m_mpq_lar_core_solver.m_column_types[j] = column_type::low_bound; | ||||
|         m_mpq_lar_core_solver.m_column_types[j] = column_type::lower_bound; | ||||
|         lp_assert(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j); | ||||
|         { | ||||
|             auto low = numeric_pair<mpq>(right_side, y_of_bound); | ||||
|             m_mpq_lar_core_solver.m_r_low_bounds[j] = low; | ||||
|             m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; | ||||
|         } | ||||
|         set_low_bound_witness(j, constr_ind); | ||||
|         set_lower_bound_witness(j, constr_ind); | ||||
|         break; | ||||
|     case EQ: | ||||
|         m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; | ||||
|         m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = numeric_pair<mpq>(right_side, zero_of_type<mpq>()); | ||||
|         m_mpq_lar_core_solver.m_r_lower_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = numeric_pair<mpq>(right_side, zero_of_type<mpq>()); | ||||
|         set_upper_bound_witness(j, constr_ind); | ||||
|         set_low_bound_witness(j, constr_ind); | ||||
|         set_lower_bound_witness(j, constr_ind); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|  | @ -1849,15 +1868,15 @@ void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstrai | |||
|         m_mpq_lar_core_solver.m_column_types[j] = column_type::boxed; | ||||
|         { | ||||
|             auto low = numeric_pair<mpq>(right_side, y_of_bound); | ||||
|             m_mpq_lar_core_solver.m_r_low_bounds[j] = low; | ||||
|             set_low_bound_witness(j, ci); | ||||
|             m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; | ||||
|             set_lower_bound_witness(j, ci); | ||||
|             m_columns_with_changed_bound.insert(j); | ||||
|             if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 m_infeasible_column_index = j; | ||||
|             } | ||||
|             else { | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j] ? column_type::boxed : column_type::fixed; | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_lower_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j] ? column_type::boxed : column_type::fixed; | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|  | @ -1866,13 +1885,13 @@ void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstrai | |||
|             auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>()); | ||||
|             if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 set_low_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|                 m_infeasible_column_index = j; | ||||
|             } | ||||
|             else { | ||||
|                 m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; | ||||
|                 m_mpq_lar_core_solver.m_r_lower_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; | ||||
|                 m_columns_with_changed_bound.insert(j); | ||||
|                 set_low_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; | ||||
|             } | ||||
|  | @ -1887,7 +1906,7 @@ void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstrai | |||
| } | ||||
| 
 | ||||
| void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
|     lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::boxed && m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j])); | ||||
|     lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::boxed && m_mpq_lar_core_solver.m_r_lower_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j])); | ||||
|     mpq y_of_bound(0); | ||||
|     switch (kind) { | ||||
|     case LT: | ||||
|  | @ -1901,13 +1920,13 @@ void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kin | |||
|                 m_columns_with_changed_bound.insert(j); | ||||
|             } | ||||
| 
 | ||||
|             if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { | ||||
|             if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 lp_assert(false); | ||||
|                 m_infeasible_column_index = j; | ||||
|             } | ||||
|             else { | ||||
|                 if (m_mpq_lar_core_solver.m_r_low_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j]) | ||||
|                 if (m_mpq_lar_core_solver.m_r_lower_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j]) | ||||
|                     m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; | ||||
|             } | ||||
| 	} | ||||
|  | @ -1917,10 +1936,10 @@ void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kin | |||
|     case GE: | ||||
| 	{ | ||||
|             auto low = numeric_pair<mpq>(right_side, y_of_bound); | ||||
|             if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) { | ||||
|                 m_mpq_lar_core_solver.m_r_low_bounds[j] = low; | ||||
|             if (low > m_mpq_lar_core_solver.m_r_lower_bounds[j]) { | ||||
|                 m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; | ||||
|                 m_columns_with_changed_bound.insert(j); | ||||
|                 set_low_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|             } | ||||
|             if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|  | @ -1934,7 +1953,7 @@ void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kin | |||
|     case EQ: | ||||
| 	{ | ||||
|             auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>()); | ||||
|             if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { | ||||
|             if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 m_infeasible_column_index = j; | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|  | @ -1942,11 +1961,11 @@ void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kin | |||
|             else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 m_infeasible_column_index = j; | ||||
|                 set_low_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|             } | ||||
|             else { | ||||
|                 m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; | ||||
|                 set_low_bound_witness(j, ci); | ||||
|                 m_mpq_lar_core_solver.m_r_lower_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; | ||||
|                 m_columns_with_changed_bound.insert(j); | ||||
|  | @ -1960,8 +1979,8 @@ void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kin | |||
| 
 | ||||
|     } | ||||
| } | ||||
| void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
|     lp_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::low_bound); | ||||
| void lar_solver::update_lower_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
|     lp_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::lower_bound); | ||||
|     mpq y_of_bound(0); | ||||
|     switch (kind) { | ||||
|     case LT: | ||||
|  | @ -1973,12 +1992,12 @@ void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint | |||
|             set_upper_bound_witness(j, ci); | ||||
|             m_columns_with_changed_bound.insert(j); | ||||
| 
 | ||||
|             if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { | ||||
|             if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 m_infeasible_column_index = j; | ||||
|             } | ||||
|             else { | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j] ? column_type::boxed : column_type::fixed; | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_lower_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j] ? column_type::boxed : column_type::fixed; | ||||
|             } | ||||
| 	} | ||||
| 	break; | ||||
|  | @ -1987,24 +2006,24 @@ void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint | |||
|     case GE: | ||||
| 	{ | ||||
|             auto low = numeric_pair<mpq>(right_side, y_of_bound); | ||||
|             if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) { | ||||
|                 m_mpq_lar_core_solver.m_r_low_bounds[j] = low; | ||||
|             if (low > m_mpq_lar_core_solver.m_r_lower_bounds[j]) { | ||||
|                 m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; | ||||
|                 m_columns_with_changed_bound.insert(j); | ||||
|                 set_low_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|             } | ||||
| 	} | ||||
| 	break; | ||||
|     case EQ: | ||||
| 	{ | ||||
|             auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>()); | ||||
|             if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { | ||||
|             if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 m_infeasible_column_index = j; | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|             } | ||||
|             else { | ||||
|                 m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; | ||||
|                 set_low_bound_witness(j, ci); | ||||
|                 m_mpq_lar_core_solver.m_r_lower_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; | ||||
|             } | ||||
|  | @ -2019,14 +2038,14 @@ void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint | |||
| } | ||||
| 
 | ||||
| void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { | ||||
|     lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::fixed && m_mpq_lar_core_solver.m_r_low_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j])); | ||||
|     lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_r_low_bounds()[j].y.is_zero() && m_mpq_lar_core_solver.m_r_upper_bounds()[j].y.is_zero())); | ||||
|     lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::fixed && m_mpq_lar_core_solver.m_r_lower_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j])); | ||||
|     lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_r_lower_bounds()[j].y.is_zero() && m_mpq_lar_core_solver.m_r_upper_bounds()[j].y.is_zero())); | ||||
|     auto v = numeric_pair<mpq>(right_side, mpq(0)); | ||||
| 
 | ||||
|     mpq y_of_bound(0); | ||||
|     switch (kind) { | ||||
|     case LT: | ||||
|         if (v <= m_mpq_lar_core_solver.m_r_low_bounds[j]) { | ||||
|         if (v <= m_mpq_lar_core_solver.m_r_lower_bounds[j]) { | ||||
|             m_status = lp_status::INFEASIBLE; | ||||
|             m_infeasible_column_index = j; | ||||
|             set_upper_bound_witness(j, ci); | ||||
|  | @ -2034,7 +2053,7 @@ void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kin | |||
|         break; | ||||
|     case LE: | ||||
| 	{ | ||||
|             if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { | ||||
|             if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 m_infeasible_column_index = j; | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|  | @ -2046,7 +2065,7 @@ void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kin | |||
|             if (v >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 m_infeasible_column_index = j; | ||||
|                 set_low_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|             } | ||||
| 	} | ||||
| 	break; | ||||
|  | @ -2055,13 +2074,13 @@ void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kin | |||
|             if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 m_infeasible_column_index = j; | ||||
|                 set_low_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|             } | ||||
| 	} | ||||
| 	break; | ||||
|     case EQ: | ||||
| 	{ | ||||
|             if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { | ||||
|             if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 m_infeasible_column_index = j; | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|  | @ -2069,7 +2088,7 @@ void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kin | |||
|             else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { | ||||
|                 m_status = lp_status::INFEASIBLE; | ||||
|                 m_infeasible_column_index = j; | ||||
|                 set_low_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|             } | ||||
|             break; | ||||
| 	} | ||||
|  | @ -2080,7 +2099,15 @@ void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kin | |||
|     } | ||||
| } | ||||
| 
 | ||||
| bool lar_solver::column_corresponds_to_term(unsigned j) const { | ||||
|     return m_columns_to_ext_vars_or_term_indices[j] >= m_terms_start_index; | ||||
| } | ||||
| 
 | ||||
| var_index lar_solver:: to_var_index(unsigned ext_j) const { | ||||
|     auto it = m_ext_vars_to_columns.find(ext_j); | ||||
|     lp_assert(it != m_ext_vars_to_columns.end()); | ||||
|     return it->second.internal_j(); | ||||
| } | ||||
| } // namespace lp
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -34,7 +34,7 @@ struct linear_combination_iterator_on_vector : linear_combination_iterator<T> { | |||
|     vector<std::pair<T, unsigned>> & m_vector; | ||||
|     int m_offset; | ||||
|     bool next(T & a, unsigned & i) { | ||||
|         if(m_offset >= m_vector.size()) | ||||
|         if(static_cast<unsigned>(m_offset) >= m_vector.size()) | ||||
|             return false; | ||||
|         auto & p = m_vector[m_offset]; | ||||
|         a = p.first; | ||||
|  | @ -44,7 +44,7 @@ struct linear_combination_iterator_on_vector : linear_combination_iterator<T> { | |||
|     } | ||||
| 
 | ||||
|     bool next(unsigned & i) { | ||||
|         if(m_offset >= m_vector.size()) | ||||
|         if(static_cast<unsigned>(m_offset) >= m_vector.size()) | ||||
|             return false; | ||||
|         auto & p = m_vector[m_offset]; | ||||
|         i = p.second; | ||||
|  |  | |||
							
								
								
									
										0
									
								
								src/util/lp/linear_combination_iterator_on_std_vector.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/util/lp/linear_combination_iterator_on_std_vector.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -21,8 +21,8 @@ Revision History: | |||
| #include "util/lp/lp_settings.h" | ||||
| namespace lp { | ||||
| class lar_solver; | ||||
| class lp_bound_propagator { | ||||
|     std::unordered_map<unsigned, unsigned> m_improved_low_bounds; // these maps map a column index to the corresponding index in ibounds
 | ||||
| class bound_propagator { | ||||
|     std::unordered_map<unsigned, unsigned> m_improved_lower_bounds; // these maps map a column index to the corresponding index in ibounds
 | ||||
|     std::unordered_map<unsigned, unsigned> m_improved_upper_bounds; | ||||
|     lar_solver & m_lar_solver; | ||||
| public: | ||||
|  | @ -30,7 +30,7 @@ public: | |||
| public: | ||||
|     lp_bound_propagator(lar_solver & ls); | ||||
|     column_type get_column_type(unsigned) const; | ||||
|     const impq & get_low_bound(unsigned) const; | ||||
|     const impq & get_lower_bound(unsigned) const; | ||||
|     const impq & get_upper_bound(unsigned) const; | ||||
|     void try_add_bound(mpq  v, unsigned j, bool is_low, bool coeff_before_j_is_pos, unsigned row_or_term_index, bool strict); | ||||
|     virtual bool bound_is_interesting(unsigned vi, | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ Revision History: | |||
| #include <string> | ||||
| #include "util/vector.h" | ||||
| #include <functional> | ||||
| #include "util/lp/lp_core_solver_base.hpp" | ||||
| #include "util/lp/lp_core_solver_base_def.h" | ||||
| template bool lp::lp_core_solver_base<double, double>::A_mult_x_is_off() const; | ||||
| template bool lp::lp_core_solver_base<double, double>::A_mult_x_is_off_on_index(const vector<unsigned> &) const; | ||||
| template bool lp::lp_core_solver_base<double, double>::basis_heading_is_correct() const; | ||||
|  | @ -77,7 +77,7 @@ public: | |||
|     vector<T>             m_d; // the vector of reduced costs
 | ||||
|     indexed_vector<T>     m_ed; // the solution of B*m_ed = a
 | ||||
|     const vector<column_type> & m_column_types; | ||||
|     const vector<X> &     m_low_bounds; | ||||
|     const vector<X> &     m_lower_bounds; | ||||
|     const vector<X> &     m_upper_bounds; | ||||
|     vector<T>             m_column_norms; // the approximate squares of column norms that help choosing a profitable column
 | ||||
|     vector<X>             m_copy_of_xB; | ||||
|  | @ -127,7 +127,7 @@ public: | |||
|                         lp_settings & settings, | ||||
|                         const column_namer& column_names, | ||||
|                         const vector<column_type> & column_types, | ||||
|                         const vector<X> & low_bound_values, | ||||
|                         const vector<X> & lower_bound_values, | ||||
|                         const vector<X> & upper_bound_values); | ||||
| 
 | ||||
|     void allocate_basis_heading(); | ||||
|  | @ -272,14 +272,14 @@ public: | |||
|     } | ||||
| 
 | ||||
|     bool x_below_low_bound(unsigned p) const { | ||||
|         return below_bound(m_x[p], m_low_bounds[p]); | ||||
|         return below_bound(m_x[p], m_lower_bounds[p]); | ||||
|     } | ||||
| 
 | ||||
|     bool infeasibility_costs_are_correct() const; | ||||
|     bool infeasibility_cost_is_correct_for_column(unsigned j) const; | ||||
|      | ||||
|     bool x_above_low_bound(unsigned p) const { | ||||
|         return above_bound(m_x[p], m_low_bounds[p]); | ||||
|     bool x_above_lower_bound(unsigned p) const { | ||||
|         return above_bound(m_x[p], m_lower_bounds[p]); | ||||
|     } | ||||
| 
 | ||||
|     bool x_below_upper_bound(unsigned p) const { | ||||
|  | @ -290,15 +290,15 @@ public: | |||
|     bool x_above_upper_bound(unsigned p) const { | ||||
|         return above_bound(m_x[p], m_upper_bounds[p]); | ||||
|     } | ||||
|     bool x_is_at_low_bound(unsigned j) const { | ||||
|         return at_bound(m_x[j], m_low_bounds[j]); | ||||
|     bool x_is_at_lower_bound(unsigned j) const { | ||||
|         return at_bound(m_x[j], m_lower_bounds[j]); | ||||
|     } | ||||
|     bool x_is_at_upper_bound(unsigned j) const { | ||||
|         return at_bound(m_x[j], m_upper_bounds[j]); | ||||
|     } | ||||
| 
 | ||||
|     bool x_is_at_bound(unsigned j) const { | ||||
|         return x_is_at_low_bound(j) || x_is_at_upper_bound(j); | ||||
|         return x_is_at_lower_bound(j) || x_is_at_upper_bound(j); | ||||
|     } | ||||
|     bool column_is_feasible(unsigned j) const; | ||||
| 
 | ||||
|  | @ -337,8 +337,8 @@ public: | |||
|     void fill_reduced_costs_from_m_y_by_rows(); | ||||
| 
 | ||||
|     void copy_rs_to_xB(vector<X> & rs); | ||||
|     virtual bool low_bounds_are_set() const { return false; } | ||||
|     X low_bound_value(unsigned j) const { return m_low_bounds[j]; } | ||||
|     virtual bool lower_bounds_are_set() const { return false; } | ||||
|     X lower_bound_value(unsigned j) const { return m_lower_bounds[j]; } | ||||
|     X upper_bound_value(unsigned j) const { return m_upper_bounds[j]; } | ||||
| 
 | ||||
|     column_type get_column_type(unsigned j) const {return m_column_types[j]; } | ||||
|  | @ -348,7 +348,7 @@ public: | |||
|     } | ||||
| 
 | ||||
|     X bound_span(unsigned j) const { | ||||
|         return m_upper_bounds[j] - m_low_bounds[j]; | ||||
|         return m_upper_bounds[j] - m_lower_bounds[j]; | ||||
|     } | ||||
| 
 | ||||
|     std::string column_name(unsigned column) const; | ||||
|  | @ -376,21 +376,21 @@ public: | |||
|         case column_type::fixed: | ||||
|             if (x_is_at_bound(j)) | ||||
|                 break; | ||||
|             m_x[j] = m_low_bounds[j]; | ||||
|             m_x[j] = m_lower_bounds[j]; | ||||
|             return true; | ||||
|         case column_type::boxed: | ||||
|             if (x_is_at_bound(j)) | ||||
|                 break; // we should preserve x if possible
 | ||||
|             // snap randomly
 | ||||
|             if (m_settings.random_next() % 2 == 1)  | ||||
|                 m_x[j] = m_low_bounds[j]; | ||||
|                 m_x[j] = m_lower_bounds[j]; | ||||
|             else | ||||
|                 m_x[j] = m_upper_bounds[j]; | ||||
|             return true; | ||||
|         case column_type::low_bound: | ||||
|             if (x_is_at_low_bound(j)) | ||||
|         case column_type::lower_bound: | ||||
|             if (x_is_at_lower_bound(j)) | ||||
|                 break; | ||||
|             m_x[j] = m_low_bounds[j]; | ||||
|             m_x[j] = m_lower_bounds[j]; | ||||
|             return true; | ||||
|         case column_type::upper_bound: | ||||
|             if (x_is_at_upper_bound(j)) | ||||
|  | @ -409,15 +409,15 @@ public: | |||
|         auto & x = m_x[j]; | ||||
|         switch (m_column_types[j]) { | ||||
|         case column_type::fixed: | ||||
|             lp_assert(m_low_bounds[j] == m_upper_bounds[j]); | ||||
|             if (x != m_low_bounds[j]) { | ||||
|                 delta = m_low_bounds[j] - x; | ||||
|             lp_assert(m_lower_bounds[j] == m_upper_bounds[j]); | ||||
|             if (x != m_lower_bounds[j]) { | ||||
|                 delta = m_lower_bounds[j] - x; | ||||
|                 ret = true;; | ||||
|             } | ||||
|             break; | ||||
|         case column_type::boxed: | ||||
|             if (x < m_low_bounds[j]) { | ||||
|                 delta = m_low_bounds[j] - x; | ||||
|             if (x < m_lower_bounds[j]) { | ||||
|                 delta = m_lower_bounds[j] - x; | ||||
|                 ret = true;; | ||||
|             } | ||||
|             if (x > m_upper_bounds[j]) { | ||||
|  | @ -425,9 +425,9 @@ public: | |||
|                 ret = true; | ||||
|             } | ||||
|             break; | ||||
|         case column_type::low_bound: | ||||
|             if (x < m_low_bounds[j]) { | ||||
|                 delta = m_low_bounds[j] - x; | ||||
|         case column_type::lower_bound: | ||||
|             if (x < m_lower_bounds[j]) { | ||||
|                 delta = m_lower_bounds[j] - x; | ||||
|                 ret = true; | ||||
|             } | ||||
|             break; | ||||
|  | @ -540,8 +540,8 @@ public: | |||
|             if (!this->x_is_at_bound(j)) | ||||
|                 return false; | ||||
|             break; | ||||
|         case column_type::low_bound: | ||||
|             if (!this->x_is_at_low_bound(j)) | ||||
|         case column_type::lower_bound: | ||||
|             if (!this->x_is_at_lower_bound(j)) | ||||
|                 return false; | ||||
|             break; | ||||
|         case column_type::upper_bound: | ||||
|  | @ -570,10 +570,10 @@ public: | |||
|         switch (m_column_types[j]) { | ||||
|         case column_type::fixed: | ||||
|         case column_type::boxed: | ||||
|             out << "(" << m_low_bounds[j] << ", " << m_upper_bounds[j] << ")" << std::endl; | ||||
|             out << "(" << m_lower_bounds[j] << ", " << m_upper_bounds[j] << ")" << std::endl; | ||||
|             break; | ||||
|         case column_type::low_bound: | ||||
|             out << m_low_bounds[j] << std::endl; | ||||
|         case column_type::lower_bound: | ||||
|             out << m_lower_bounds[j] << std::endl; | ||||
|             break; | ||||
|         case column_type::upper_bound: | ||||
|             out << m_upper_bounds[j] << std::endl; | ||||
|  | @ -588,10 +588,10 @@ public: | |||
|         switch (m_column_types[j]) { | ||||
|         case column_type::fixed: | ||||
|         case column_type::boxed: | ||||
|             out << " [" << m_low_bounds[j] << ", " << m_upper_bounds[j] << "]"; | ||||
|             out << " [" << m_lower_bounds[j] << ", " << m_upper_bounds[j] << "]"; | ||||
|             break; | ||||
|         case column_type::low_bound: | ||||
|             out << " [" << m_low_bounds[j] << "," << "oo" << "]"; | ||||
|         case column_type::lower_bound: | ||||
|             out << " [" << m_lower_bounds[j] << "," << "oo" << "]"; | ||||
|             break; | ||||
|         case column_type::upper_bound: | ||||
|             out << " [-oo, " << m_upper_bounds[j] << ']'; | ||||
|  | @ -619,7 +619,7 @@ public: | |||
|     bool column_has_upper_bound(unsigned j) { | ||||
|         switch(m_column_types[j]) { | ||||
|         case column_type::free_column: | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             return false; | ||||
|         default: | ||||
|             return true; | ||||
|  | @ -629,13 +629,13 @@ public: | |||
|     bool bounds_for_boxed_are_set_correctly() const { | ||||
|         for (unsigned j = 0; j < m_column_types.size(); j++) { | ||||
|             if (m_column_types[j] != column_type::boxed) continue; | ||||
|             if (m_low_bounds[j] > m_upper_bounds[j]) | ||||
|             if (m_lower_bounds[j] > m_upper_bounds[j]) | ||||
|                 return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|      | ||||
|     bool column_has_low_bound(unsigned j) { | ||||
|     bool column_has_lower_bound(unsigned j) { | ||||
|         switch(m_column_types[j]) { | ||||
|         case column_type::free_column: | ||||
|         case column_type::upper_bound: | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ lp_core_solver_base(static_matrix<T, X> & A, | |||
|                     lp_settings & settings, | ||||
|                     const column_namer& column_names, | ||||
|                     const vector<column_type> & column_types, | ||||
|                     const vector<X> & low_bound_values, | ||||
|                     const vector<X> & lower_bound_values, | ||||
|                     const vector<X> & upper_bound_values): | ||||
|     m_total_iterations(0), | ||||
|     m_iters_with_no_cost_growing(0), | ||||
|  | @ -59,7 +59,7 @@ lp_core_solver_base(static_matrix<T, X> & A, | |||
|     m_d(m_n()), | ||||
|     m_ed(m_m()), | ||||
|     m_column_types(column_types), | ||||
|     m_low_bounds(low_bound_values), | ||||
|     m_lower_bounds(lower_bound_values), | ||||
|     m_upper_bounds(upper_bound_values), | ||||
|     m_column_norms(m_n()), | ||||
|     m_copy_of_xB(m_m()), | ||||
|  | @ -392,10 +392,10 @@ set_non_basic_x_to_correct_bounds() { | |||
|     for (unsigned j : non_basis()) { | ||||
|         switch (m_column_types[j]) { | ||||
|         case column_type::boxed: | ||||
|             m_x[j] = m_d[j] < 0? m_upper_bounds[j]: m_low_bounds[j]; | ||||
|             m_x[j] = m_d[j] < 0? m_upper_bounds[j]: m_lower_bounds[j]; | ||||
|             break; | ||||
|         case column_type::low_bound: | ||||
|             m_x[j] = m_low_bounds[j]; | ||||
|         case column_type::lower_bound: | ||||
|             m_x[j] = m_lower_bounds[j]; | ||||
|             lp_assert(column_is_dual_feasible(j)); | ||||
|             break; | ||||
|         case column_type::upper_bound: | ||||
|  | @ -412,12 +412,12 @@ column_is_dual_feasible(unsigned j) const { | |||
|     switch (m_column_types[j]) { | ||||
|     case column_type::fixed: | ||||
|     case column_type::boxed: | ||||
|         return (x_is_at_low_bound(j) && d_is_not_negative(j)) || | ||||
|         return (x_is_at_lower_bound(j) && d_is_not_negative(j)) || | ||||
|             (x_is_at_upper_bound(j) && d_is_not_positive(j)); | ||||
|     case column_type::low_bound: | ||||
|         return x_is_at_low_bound(j) && d_is_not_negative(j); | ||||
|     case column_type::lower_bound: | ||||
|         return x_is_at_lower_bound(j) && d_is_not_negative(j); | ||||
|     case column_type::upper_bound: | ||||
|         LP_OUT(m_settings,  "upper_bound type should be switched to low_bound" << std::endl); | ||||
|         LP_OUT(m_settings,  "upper_bound type should be switched to lower_bound" << std::endl); | ||||
|         lp_assert(false); // impossible case
 | ||||
|     case column_type::free_column: | ||||
|         return numeric_traits<X>::is_zero(m_d[j]); | ||||
|  | @ -485,14 +485,14 @@ template <typename T, typename X> bool lp_core_solver_base<T, X>::column_is_feas | |||
|     case column_type::boxed: | ||||
|         if (this->above_bound(x, this->m_upper_bounds[j])) { | ||||
|             return false; | ||||
|         } else if (this->below_bound(x, this->m_low_bounds[j])) { | ||||
|         } else if (this->below_bound(x, this->m_lower_bounds[j])) { | ||||
|             return false; | ||||
|         } else { | ||||
|             return true; | ||||
|         } | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|         if (this->below_bound(x, this->m_low_bounds[j])) { | ||||
|     case column_type::lower_bound: | ||||
|         if (this->below_bound(x, this->m_lower_bounds[j])) { | ||||
|             return false; | ||||
|         } else { | ||||
|             return true; | ||||
|  | @ -861,8 +861,8 @@ snap_non_basic_x_to_bound_and_free_to_zeroes() { | |||
|         switch (m_column_types[j]) { | ||||
|         case column_type::fixed: | ||||
|         case column_type::boxed: | ||||
|         case column_type::low_bound: | ||||
|             m_x[j] = m_low_bounds[j]; | ||||
|         case column_type::lower_bound: | ||||
|             m_x[j] = m_lower_bounds[j]; | ||||
|             break; | ||||
|         case column_type::upper_bound: | ||||
|             m_x[j] = m_upper_bounds[j]; | ||||
|  | @ -895,23 +895,23 @@ template <typename T, typename X> non_basic_column_value_position lp_core_solver | |||
| get_non_basic_column_value_position(unsigned j) const { | ||||
|     switch (m_column_types[j]) { | ||||
|     case column_type::fixed: | ||||
|         return x_is_at_low_bound(j)? at_fixed : not_at_bound; | ||||
|         return x_is_at_lower_bound(j)? at_fixed : not_at_bound; | ||||
|     case column_type::free_column: | ||||
|         return free_of_bounds; | ||||
|     case column_type::boxed: | ||||
|         return x_is_at_low_bound(j)? at_low_bound :( | ||||
|         return x_is_at_lower_bound(j)? at_lower_bound :( | ||||
|                                                     x_is_at_upper_bound(j)? at_upper_bound: | ||||
|                                                     not_at_bound | ||||
|                                                     ); | ||||
|     case column_type::low_bound: | ||||
|         return x_is_at_low_bound(j)? at_low_bound : not_at_bound; | ||||
|     case column_type::lower_bound: | ||||
|         return x_is_at_lower_bound(j)? at_lower_bound : not_at_bound; | ||||
|     case column_type::upper_bound: | ||||
|         return x_is_at_upper_bound(j)? at_upper_bound : not_at_bound; | ||||
|     default: | ||||
|         lp_unreachable(); | ||||
|     } | ||||
|     lp_unreachable(); | ||||
|     return at_low_bound; | ||||
|     return at_lower_bound; | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename X> void lp_core_solver_base<T, X>::init_lu() { | ||||
|  | @ -1026,7 +1026,7 @@ lp_core_solver_base<T, X>::infeasibility_cost_is_correct_for_column(unsigned j) | |||
|         } | ||||
|         return is_zero(this->m_costs[j]); | ||||
| 
 | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|         if (this->x_below_low_bound(j)) { | ||||
|             return this->m_costs[j] == -r; | ||||
|         } | ||||
|  | @ -22,7 +22,7 @@ Revision History: | |||
| #include <string> | ||||
| #include "util/vector.h" | ||||
| #include <functional> | ||||
| #include "util/lp/lp_dual_core_solver.hpp" | ||||
| #include "util/lp/lp_dual_core_solver_def.h" | ||||
| template void lp::lp_dual_core_solver<lp::mpq, lp::mpq>::start_with_initial_basis_and_make_it_dual_feasible(); | ||||
| template void lp::lp_dual_core_solver<lp::mpq, lp::mpq>::solve(); | ||||
| template lp::lp_dual_core_solver<double, double>::lp_dual_core_solver(lp::static_matrix<double, double>&, vector<bool>&, | ||||
|  | @ -56,7 +56,7 @@ public: | |||
|                         vector<int> & heading, | ||||
|                         vector<T> & costs, | ||||
|                         vector<column_type> & column_type_array, | ||||
|                         vector<X> & low_bound_values, | ||||
|                         vector<X> & lower_bound_values, | ||||
|                         vector<X> & upper_bound_values, | ||||
|                         lp_settings & settings, | ||||
|                         const column_namer & column_names): | ||||
|  | @ -70,7 +70,7 @@ public: | |||
|                                   settings, | ||||
|                                   column_names, | ||||
|                                   column_type_array, | ||||
|                                   low_bound_values, | ||||
|                                   lower_bound_values, | ||||
|                                   upper_bound_values), | ||||
|         m_can_enter_basis(can_enter_basis), | ||||
|         m_a_wave(this->m_m()), | ||||
|  | @ -110,7 +110,7 @@ public: | |||
| 
 | ||||
|     bool done(); | ||||
| 
 | ||||
|     T get_edge_steepness_for_low_bound(unsigned p); | ||||
|     T get_edge_steepness_for_lower_bound(unsigned p); | ||||
| 
 | ||||
|     T get_edge_steepness_for_upper_bound(unsigned p); | ||||
| 
 | ||||
|  | @ -174,7 +174,7 @@ public: | |||
| 
 | ||||
|     // it is positive if going from low bound to upper bound and negative if going from upper bound to low bound
 | ||||
|     T signed_span_of_boxed(unsigned j) { | ||||
|         return this->x_is_at_low_bound(j)? this->bound_span(j): - this->bound_span(j); | ||||
|         return this->x_is_at_lower_bound(j)? this->bound_span(j): - this->bound_span(j); | ||||
|     } | ||||
| 
 | ||||
|     void add_tight_breakpoints_and_q_to_flipped_set(); | ||||
|  | @ -207,6 +207,6 @@ public: | |||
| 
 | ||||
|     void solve(); | ||||
| 
 | ||||
|     bool low_bounds_are_set() const override { return true; } | ||||
|     bool lower_bounds_are_set() const override { return true; } | ||||
| }; | ||||
| } | ||||
|  |  | |||
|  | @ -107,9 +107,9 @@ template <typename T, typename X> bool lp_dual_core_solver<T, X>::done() { | |||
|     return false; // todo, need to be more cases
 | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename X> T lp_dual_core_solver<T, X>::get_edge_steepness_for_low_bound(unsigned p) { | ||||
| template <typename T, typename X> T lp_dual_core_solver<T, X>::get_edge_steepness_for_lower_bound(unsigned p) { | ||||
|     lp_assert(this->m_basis_heading[p] >= 0 && static_cast<unsigned>(this->m_basis_heading[p]) < this->m_m()); | ||||
|     T del = this->m_x[p] - this->m_low_bounds[p]; | ||||
|     T del = this->m_x[p] - this->m_lower_bounds[p]; | ||||
|     del *= del; | ||||
|     return del / this->m_betas[this->m_basis_heading[p]]; | ||||
| } | ||||
|  | @ -127,7 +127,7 @@ template <typename T, typename X> T lp_dual_core_solver<T, X>::pricing_for_row(u | |||
|     case column_type::fixed: | ||||
|     case column_type::boxed: | ||||
|         if (this->x_below_low_bound(p)) { | ||||
|             T del =  get_edge_steepness_for_low_bound(p); | ||||
|             T del =  get_edge_steepness_for_lower_bound(p); | ||||
|             return del; | ||||
|         } | ||||
|         if (this->x_above_upper_bound(p)) { | ||||
|  | @ -135,9 +135,9 @@ template <typename T, typename X> T lp_dual_core_solver<T, X>::pricing_for_row(u | |||
|             return del; | ||||
|         } | ||||
|         return numeric_traits<T>::zero(); | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|         if (this->x_below_low_bound(p)) { | ||||
|             T del =  get_edge_steepness_for_low_bound(p); | ||||
|             T del =  get_edge_steepness_for_lower_bound(p); | ||||
|             return del; | ||||
|         } | ||||
|         return numeric_traits<T>::zero(); | ||||
|  | @ -244,7 +244,7 @@ template <typename T, typename X> int lp_dual_core_solver<T, X>::define_sign_of_ | |||
|             return 1; | ||||
|         } | ||||
|         lp_unreachable(); | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|         if (this->x_below_low_bound(m_p)) { | ||||
|             return -1; | ||||
|         } | ||||
|  | @ -264,17 +264,17 @@ template <typename T, typename X> int lp_dual_core_solver<T, X>::define_sign_of_ | |||
| template <typename T, typename X> bool lp_dual_core_solver<T, X>::can_be_breakpoint(unsigned j) { | ||||
|     if (this->pivot_row_element_is_too_small_for_ratio_test(j)) return false; | ||||
|     switch (this->m_column_types[j]) { | ||||
|     case column_type::low_bound: | ||||
|         lp_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_low_bounds[j])); | ||||
|     case column_type::lower_bound: | ||||
|         lp_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_lower_bounds[j])); | ||||
|         return m_sign_of_alpha_r * this->m_pivot_row[j]  > 0; | ||||
|     case column_type::upper_bound: | ||||
|         lp_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_upper_bounds[j])); | ||||
|         return m_sign_of_alpha_r * this->m_pivot_row[j] < 0; | ||||
|     case column_type::boxed: | ||||
|         { | ||||
|             bool low_bound = this->x_is_at_low_bound(j); | ||||
|             bool lower_bound = this->x_is_at_lower_bound(j); | ||||
|             bool grawing = m_sign_of_alpha_r * this->m_pivot_row[j] > 0; | ||||
|             return low_bound == grawing; | ||||
|             return lower_bound == grawing; | ||||
|         } | ||||
|     case column_type::fixed: // is always dual feasible so we ingore it
 | ||||
|         return false; | ||||
|  | @ -302,15 +302,15 @@ template <typename T, typename X> T lp_dual_core_solver<T, X>::get_delta() { | |||
|     switch (this->m_column_types[m_p]) { | ||||
|     case column_type::boxed: | ||||
|         if (this->x_below_low_bound(m_p)) { | ||||
|             return this->m_x[m_p] - this->m_low_bounds[m_p]; | ||||
|             return this->m_x[m_p] - this->m_lower_bounds[m_p]; | ||||
|         } | ||||
|         if (this->x_above_upper_bound(m_p)) { | ||||
|             return this->m_x[m_p] - this->m_upper_bounds[m_p]; | ||||
|         } | ||||
|         lp_unreachable(); | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|         if (this->x_below_low_bound(m_p)) { | ||||
|             return this->m_x[m_p] - this->m_low_bounds[m_p]; | ||||
|             return this->m_x[m_p] - this->m_lower_bounds[m_p]; | ||||
|         } | ||||
|         lp_unreachable(); | ||||
|     case column_type::upper_bound: | ||||
|  | @ -371,10 +371,10 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::update_betas() | |||
| template <typename T, typename X> void lp_dual_core_solver<T, X>::apply_flips() { | ||||
|     for (unsigned j : m_flipped_boxed) { | ||||
|         lp_assert(this->x_is_at_bound(j)); | ||||
|         if (this->x_is_at_low_bound(j)) { | ||||
|         if (this->x_is_at_lower_bound(j)) { | ||||
|             this->m_x[j] = this->m_upper_bounds[j]; | ||||
|         } else { | ||||
|             this->m_x[j] = this->m_low_bounds[j]; | ||||
|             this->m_x[j] = this->m_lower_bounds[j]; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -382,17 +382,17 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::apply_flips() | |||
| template <typename T, typename X> void lp_dual_core_solver<T, X>::snap_xN_column_to_bounds(unsigned j) { | ||||
|     switch (this->m_column_type[j]) { | ||||
|     case column_type::fixed: | ||||
|         this->m_x[j] = this->m_low_bounds[j]; | ||||
|         this->m_x[j] = this->m_lower_bounds[j]; | ||||
|         break; | ||||
|     case column_type::boxed: | ||||
|         if (this->x_is_at_low_bound(j)) { | ||||
|             this->m_x[j] = this->m_low_bounds[j]; | ||||
|         if (this->x_is_at_lower_bound(j)) { | ||||
|             this->m_x[j] = this->m_lower_bounds[j]; | ||||
|         } else { | ||||
|             this->m_x[j] = this->m_upper_bounds[j]; | ||||
|         } | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|         this->m_x[j] = this->m_low_bounds[j]; | ||||
|     case column_type::lower_bound: | ||||
|         this->m_x[j] = this->m_lower_bounds[j]; | ||||
|         break; | ||||
|     case column_type::upper_bound: | ||||
|         this->m_x[j] = this->m_upper_bounds[j]; | ||||
|  | @ -462,9 +462,9 @@ template <typename T, typename X> bool lp_dual_core_solver<T, X>::basis_change_a | |||
| 
 | ||||
| template <typename T, typename X> void lp_dual_core_solver<T, X>::recover_leaving() { | ||||
|     switch (m_entering_boundary_position) { | ||||
|     case at_low_bound: | ||||
|     case at_lower_bound: | ||||
|     case at_fixed: | ||||
|         this->m_x[m_q] = this->m_low_bounds[m_q]; | ||||
|         this->m_x[m_q] = this->m_lower_bounds[m_q]; | ||||
|         break; | ||||
|     case at_upper_bound: | ||||
|         this->m_x[m_q] = this->m_upper_bounds[m_q]; | ||||
|  | @ -497,23 +497,23 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::revert_to_prev | |||
| template <typename T, typename X> bool lp_dual_core_solver<T, X>::snap_runaway_nonbasic_column(unsigned j) { | ||||
|     switch (this->m_column_types[j]) { | ||||
|     case column_type::fixed: | ||||
|     case column_type::low_bound: | ||||
|         if (!this->x_is_at_low_bound(j)) { | ||||
|             this->m_x[j] = this->m_low_bounds[j]; | ||||
|     case column_type::lower_bound: | ||||
|         if (!this->x_is_at_lower_bound(j)) { | ||||
|             this->m_x[j] = this->m_lower_bounds[j]; | ||||
|             return true; | ||||
|         } | ||||
|         break; | ||||
|     case column_type::boxed: | ||||
|         { | ||||
|             bool closer_to_low_bound = abs(this->m_low_bounds[j] - this->m_x[j]) < abs(this->m_upper_bounds[j] - this->m_x[j]); | ||||
|             if (closer_to_low_bound) { | ||||
|                 if (!this->x_is_at_low_bound(j)) { | ||||
|                     this->m_x[j] = this->m_low_bounds[j]; | ||||
|             bool closer_to_lower_bound = abs(this->m_lower_bounds[j] - this->m_x[j]) < abs(this->m_upper_bounds[j] - this->m_x[j]); | ||||
|             if (closer_to_lower_bound) { | ||||
|                 if (!this->x_is_at_lower_bound(j)) { | ||||
|                     this->m_x[j] = this->m_lower_bounds[j]; | ||||
|                     return true; | ||||
|                 } | ||||
|             } else { | ||||
|                 if (!this->x_is_at_upper_bound(j)) { | ||||
|                     this->m_x[j] = this->m_low_bounds[j]; | ||||
|                     this->m_x[j] = this->m_lower_bounds[j]; | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|  | @ -539,7 +539,7 @@ template <typename T, typename X> bool lp_dual_core_solver<T, X>::problem_is_dua | |||
|             // 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_bounds[j] << "," << this->m_upper_bounds[j] << std::endl;
 | ||||
|             // std::cout << "bounds = " << this->m_lower_bounds[j] << "," << this->m_upper_bounds[j] << std::endl;
 | ||||
|             // std::cout << "total_iterations = " << this->total_iterations() << std::endl;
 | ||||
|             return false; | ||||
|         } | ||||
|  | @ -602,7 +602,7 @@ template <typename T, typename X> T lp_dual_core_solver<T, X>::calculate_harris_ | |||
|     lp_assert(m_breakpoint_set.size() > 0); | ||||
|     for (auto j : m_breakpoint_set) { | ||||
|         T t; | ||||
|         if (this->x_is_at_low_bound(j)) { | ||||
|         if (this->x_is_at_lower_bound(j)) { | ||||
|             t = abs((std::max(this->m_d[j], numeric_traits<T>::zero()) + m_harris_tolerance) / this->m_pivot_row[j]); | ||||
|         } else { | ||||
|             t = abs((std::min(this->m_d[j], numeric_traits<T>::zero()) - m_harris_tolerance) / this->m_pivot_row[j]); | ||||
|  | @ -620,7 +620,7 @@ template <typename T, typename X> T lp_dual_core_solver<T, X>::calculate_harris_ | |||
| template <typename T, typename X> void lp_dual_core_solver<T, X>::fill_tight_set_on_harris_delta(const T & harris_delta ){ | ||||
|     m_tight_set.clear(); | ||||
|     for (auto j : m_breakpoint_set) { | ||||
|         if (this->x_is_at_low_bound(j)) { | ||||
|         if (this->x_is_at_lower_bound(j)) { | ||||
|             if (abs(std::max(this->m_d[j], numeric_traits<T>::zero()) / this->m_pivot_row[j]) <= harris_delta){ | ||||
|                 m_tight_set.insert(j); | ||||
|             } | ||||
|  | @ -17,7 +17,7 @@ Revision History: | |||
| 
 | ||||
| 
 | ||||
| --*/ | ||||
| #include "util/lp/lp_dual_simplex.hpp" | ||||
| #include "util/lp/lp_dual_simplex_def.h" | ||||
| template lp::mpq lp::lp_dual_simplex<lp::mpq, lp::mpq>::get_current_cost() const; | ||||
| template void lp::lp_dual_simplex<lp::mpq, lp::mpq>::find_maximal_solution(); | ||||
| template double lp::lp_dual_simplex<double, double>::get_current_cost() const; | ||||
|  | @ -28,7 +28,7 @@ template <typename T, typename X> | |||
| class lp_dual_simplex: public lp_solver<T, X> { | ||||
|     lp_dual_core_solver<T, X> * m_core_solver; | ||||
|     vector<T> m_b_copy; | ||||
|     vector<T> 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
 | ||||
|     vector<T> m_lower_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
 | ||||
|     vector<column_type> m_column_types_of_core_solver; | ||||
|     vector<column_type> m_column_types_of_logicals; | ||||
|     vector<bool>  m_can_enter_basis; | ||||
|  |  | |||
|  | @ -48,13 +48,13 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::decide_on_status_a | |||
| template <typename T, typename X> void lp_dual_simplex<T, X>::fix_logical_for_stage2(unsigned j) { | ||||
|     lp_assert(j >= this->number_of_core_structurals()); | ||||
|     switch (m_column_types_of_logicals[j - this->number_of_core_structurals()]) { | ||||
|     case column_type::low_bound: | ||||
|         m_low_bounds[j] = numeric_traits<T>::zero(); | ||||
|         m_column_types_of_core_solver[j] = column_type::low_bound; | ||||
|     case column_type::lower_bound: | ||||
|         m_lower_bounds[j] = numeric_traits<T>::zero(); | ||||
|         m_column_types_of_core_solver[j] = column_type::lower_bound; | ||||
|         m_can_enter_basis[j] = true; | ||||
|         break; | ||||
|     case column_type::fixed: | ||||
|         this->m_upper_bounds[j] = m_low_bounds[j] = numeric_traits<T>::zero(); | ||||
|         this->m_upper_bounds[j] = m_lower_bounds[j] = numeric_traits<T>::zero(); | ||||
|         m_column_types_of_core_solver[j] = column_type::fixed; | ||||
|         m_can_enter_basis[j] = false; | ||||
|         break; | ||||
|  | @ -66,9 +66,9 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fix_logical_for_st | |||
| template <typename T, typename X> void lp_dual_simplex<T, X>::fix_structural_for_stage2(unsigned j) { | ||||
|     column_info<T> * ci = this->m_map_from_var_index_to_column_info[this->m_core_solver_columns_to_external_columns[j]]; | ||||
|     switch (ci->get_column_type()) { | ||||
|     case column_type::low_bound: | ||||
|         m_low_bounds[j] = numeric_traits<T>::zero(); | ||||
|         m_column_types_of_core_solver[j] = column_type::low_bound; | ||||
|     case column_type::lower_bound: | ||||
|         m_lower_bounds[j] = numeric_traits<T>::zero(); | ||||
|         m_column_types_of_core_solver[j] = column_type::lower_bound; | ||||
|         m_can_enter_basis[j] = true; | ||||
|         break; | ||||
|     case column_type::fixed: | ||||
|  | @ -76,7 +76,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fix_structural_for | |||
|         lp_unreachable(); | ||||
|     case column_type::boxed: | ||||
|         this->m_upper_bounds[j] = ci->get_adjusted_upper_bound() / this->m_column_scale[j]; | ||||
|         m_low_bounds[j] = numeric_traits<T>::zero(); | ||||
|         m_lower_bounds[j] = numeric_traits<T>::zero(); | ||||
|         m_column_types_of_core_solver[j] = column_type::boxed; | ||||
|         m_can_enter_basis[j] = true; | ||||
|         break; | ||||
|  | @ -158,7 +158,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::stage1() { | |||
|                                                   this->m_heading, | ||||
|                                                   this->m_costs, | ||||
|                                                   this->m_column_types_of_core_solver, | ||||
|                                                   this->m_low_bounds, | ||||
|                                                   this->m_lower_bounds, | ||||
|                                                   this->m_upper_bounds, | ||||
|                                                   this->m_settings, | ||||
|                                                   *this); | ||||
|  | @ -216,10 +216,10 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_bounds_ | |||
|         throw_exception(s.str()); | ||||
|         break; | ||||
|     } | ||||
|     case column_type::low_bound: { | ||||
|     case column_type::lower_bound: { | ||||
|         m_can_enter_basis[j] = true; | ||||
|         this->set_scaled_cost(j); | ||||
|         this->m_low_bounds[j] = numeric_traits<T>::zero(); | ||||
|         this->m_lower_bounds[j] = numeric_traits<T>::zero(); | ||||
|         this->m_upper_bounds[j] =numeric_traits<T>::one(); | ||||
|         break; | ||||
|     } | ||||
|  | @ -227,13 +227,13 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_bounds_ | |||
|         m_can_enter_basis[j] = true; | ||||
|         this->set_scaled_cost(j); | ||||
|         this->m_upper_bounds[j] = free_bound; | ||||
|         this->m_low_bounds[j] =  -free_bound; | ||||
|         this->m_lower_bounds[j] =  -free_bound; | ||||
|         break; | ||||
|     } | ||||
|     case column_type::boxed: | ||||
|         m_can_enter_basis[j] = false; | ||||
|         this->m_costs[j] = numeric_traits<T>::zero(); | ||||
|         this->m_upper_bounds[j] = this->m_low_bounds[j] =  numeric_traits<T>::zero(); // is it needed?
 | ||||
|         this->m_upper_bounds[j] = this->m_lower_bounds[j] =  numeric_traits<T>::zero(); // is it needed?
 | ||||
|         break; | ||||
|     default: | ||||
|         lp_unreachable(); | ||||
|  | @ -244,13 +244,13 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_bounds_ | |||
| template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_bounds_types_and_can_enter_basis_for_the_first_stage_solver_logical_column(unsigned j) { | ||||
|     this->m_costs[j] = 0; | ||||
|     lp_assert(get_column_type(j) != column_type::upper_bound); | ||||
|     if ((m_can_enter_basis[j] = (get_column_type(j) == column_type::low_bound))) { | ||||
|     if ((m_can_enter_basis[j] = (get_column_type(j) == column_type::lower_bound))) { | ||||
|         m_column_types_of_core_solver[j] = column_type::boxed; | ||||
|         this->m_low_bounds[j] = numeric_traits<T>::zero(); | ||||
|         this->m_lower_bounds[j] = numeric_traits<T>::zero(); | ||||
|         this->m_upper_bounds[j] = numeric_traits<T>::one(); | ||||
|     } else { | ||||
|         m_column_types_of_core_solver[j] = column_type::fixed; | ||||
|         this->m_low_bounds[j] = numeric_traits<T>::zero(); | ||||
|         this->m_lower_bounds[j] = numeric_traits<T>::zero(); | ||||
|         this->m_upper_bounds[j] = numeric_traits<T>::zero(); | ||||
|     } | ||||
| } | ||||
|  | @ -283,7 +283,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_first_stage_s | |||
|         break; | ||||
| 
 | ||||
|     case Greater_or_equal: | ||||
|         set_type_for_logical(slack_var, column_type::low_bound); | ||||
|         set_type_for_logical(slack_var, column_type::lower_bound); | ||||
|         (*this->m_A)(row, slack_var) = - numeric_traits<T>::one(); | ||||
|         if (rs > 0) { | ||||
|             // adding one artificial
 | ||||
|  | @ -301,7 +301,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_first_stage_s | |||
|         break; | ||||
|     case Less_or_equal: | ||||
|         // introduce a non-negative slack variable
 | ||||
|         set_type_for_logical(slack_var, column_type::low_bound); | ||||
|         set_type_for_logical(slack_var, column_type::lower_bound); | ||||
|         (*this->m_A)(row, slack_var) = numeric_traits<T>::one(); | ||||
|         if (rs < 0) { | ||||
|             // adding one artificial
 | ||||
|  | @ -328,7 +328,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::augment_matrix_A_a | |||
|     m_column_types_of_logicals.resize(this->m_slacks + this->m_artificials); | ||||
|     this->m_costs.resize(n); | ||||
|     this->m_upper_bounds.resize(n); | ||||
|     this->m_low_bounds.resize(n); | ||||
|     this->m_lower_bounds.resize(n); | ||||
|     m_can_enter_basis.resize(n); | ||||
|     this->m_basis.resize(this->m_A->row_count()); | ||||
| } | ||||
|  | @ -23,8 +23,8 @@ Revision History: | |||
| #include "util/vector.h" | ||||
| #include <functional> | ||||
| #include "util/lp/lar_solver.h" | ||||
| #include "util/lp/lp_primal_core_solver.hpp" | ||||
| #include "util/lp/lp_primal_core_solver_tableau.hpp" | ||||
| #include "util/lp/lp_primal_core_solver_def.h" | ||||
| #include "util/lp/lp_primal_core_solver_tableau_def.h" | ||||
| namespace lp { | ||||
| 
 | ||||
| template void lp_primal_core_solver<double, double>::find_feasible_solution(); | ||||
|  | @ -40,7 +40,7 @@ Revision History: | |||
| #include "util/lp/iterator_on_row.h" | ||||
| namespace lp { | ||||
| 
 | ||||
| // This core solver solves (Ax=b, low_bound_values \leq x \leq upper_bound_values, maximize costs*x )
 | ||||
| // This core solver solves (Ax=b, lower_bound_values \leq x \leq upper_bound_values, maximize costs*x )
 | ||||
| // The right side b is given implicitly by x and the basis
 | ||||
| template <typename T, typename X> | ||||
| class lp_primal_core_solver:public lp_core_solver_base<T, X> { | ||||
|  | @ -118,17 +118,17 @@ public: | |||
|         switch (this->m_column_types[j]) { | ||||
|         case column_type::free_column: return true; | ||||
|         case column_type::fixed: return false; | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             if (sign < 0) | ||||
|                 return true; | ||||
|             return !this->x_is_at_low_bound(j); | ||||
|             return !this->x_is_at_lower_bound(j); | ||||
|         case column_type::upper_bound: | ||||
|             if (sign > 0) | ||||
|                 return true; | ||||
|             return !this->x_is_at_upper_bound(j); | ||||
|         case column_type::boxed: | ||||
|             if (sign < 0) | ||||
|                 return !this->x_is_at_low_bound(j); | ||||
|                 return !this->x_is_at_lower_bound(j); | ||||
|             return !this->x_is_at_upper_bound(j); | ||||
|         } | ||||
| 
 | ||||
|  | @ -143,7 +143,7 @@ public: | |||
|         case column_type::free_column: | ||||
|             return false; | ||||
|         case column_type::fixed:  | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|         case column_type::boxed: | ||||
|             return this-> x_below_low_bound(bj); | ||||
|         default: | ||||
|  | @ -158,7 +158,7 @@ public: | |||
|         switch(this->m_column_types[bj]) { | ||||
|         case column_type::free_column: | ||||
|             return 0; | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             return 1; | ||||
|         case column_type::fixed:  | ||||
|         case column_type::boxed:             | ||||
|  | @ -180,9 +180,9 @@ public: | |||
|             return true; | ||||
|         case column_type::fixed: | ||||
|             return false; | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             if (is_pos(rc.get_val())) { | ||||
|                 return this->x_above_low_bound(j); | ||||
|                 return this->x_above_lower_bound(j); | ||||
|             } | ||||
| 
 | ||||
|             return true; | ||||
|  | @ -194,7 +194,7 @@ public: | |||
|             return this->x_below_upper_bound(j); | ||||
|         case column_type::boxed: | ||||
|             if (is_pos(rc.get_val())) { | ||||
|                 return this->x_above_low_bound(j); | ||||
|                 return this->x_above_lower_bound(j); | ||||
|             } | ||||
| 
 | ||||
|             return this->x_below_upper_bound(j); | ||||
|  | @ -213,9 +213,9 @@ public: | |||
|             return true; | ||||
|         case column_type::fixed: | ||||
|             return false; | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             if (is_neg(rc.get_val())) { | ||||
|                 return this->x_above_low_bound(j); | ||||
|                 return this->x_above_lower_bound(j); | ||||
|             } | ||||
| 
 | ||||
|             return true; | ||||
|  | @ -227,7 +227,7 @@ public: | |||
|             return this->x_below_upper_bound(j); | ||||
|         case column_type::boxed: | ||||
|             if (is_neg(rc.get_val())) { | ||||
|                 return this->x_above_low_bound(j); | ||||
|                 return this->x_above_lower_bound(j); | ||||
|             } | ||||
| 
 | ||||
|             return this->x_below_upper_bound(j); | ||||
|  | @ -349,15 +349,15 @@ public: | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void limit_theta_on_basis_column_for_inf_case_m_neg_low_bound(unsigned j, const T & m, X & theta, bool & unlimited) { | ||||
|         lp_assert(m < 0 && this->m_column_types[j] == column_type::low_bound); | ||||
|         limit_inf_on_bound_m_neg(m, this->m_x[j], this->m_low_bounds[j], theta, unlimited); | ||||
|     void limit_theta_on_basis_column_for_inf_case_m_neg_lower_bound(unsigned j, const T & m, X & theta, bool & unlimited) { | ||||
|         lp_assert(m < 0 && this->m_column_types[j] == column_type::lower_bound); | ||||
|         limit_inf_on_bound_m_neg(m, this->m_x[j], this->m_lower_bounds[j], theta, unlimited); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void limit_theta_on_basis_column_for_inf_case_m_pos_low_bound(unsigned j, const T & m, X & theta, bool & unlimited) { | ||||
|         lp_assert(m > 0 && this->m_column_types[j] == column_type::low_bound); | ||||
|         limit_inf_on_low_bound_m_pos(m, this->m_x[j], this->m_low_bounds[j], theta, unlimited); | ||||
|     void limit_theta_on_basis_column_for_inf_case_m_pos_lower_bound(unsigned j, const T & m, X & theta, bool & unlimited) { | ||||
|         lp_assert(m > 0 && this->m_column_types[j] == column_type::lower_bound); | ||||
|         limit_inf_on_lower_bound_m_pos(m, this->m_x[j], this->m_lower_bounds[j], theta, unlimited); | ||||
|     } | ||||
| 
 | ||||
|     void limit_theta_on_basis_column_for_inf_case_m_pos_upper_bound(unsigned j, const T & m, X & theta, bool & unlimited) { | ||||
|  | @ -370,7 +370,7 @@ public: | |||
| 
 | ||||
|     void get_bound_on_variable_and_update_leaving_precisely(unsigned j, vector<unsigned> & leavings, T m, X & t, T & abs_of_d_of_leaving); | ||||
| 
 | ||||
|     vector<T> m_low_bounds_dummy; // needed for the base class only
 | ||||
|     vector<T> m_lower_bounds_dummy; // needed for the base class only
 | ||||
| 
 | ||||
|     X get_max_bound(vector<X> & b); | ||||
| 
 | ||||
|  | @ -464,14 +464,14 @@ public: | |||
|         case column_type::upper_bound: | ||||
|             new_val_for_leaving = this->m_upper_bounds[j]; | ||||
|             break; | ||||
|         case column_type::low_bound: | ||||
|             new_val_for_leaving = this->m_low_bounds[j]; | ||||
|         case column_type::lower_bound: | ||||
|             new_val_for_leaving = this->m_lower_bounds[j]; | ||||
|             break; | ||||
|         case column_type::boxed: | ||||
|             if (this->x_above_upper_bound(j)) | ||||
|                 new_val_for_leaving = this->m_upper_bounds[j]; | ||||
|             else | ||||
|                 new_val_for_leaving = this->m_low_bounds[j]; | ||||
|                 new_val_for_leaving = this->m_lower_bounds[j]; | ||||
|             break; | ||||
|         default: | ||||
|             lp_assert(false); | ||||
|  | @ -528,18 +528,18 @@ public: | |||
| 
 | ||||
|     // void limit_theta_on_basis_column_for_feas_case_m_neg(unsigned j, const T & m, X & theta) {
 | ||||
|     //     lp_assert(m < 0);
 | ||||
|     //     lp_assert(this->m_column_type[j] == low_bound || this->m_column_type[j] == boxed);
 | ||||
|     //     const X & eps = harris_eps_for_bound(this->m_low_bounds[j]);
 | ||||
|     //     if (this->above_bound(this->m_x[j], this->m_low_bounds[j])) {
 | ||||
|     //         theta = std::min((this->m_low_bounds[j] -this->m_x[j] - eps) / m, theta);
 | ||||
|     //     lp_assert(this->m_column_type[j] == lower_bound || this->m_column_type[j] == boxed);
 | ||||
|     //     const X & eps = harris_eps_for_bound(this->m_lower_bounds[j]);
 | ||||
|     //     if (this->above_bound(this->m_x[j], this->m_lower_bounds[j])) {
 | ||||
|     //         theta = std::min((this->m_lower_bounds[j] -this->m_x[j] - eps) / m, theta);
 | ||||
|     //         if (theta < zero_of_type<X>()) theta = zero_of_type<X>();
 | ||||
|     //     }
 | ||||
|     // }
 | ||||
| 
 | ||||
|     void limit_theta_on_basis_column_for_feas_case_m_neg_no_check(unsigned j, const T & m, X & theta, bool & unlimited) { | ||||
|         lp_assert(m < 0); | ||||
|         const X& eps = harris_eps_for_bound(this->m_low_bounds[j]); | ||||
|         limit_theta((this->m_low_bounds[j] - this->m_x[j] - eps) / m, theta, unlimited); | ||||
|         const X& eps = harris_eps_for_bound(this->m_lower_bounds[j]); | ||||
|         limit_theta((this->m_lower_bounds[j] - this->m_x[j] - eps) / m, theta, unlimited); | ||||
|         if (theta < zero_of_type<X>()) theta = zero_of_type<X>(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -591,7 +591,7 @@ public: | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     void limit_inf_on_low_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) { | ||||
|     void limit_inf_on_lower_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) { | ||||
|         if (numeric_traits<T>::precise()) { | ||||
|             // x gets larger
 | ||||
|             lp_assert(m > 0); | ||||
|  | @ -621,7 +621,7 @@ public: | |||
|     void limit_theta_on_basis_column_for_inf_case_m_pos_boxed(unsigned j, const T & m, X & theta, bool & unlimited) { | ||||
|         //        lp_assert(m > 0 && this->m_column_type[j] == column_type::boxed);
 | ||||
|         const X & x = this->m_x[j]; | ||||
|         const X & lbound = this->m_low_bounds[j]; | ||||
|         const X & lbound = this->m_lower_bounds[j]; | ||||
| 
 | ||||
|         if (this->below_bound(x, lbound)) { | ||||
|             const X& eps = harris_eps_for_bound(this->m_upper_bounds[j]); | ||||
|  | @ -646,7 +646,7 @@ public: | |||
|             const X& eps = harris_eps_for_bound(ubound); | ||||
|             limit_theta((ubound - x - eps) / m, theta, unlimited); | ||||
|         } else { | ||||
|             const X & lbound = this->m_low_bounds[j]; | ||||
|             const X & lbound = this->m_lower_bounds[j]; | ||||
|             if (this->above_bound(x, lbound)){ | ||||
|                 const X& eps = harris_eps_for_bound(lbound); | ||||
|                 limit_theta((lbound - x - eps) / m, theta, unlimited); | ||||
|  | @ -679,7 +679,7 @@ public: | |||
| 
 | ||||
|     // j is a basic column or the entering, in any case x[j] has to stay feasible.
 | ||||
|     // m is the multiplier. updating t in a way that holds the following
 | ||||
|     // x[j] + t * m >=  this->m_low_bounds[j]- harris_feasibility_tolerance ( if m < 0 )
 | ||||
|     // x[j] + t * m >=  this->m_lower_bounds[j]- harris_feasibility_tolerance ( if m < 0 )
 | ||||
|     // or
 | ||||
|     // x[j] + t * m <= this->m_upper_bounds[j] + harris_feasibility_tolerance ( if m > 0)
 | ||||
|     void limit_theta_on_basis_column(unsigned j, T m, X & theta, bool & unlimited) { | ||||
|  | @ -696,15 +696,15 @@ public: | |||
|                     limit_theta_on_basis_column_for_inf_case_m_neg_upper_bound(j, m, theta, unlimited); | ||||
|             } | ||||
|             break; | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             if (this->current_x_is_feasible()) { | ||||
|                 if (m < 0) | ||||
|                     limit_theta_on_basis_column_for_feas_case_m_neg_no_check(j, m, theta, unlimited); | ||||
|             } else { | ||||
|                 if (m < 0) | ||||
|                     limit_theta_on_basis_column_for_inf_case_m_neg_low_bound(j, m, theta, unlimited); | ||||
|                     limit_theta_on_basis_column_for_inf_case_m_neg_lower_bound(j, m, theta, unlimited); | ||||
|                 else | ||||
|                     limit_theta_on_basis_column_for_inf_case_m_pos_low_bound(j, m, theta, unlimited); | ||||
|                     limit_theta_on_basis_column_for_inf_case_m_pos_lower_bound(j, m, theta, unlimited); | ||||
|             } | ||||
|             break; | ||||
|             // case fixed:
 | ||||
|  | @ -770,7 +770,7 @@ public: | |||
| 
 | ||||
|     void init_reduced_costs(); | ||||
| 
 | ||||
|     bool low_bounds_are_set() const override { return true; } | ||||
|     bool lower_bounds_are_set() const override { return true; } | ||||
| 
 | ||||
|     int advance_on_sorted_breakpoints(unsigned entering, X & t); | ||||
|      | ||||
|  | @ -807,7 +807,7 @@ public: | |||
|             if (this->x_above_upper_bound(j)) | ||||
|                 return 1; | ||||
|             break; | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             if (this->x_below_low_bound(j)) | ||||
|                 return -1; | ||||
|             break; | ||||
|  | @ -842,11 +842,11 @@ public: | |||
|         case column_type::fixed: | ||||
|             return 0; | ||||
|         case column_type::boxed: | ||||
|             if (this->x_is_at_low_bound(j)) | ||||
|             if (this->x_is_at_lower_bound(j)) | ||||
|                 return 1; | ||||
|             return -1; | ||||
|             break; | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             return 1; | ||||
|             break; | ||||
|         case column_type::upper_bound: | ||||
|  | @ -906,7 +906,7 @@ public: | |||
|                           vector<int> & heading, | ||||
|                           vector<T> & costs, | ||||
|                           const vector<column_type> & column_type_array, | ||||
|                           const vector<X> & low_bound_values, | ||||
|                           const vector<X> & lower_bound_values, | ||||
|                           const vector<X> & upper_bound_values, | ||||
|                           lp_settings & settings, | ||||
|                           const column_namer& column_names): | ||||
|  | @ -919,7 +919,7 @@ public: | |||
|                                   settings, | ||||
|                                   column_names, | ||||
|                                   column_type_array, | ||||
|                                   low_bound_values, | ||||
|                                   lower_bound_values, | ||||
|                                   upper_bound_values), | ||||
|         m_beta(A.row_count()), | ||||
|         m_epsilon_of_reduced_cost(T(1)/T(10000000)), | ||||
|  | @ -954,12 +954,12 @@ public: | |||
|                                   settings, | ||||
|                                   column_names, | ||||
|                                   column_type_array, | ||||
|                                   m_low_bounds_dummy, | ||||
|                                   m_lower_bounds_dummy, | ||||
|                                   upper_bound_values), | ||||
|         m_beta(A.row_count()), | ||||
|         m_converted_harris_eps(convert_struct<T, double>::convert(this->m_settings.harris_feasibility_tolerance)) { | ||||
|         lp_assert(initial_x_is_correct()); | ||||
|         m_low_bounds_dummy.resize(A.column_count(), zero_of_type<T>()); | ||||
|         m_lower_bounds_dummy.resize(A.column_count(), zero_of_type<T>()); | ||||
|         m_enter_price_eps = numeric_traits<T>::precise() ? numeric_traits<T>::zero() : T(1e-5); | ||||
| #ifdef Z3DEBUG | ||||
|         // check_correctness();
 | ||||
|  | @ -972,7 +972,7 @@ public: | |||
|             basis_set.insert(this->m_basis[i]); | ||||
|         } | ||||
|         for (unsigned j = 0; j < this->m_n(); j++) { | ||||
|             if (this->column_has_low_bound(j) && this->m_x[j] < numeric_traits<T>::zero()) { | ||||
|             if (this->column_has_lower_bound(j) && this->m_x[j] < numeric_traits<T>::zero()) { | ||||
|                 LP_OUT(this->m_settings, "low bound for variable " << j << " does not hold: this->m_x[" << j << "] = " << this->m_x[j] << " is negative " << std::endl); | ||||
|                 return false; | ||||
|             } | ||||
|  | @ -983,7 +983,7 @@ public: | |||
|             } | ||||
| 
 | ||||
|             if (basis_set.find(j) != basis_set.end()) continue; | ||||
|             if (this->m_column_types[j] == column_type::low_bound)  { | ||||
|             if (this->m_column_types[j] == column_type::lower_bound)  { | ||||
|                 if (numeric_traits<T>::zero() != this->m_x[j]) { | ||||
|                     LP_OUT(this->m_settings, "only low bound is set for " << j << " but low bound value " << numeric_traits<T>::zero() << " is not equal to " << this->m_x[j] << std::endl); | ||||
|                     return false; | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ Revision History: | |||
| #include <string> | ||||
| #include "util/lp/lp_primal_core_solver.h" | ||||
| namespace lp { | ||||
| // This core solver solves (Ax=b, low_bound_values \leq x \leq upper_bound_values, maximize costs*x )
 | ||||
| // This core solver solves (Ax=b, lower_bound_values \leq x \leq upper_bound_values, maximize costs*x )
 | ||||
| // The right side b is given implicitly by x and the basis
 | ||||
| 
 | ||||
| template <typename T, typename X> | ||||
|  | @ -84,8 +84,8 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_on_breakpoin | |||
|     bool ret; | ||||
|     const T & d = this->m_d[j]; | ||||
|     switch (this->m_column_types[j]) { | ||||
|     case column_type::low_bound: | ||||
|         lp_assert(this->x_is_at_low_bound(j)); | ||||
|     case column_type::lower_bound: | ||||
|         lp_assert(this->x_is_at_lower_bound(j)); | ||||
|         ret = d < -m_epsilon_of_reduced_cost; | ||||
|         break; | ||||
|     case column_type::upper_bound: | ||||
|  | @ -97,9 +97,9 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_on_breakpoin | |||
|         break; | ||||
|     case column_type::boxed: | ||||
|         { | ||||
|             bool low_bound = this->x_is_at_low_bound(j); | ||||
|             lp_assert(low_bound || this->x_is_at_upper_bound(j)); | ||||
|             ret = (low_bound && d < -m_epsilon_of_reduced_cost) || ((!low_bound) && d > m_epsilon_of_reduced_cost); | ||||
|             bool lower_bound = this->x_is_at_lower_bound(j); | ||||
|             lp_assert(lower_bound || this->x_is_at_upper_bound(j)); | ||||
|             ret = (lower_bound && d < -m_epsilon_of_reduced_cost) || ((!lower_bound) && d > m_epsilon_of_reduced_cost); | ||||
|         } | ||||
|         break; | ||||
|     case column_type::free_column: | ||||
|  | @ -125,7 +125,7 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis(unsign | |||
|         if (dj > m_epsilon_of_reduced_cost || dj < -m_epsilon_of_reduced_cost) | ||||
|             return true; | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|         if (dj > m_epsilon_of_reduced_cost) return true;; | ||||
|         break; | ||||
|     case column_type::upper_bound: | ||||
|  | @ -137,7 +137,7 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis(unsign | |||
|                 return true; | ||||
|             break; | ||||
|         } else if (dj < - m_epsilon_of_reduced_cost) { | ||||
|             if (this->m_x[j] > this->m_low_bounds[j] + this->bound_span(j)/2) | ||||
|             if (this->m_x[j] > this->m_lower_bounds[j] + this->bound_span(j)/2) | ||||
|                 return true; | ||||
|         } | ||||
|         break; | ||||
|  | @ -159,9 +159,9 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precis | |||
|         if (!is_zero(dj)) | ||||
|             return true; | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|         if (dj > zero_of_type<T>()) return true; | ||||
|         if (dj < 0 && this->m_x[j] > this->m_low_bounds[j]){ | ||||
|         if (dj < 0 && this->m_x[j] > this->m_lower_bounds[j]){ | ||||
|             return true; | ||||
|         } | ||||
|         break; | ||||
|  | @ -177,7 +177,7 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precis | |||
|                 return true; | ||||
|             break; | ||||
|         } else if (dj < zero_of_type<T>()) { | ||||
|             if (this->m_x[j] > this->m_low_bounds[j]) | ||||
|             if (this->m_x[j] > this->m_lower_bounds[j]) | ||||
|                 return true; | ||||
|         } | ||||
|         break; | ||||
|  | @ -364,7 +364,7 @@ template <typename T, typename X> bool lp_primal_core_solver<T, X>::try_jump_to_ | |||
|                     return true; | ||||
|                 } | ||||
|             } else { // m_sign_of_entering_delta == -1
 | ||||
|                 t = this->m_x[entering] - this->m_low_bounds[entering]; | ||||
|                 t = this->m_x[entering] - this->m_lower_bounds[entering]; | ||||
|                 if (unlimited || t <= theta) { | ||||
|                     lp_assert(t >= zero_of_type<X>()); | ||||
|                     return true; | ||||
|  | @ -380,9 +380,9 @@ template <typename T, typename X> bool lp_primal_core_solver<T, X>::try_jump_to_ | |||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|         if (m_sign_of_entering_delta < 0) { | ||||
|                 t = this->m_x[entering] - this->m_low_bounds[entering]; | ||||
|                 t = this->m_x[entering] - this->m_lower_bounds[entering]; | ||||
|                 if (unlimited || t <= theta) { | ||||
|                     lp_assert(t >= zero_of_type<X>()); | ||||
|                     return true; | ||||
|  | @ -404,7 +404,7 @@ try_jump_to_another_bound_on_entering_unlimited(unsigned entering, X & t ) { | |||
|         return true; | ||||
|     } | ||||
|      // m_sign_of_entering_delta == -1
 | ||||
|     t = this->m_x[entering] - this->m_low_bounds[entering]; | ||||
|     t = this->m_x[entering] - this->m_lower_bounds[entering]; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
|  | @ -489,7 +489,7 @@ template <typename T, typename X>    int lp_primal_core_solver<T, X>::find_leavi | |||
| 
 | ||||
| 
 | ||||
| // m is the multiplier. updating t in a way that holds the following
 | ||||
| // x[j] + t * m >= m_low_bounds[j] ( if m < 0 )
 | ||||
| // x[j] + t * m >= m_lower_bounds[j] ( if m < 0 )
 | ||||
| // or
 | ||||
| // x[j] + t * m <= this->m_upper_bounds[j] ( if m > 0)
 | ||||
| template <typename T, typename X> void | ||||
|  | @ -501,7 +501,7 @@ lp_primal_core_solver<T, X>::get_bound_on_variable_and_update_leaving_precisely( | |||
|             return; | ||||
|         default:break; | ||||
|         } | ||||
|         X tt = - (this->m_low_bounds[j] - this->m_x[j]) / m; | ||||
|         X tt = - (this->m_lower_bounds[j] - this->m_x[j]) / m; | ||||
|         if (numeric_traits<X>::is_neg(tt)) | ||||
|             tt = zero_of_type<X>(); | ||||
|         if (leavings.size() == 0 || tt < t || (tt == t && m > abs_of_d_of_leaving)) { | ||||
|  | @ -516,7 +516,7 @@ lp_primal_core_solver<T, X>::get_bound_on_variable_and_update_leaving_precisely( | |||
|     } else if (m < 0){ | ||||
|         switch (this->m_column_types[j]) { // check that j has an upper bound
 | ||||
|         case column_type::free_column: | ||||
|         case column_type::low_bound: | ||||
|         case column_type::lower_bound: | ||||
|             return; | ||||
|         default:break; | ||||
|         } | ||||
|  | @ -558,7 +558,7 @@ template <typename T, typename X>    void lp_primal_core_solver<T, X>::check_the | |||
| } | ||||
| 
 | ||||
| template <typename T, typename X>    void lp_primal_core_solver<T, X>::check_bound(unsigned i) { | ||||
|     lp_assert (!(this->column_has_low_bound(i) && (numeric_traits<T>::zero() > this->m_x[i]))); | ||||
|     lp_assert (!(this->column_has_lower_bound(i) && (numeric_traits<T>::zero() > this->m_x[i]))); | ||||
|     lp_assert (!(this->column_has_upper_bound(i) && (this->m_upper_bounds[i] < this->m_x[i]))); | ||||
| } | ||||
| 
 | ||||
|  | @ -1136,7 +1136,7 @@ lp_primal_core_solver<T, X>::get_infeasibility_cost_for_column(unsigned j) const | |||
|             ret = numeric_traits<T>::zero(); | ||||
|         } | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|         if (this->x_below_low_bound(j)) { | ||||
|             ret = -1; | ||||
|         } else { | ||||
|  | @ -1190,7 +1190,7 @@ lp_primal_core_solver<T, X>::init_infeasibility_cost_for_column(unsigned j) { | |||
|             this->m_costs[j] = numeric_traits<T>::zero(); | ||||
|         } | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|     case column_type::lower_bound: | ||||
|         if (this->x_below_low_bound(j)) { | ||||
|             this->m_costs[j] = -1; | ||||
|         } else { | ||||
|  | @ -1228,13 +1228,13 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::print_column | |||
|     switch (this->m_column_type[j]) { | ||||
|     case column_type::fixed: | ||||
|     case column_type::boxed: | ||||
|         out <<  "( " << this->m_low_bounds[j] << " " << this->m_x[j] << " " << this->m_upper_bounds[j] << ")" << std::endl; | ||||
|         out <<  "( " << this->m_lower_bounds[j] << " " << this->m_x[j] << " " << this->m_upper_bounds[j] << ")" << std::endl; | ||||
|         break; | ||||
|     case column_type::upper_bound: | ||||
|         out <<  "( _"  << this->m_x[j] << " " << this->m_upper_bounds[j] << ")" << std::endl; | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|         out <<  "( " << this->m_low_bounds[j] << " " << this->m_x[j] << " " << "_ )" << std::endl; | ||||
|     case column_type::lower_bound: | ||||
|         out <<  "( " << this->m_lower_bounds[j] << " " << this->m_x[j] << " " << "_ )" << std::endl; | ||||
|         break; | ||||
|     case column_type::free_column: | ||||
|         out << "( _" << this->m_x[j] << "_)" << std::endl; | ||||
|  | @ -1343,14 +1343,14 @@ template <typename T, typename X>    void lp_primal_core_solver<T, X>::try_add_b | |||
|     const X & x = this->m_x[j]; | ||||
|     switch (this->m_column_types[j]) { | ||||
|     case column_type::fixed: | ||||
|         try_add_breakpoint(j, x, d, fixed_break, this->m_low_bounds[j]); | ||||
|         try_add_breakpoint(j, x, d, fixed_break, this->m_lower_bounds[j]); | ||||
|         break; | ||||
|     case column_type::boxed: | ||||
|         try_add_breakpoint(j, x, d, low_break, this->m_low_bounds[j]); | ||||
|         try_add_breakpoint(j, x, d, low_break, this->m_lower_bounds[j]); | ||||
|         try_add_breakpoint(j, x, d, upper_break, this->m_upper_bounds[j]); | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|         try_add_breakpoint(j, x, d, low_break, this->m_low_bounds[j]); | ||||
|     case column_type::lower_bound: | ||||
|         try_add_breakpoint(j, x, d, low_break, this->m_lower_bounds[j]); | ||||
|         break; | ||||
|     case column_type::upper_bound: | ||||
|         try_add_breakpoint(j, x, d, upper_break, this->m_upper_bounds[j]); | ||||
|  | @ -1370,10 +1370,10 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::print_bound_ | |||
|     switch (this->m_column_types[j]) { | ||||
|     case column_type::fixed: | ||||
|     case column_type::boxed: | ||||
|         out << "[" << this->m_low_bounds[j] << "," << this->m_upper_bounds[j] << "]" << std::endl; | ||||
|         out << "[" << this->m_lower_bounds[j] << "," << this->m_upper_bounds[j] << "]" << std::endl; | ||||
|         break; | ||||
|     case column_type::low_bound: | ||||
|         out << "[" << this->m_low_bounds[j] << ", inf" << std::endl; | ||||
|     case column_type::lower_bound: | ||||
|         out << "[" << this->m_lower_bounds[j] << ", inf" << std::endl; | ||||
|         break; | ||||
|     case column_type::upper_bound: | ||||
|         out << "inf ," << this->m_upper_bounds[j] << "]" << std::endl; | ||||
|  | @ -177,13 +177,13 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() { | |||
|         default: | ||||
|             break; // do nothing
 | ||||
|         } | ||||
| 	} while (this->get_status() != FLOATING_POINT_ERROR | ||||
|     } while (this->get_status() != lp_status::FLOATING_POINT_ERROR | ||||
| 		&& | ||||
| 		this->get_status() != UNBOUNDED | ||||
|              this->get_status() != lp_status::UNBOUNDED | ||||
| 		&& | ||||
| 		this->get_status() != OPTIMAL | ||||
|              this->get_status() != lp_status::OPTIMAL | ||||
| 		&& | ||||
| 		this->get_status() != INFEASIBLE | ||||
|              this->get_status() != lp_status::INFEASIBLE | ||||
| 		&& | ||||
| 		this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements | ||||
| 		&& | ||||
|  | @ -194,14 +194,17 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() { | |||
| 		this->m_settings.get_cancel_flag() == false); | ||||
| 	 | ||||
| 	if (this->m_settings.get_cancel_flag()) { | ||||
|             this->set_status(CANCELLED); | ||||
|         this->set_status(lp_status::CANCELLED); | ||||
| 	} | ||||
| 
 | ||||
|     lp_assert(this->get_status() == lp_status::FLOATING_POINT_ERROR | ||||
|                 || | ||||
|                 this->current_x_is_feasible() == false | ||||
|                 || | ||||
|                 this->calc_current_x_is_feasible_include_non_basis()); | ||||
| 	lp_assert( | ||||
|             this->get_status() == lp_status::FLOATING_POINT_ERROR | ||||
|             || | ||||
|             this->get_status() == lp_status::CANCELLED | ||||
|             || | ||||
|             this->current_x_is_feasible() == false | ||||
|             || | ||||
|             this->calc_current_x_is_feasible_include_non_basis()); | ||||
|     return this->total_iterations(); | ||||
| 
 | ||||
| } | ||||
|  | @ -22,7 +22,7 @@ Revision History: | |||
| #include <string> | ||||
| #include "util/vector.h" | ||||
| #include <functional> | ||||
| #include "util/lp/lp_primal_simplex.hpp" | ||||
| #include "util/lp/lp_primal_simplex_def.h" | ||||
| template bool lp::lp_primal_simplex<double, double>::bounds_hold(std::unordered_map<std::string, double, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, double> > > const&); | ||||
| template bool lp::lp_primal_simplex<double, double>::row_constraints_hold(std::unordered_map<std::string, double, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, double> > > const&); | ||||
| template double lp::lp_primal_simplex<double, double>::get_current_cost() const; | ||||
|  | @ -31,7 +31,7 @@ namespace lp { | |||
| template <typename T, typename X> | ||||
| class lp_primal_simplex: public lp_solver<T, X> { | ||||
|     lp_primal_core_solver<T, X> * m_core_solver; | ||||
|     vector<X> m_low_bounds; | ||||
|     vector<X> m_lower_bounds; | ||||
| private: | ||||
|     unsigned original_rows() { return this->m_external_rows_to_core_solver_rows.size(); } | ||||
| 
 | ||||
|  |  | |||
|  | @ -83,7 +83,7 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::fill_costs_and_x | |||
|     T artificial_cost =  - numeric_traits<T>::one(); | ||||
|     switch (constraint.m_relation) { | ||||
|     case Equal: // no slack variable here
 | ||||
|         this->m_column_types[artificial] = column_type::low_bound; | ||||
|         this->m_column_types[artificial] = column_type::lower_bound; | ||||
|         this->m_costs[artificial] = artificial_cost; // we are maximizing, so the artificial, which is non-negatiive, will be pushed to zero
 | ||||
|         this->m_basis[row] = artificial; | ||||
|         if (rs >= 0) { | ||||
|  | @ -97,13 +97,13 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::fill_costs_and_x | |||
|         break; | ||||
| 
 | ||||
|     case Greater_or_equal: | ||||
|         this->m_column_types[slack_var] = column_type::low_bound; | ||||
|         this->m_column_types[slack_var] = column_type::lower_bound; | ||||
|         (*this->m_A)(row, slack_var) = - numeric_traits<T>::one(); | ||||
| 
 | ||||
|         if (rs > 0) { | ||||
|             lp_assert(numeric_traits<T>::is_zero(this->m_x[slack_var])); | ||||
|             // adding one artificial
 | ||||
|             this->m_column_types[artificial] = column_type::low_bound; | ||||
|             this->m_column_types[artificial] = column_type::lower_bound; | ||||
|             (*this->m_A)(row, artificial) = numeric_traits<T>::one(); | ||||
|             this->m_costs[artificial] = artificial_cost; | ||||
|             this->m_basis[row] = artificial; | ||||
|  | @ -118,13 +118,13 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::fill_costs_and_x | |||
|         break; | ||||
|     case Less_or_equal: | ||||
|         // introduce a non-negative slack variable
 | ||||
|         this->m_column_types[slack_var] = column_type::low_bound; | ||||
|         this->m_column_types[slack_var] = column_type::lower_bound; | ||||
|         (*this->m_A)(row, slack_var) = numeric_traits<T>::one(); | ||||
| 
 | ||||
|         if (rs < 0) { | ||||
|             // adding one artificial
 | ||||
|             lp_assert(numeric_traits<T>::is_zero(this->m_x[slack_var])); | ||||
|             this->m_column_types[artificial] = column_type::low_bound; | ||||
|             this->m_column_types[artificial] = column_type::lower_bound; | ||||
|             (*this->m_A)(row, artificial) = - numeric_traits<T>::one(); | ||||
|             this->m_costs[artificial] = artificial_cost; | ||||
|             this->m_x[artificial] = - rs; | ||||
|  | @ -208,20 +208,20 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::fill_A_x_and_bas | |||
|         this->m_x[j] = this->m_b[row]; | ||||
|         (*this->m_A)(row, j) = numeric_traits<T>::one(); | ||||
|         this->m_column_types[j] = column_type::fixed; | ||||
|         this->m_upper_bounds[j] = m_low_bounds[j] = zero_of_type<X>(); | ||||
|         this->m_upper_bounds[j] = m_lower_bounds[j] = zero_of_type<X>(); | ||||
|         break; | ||||
| 
 | ||||
|     case Greater_or_equal: | ||||
|         this->m_x[j] = - this->m_b[row]; | ||||
|         (*this->m_A)(row, j) = - numeric_traits<T>::one(); | ||||
|         this->m_column_types[j] = column_type::low_bound; | ||||
|         this->m_column_types[j] = column_type::lower_bound; | ||||
|         this->m_upper_bounds[j] = zero_of_type<X>(); | ||||
|         break; | ||||
|     case Less_or_equal: | ||||
|         this->m_x[j] = this->m_b[row]; | ||||
|         (*this->m_A)(row, j) = numeric_traits<T>::one(); | ||||
|         this->m_column_types[j] = column_type::low_bound; | ||||
|         this->m_upper_bounds[j] = m_low_bounds[j] = zero_of_type<X>(); | ||||
|         this->m_column_types[j] = column_type::lower_bound; | ||||
|         this->m_upper_bounds[j] = m_lower_bounds[j] = zero_of_type<X>(); | ||||
|         break; | ||||
|     default: | ||||
|         lp_unreachable(); | ||||
|  | @ -234,8 +234,8 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::solve_with_total | |||
|         this->m_status = lp_status::OPTIMAL; | ||||
|         return; | ||||
|     } | ||||
|     m_low_bounds.clear(); | ||||
|     m_low_bounds.resize(total_vars, zero_of_type<X>());  // low bounds are shifted ot zero
 | ||||
|     m_lower_bounds.clear(); | ||||
|     m_lower_bounds.resize(total_vars, zero_of_type<X>());  // low bounds are shifted ot zero
 | ||||
|     this->m_x.resize(total_vars, numeric_traits<T>::zero()); | ||||
|     this->m_basis.resize(this->row_count()); | ||||
|     this->m_costs.clear(); | ||||
|  | @ -253,7 +253,7 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::solve_with_total | |||
|                                                     this->m_heading, | ||||
|                                                     this->m_costs, | ||||
|                                                     this->m_column_types, | ||||
|                                                     m_low_bounds, | ||||
|                                                     m_lower_bounds, | ||||
|                                                     this->m_upper_bounds, | ||||
|                                                     this->m_settings, *this); | ||||
|     m_core_solver->solve(); | ||||
|  | @ -19,7 +19,7 @@ Revision History: | |||
| --*/ | ||||
| #include <memory> | ||||
| #include "util/vector.h" | ||||
| #include "util/lp/lp_settings.hpp" | ||||
| #include "util/lp/lp_settings_def.h" | ||||
| template bool lp::vectors_are_equal<double>(vector<double> const&, vector<double> const&); | ||||
| template bool lp::vectors_are_equal<lp::mpq>(vector<lp::mpq > const&, vector<lp::mpq> const&); | ||||
| 
 | ||||
|  | @ -36,7 +36,7 @@ typedef vector<std::pair<mpq, constraint_index>> explanation_t; | |||
| 
 | ||||
| enum class column_type  { | ||||
|     free_column = 0, | ||||
|     low_bound = 1, | ||||
|     lower_bound = 1, | ||||
|     upper_bound = 2, | ||||
|     boxed = 3, | ||||
|     fixed = 4 | ||||
|  | @ -84,7 +84,7 @@ inline std::ostream& operator<<(std::ostream& out, lp_status status) { | |||
| 
 | ||||
| lp_status lp_status_from_string(std::string status); | ||||
| 
 | ||||
| enum non_basic_column_value_position { at_low_bound, at_upper_bound, at_fixed, free_of_bounds, not_at_bound }; | ||||
| enum non_basic_column_value_position { at_lower_bound, at_upper_bound, at_fixed, free_of_bounds, not_at_bound }; | ||||
| 
 | ||||
| template <typename X> bool is_epsilon_small(const X & v, const double& eps);    // forward definition
 | ||||
| 
 | ||||
|  | @ -102,6 +102,10 @@ struct stats { | |||
|     unsigned m_need_to_solve_inf; | ||||
|     unsigned m_max_cols; | ||||
|     unsigned m_max_rows; | ||||
|     unsigned m_cut_solver_calls; | ||||
|     unsigned m_cut_solver_true; | ||||
|     unsigned m_cut_solver_false; | ||||
|     unsigned m_cut_solver_undef; | ||||
|     stats() { reset(); } | ||||
|     void reset() { memset(this, 0, sizeof(*this)); } | ||||
| }; | ||||
|  | @ -222,7 +226,10 @@ public: | |||
|                     backup_costs(true), | ||||
|                     column_number_threshold_for_using_lu_in_lar_solver(4000), | ||||
|                     m_int_branch_cut_gomory_threshold(4), | ||||
|                     m_run_gcd_test(true) | ||||
|                     m_int_branch_cut_solver(4), | ||||
|                     m_run_gcd_test(true), | ||||
|                     m_cut_solver_bound_propagation_factor(5), | ||||
|                     m_cut_solver_cycle_on_var(10) | ||||
|     {} | ||||
| 
 | ||||
|     void set_resource_limit(lp_resource_limit& lim) { m_resource_limit = &lim; } | ||||
|  | @ -330,7 +337,10 @@ public: | |||
|     bool backup_costs; | ||||
|     unsigned column_number_threshold_for_using_lu_in_lar_solver; | ||||
|     unsigned m_int_branch_cut_gomory_threshold; | ||||
|     unsigned m_int_branch_cut_solver; | ||||
|     bool m_run_gcd_test; | ||||
|     unsigned m_cut_solver_bound_propagation_factor; | ||||
|     unsigned m_cut_solver_cycle_on_var; | ||||
| }; // end of lp_settings class
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ std::string column_type_to_string(column_type t) { | |||
|     switch (t) { | ||||
|     case column_type::fixed:       return "fixed"; | ||||
|     case column_type::boxed:       return "boxed"; | ||||
|     case column_type::low_bound:   return "low_bound"; | ||||
|     case column_type::lower_bound:   return "lower_bound"; | ||||
|     case column_type::upper_bound: return "upper_bound"; | ||||
|     case column_type::free_column: return "free_column"; | ||||
|     default:  lp_unreachable(); | ||||
|  | @ -18,7 +18,7 @@ Revision History: | |||
| 
 | ||||
| --*/ | ||||
| #include <string> | ||||
| #include "util/lp/lp_solver.hpp" | ||||
| #include "util/lp/lp_solver_def.h" | ||||
| template void lp::lp_solver<double, double>::add_constraint(lp::lp_relation, double, unsigned int); | ||||
| template void lp::lp_solver<double, double>::cleanup(); | ||||
| template void lp::lp_solver<double, double>::count_slacks_and_artificials(); | ||||
|  | @ -114,9 +114,9 @@ public: | |||
|     // returns -1 if not found
 | ||||
|     virtual int get_column_index_by_name(std::string name) const; | ||||
| 
 | ||||
|     void set_low_bound(unsigned i, T bound) { | ||||
|     void set_lower_bound(unsigned i, T bound) { | ||||
|         column_info<T> *ci = get_or_create_column_info(i); | ||||
|         ci->set_low_bound(bound); | ||||
|         ci->set_lower_bound(bound); | ||||
|     } | ||||
| 
 | ||||
|     void set_upper_bound(unsigned i, T bound) { | ||||
|  | @ -124,8 +124,8 @@ public: | |||
|         ci->set_upper_bound(bound); | ||||
|     } | ||||
| 
 | ||||
|     void unset_low_bound(unsigned i) { | ||||
|         get_or_create_column_info(i)->unset_low_bound(); | ||||
|     void unset_lower_bound(unsigned i) { | ||||
|         get_or_create_column_info(i)->unset_lower_bound(); | ||||
|     } | ||||
| 
 | ||||
|     void unset_upper_bound(unsigned i) { | ||||
|  | @ -194,9 +194,9 @@ protected: | |||
| 
 | ||||
|     void pin_vars_on_row_with_sign(std::unordered_map<unsigned, T> & row, T sign ); | ||||
| 
 | ||||
|     bool get_minimal_row_value(std::unordered_map<unsigned, T> & row, T & low_bound); | ||||
|     bool get_minimal_row_value(std::unordered_map<unsigned, T> & row, T & lower_bound); | ||||
| 
 | ||||
|     bool get_maximal_row_value(std::unordered_map<unsigned, T> & row, T & low_bound); | ||||
|     bool get_maximal_row_value(std::unordered_map<unsigned, T> & row, T & lower_bound); | ||||
| 
 | ||||
|     bool row_is_zero(std::unordered_map<unsigned, T> & row); | ||||
| 
 | ||||
|  | @ -244,7 +244,7 @@ protected: | |||
| 
 | ||||
|     void count_slacks_and_artificials_for_row(unsigned i); | ||||
| 
 | ||||
|     T low_bound_shift_for_row(unsigned i); | ||||
|     T lower_bound_shift_for_row(unsigned i); | ||||
| 
 | ||||
|     void fill_m_b(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -176,26 +176,26 @@ template <typename T, typename X> void lp_solver<T, X>::pin_vars_on_row_with_sig | |||
|             lp_assert(ci->upper_bound_is_set()); | ||||
|             ci->set_fixed_value(ci->get_upper_bound()); | ||||
|         } else { | ||||
|             lp_assert(ci->low_bound_is_set()); | ||||
|             ci->set_fixed_value(ci->get_low_bound()); | ||||
|             lp_assert(ci->lower_bound_is_set()); | ||||
|             ci->set_fixed_value(ci->get_lower_bound()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename X>    bool lp_solver<T, X>::get_minimal_row_value(std::unordered_map<unsigned, T> & row, T & low_bound) { | ||||
|     low_bound = numeric_traits<T>::zero(); | ||||
| template <typename T, typename X>    bool lp_solver<T, X>::get_minimal_row_value(std::unordered_map<unsigned, T> & row, T & lower_bound) { | ||||
|     lower_bound = numeric_traits<T>::zero(); | ||||
|     for (auto & t : row) { | ||||
|         T a = t.second; | ||||
|         column_info<T> * ci = m_map_from_var_index_to_column_info[t.first]; | ||||
|         if (a > numeric_traits<T>::zero()) { | ||||
|             if (ci->low_bound_is_set()) { | ||||
|                 low_bound += ci->get_low_bound() * a; | ||||
|             if (ci->lower_bound_is_set()) { | ||||
|                 lower_bound += ci->get_lower_bound() * a; | ||||
|             } else { | ||||
|                 return false; | ||||
|             } | ||||
|         } else { | ||||
|             if (ci->upper_bound_is_set()) { | ||||
|                 low_bound += ci->get_upper_bound() * a; | ||||
|                 lower_bound += ci->get_upper_bound() * a; | ||||
|             } else { | ||||
|                 return false; | ||||
|             } | ||||
|  | @ -204,20 +204,20 @@ template <typename T, typename X>    bool lp_solver<T, X>::get_minimal_row_value | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename X>    bool lp_solver<T, X>::get_maximal_row_value(std::unordered_map<unsigned, T> & row, T & low_bound) { | ||||
|     low_bound = numeric_traits<T>::zero(); | ||||
| template <typename T, typename X>    bool lp_solver<T, X>::get_maximal_row_value(std::unordered_map<unsigned, T> & row, T & lower_bound) { | ||||
|     lower_bound = numeric_traits<T>::zero(); | ||||
|     for (auto & t : row) { | ||||
|         T a = t.second; | ||||
|         column_info<T> * ci = m_map_from_var_index_to_column_info[t.first]; | ||||
|         if (a < numeric_traits<T>::zero()) { | ||||
|             if (ci->low_bound_is_set()) { | ||||
|                 low_bound += ci->get_low_bound() * a; | ||||
|             if (ci->lower_bound_is_set()) { | ||||
|                 lower_bound += ci->get_lower_bound() * a; | ||||
|             } else { | ||||
|                 return false; | ||||
|             } | ||||
|         } else { | ||||
|             if (ci->upper_bound_is_set()) { | ||||
|                 low_bound += ci->get_upper_bound() * a; | ||||
|                 lower_bound += ci->get_upper_bound() * a; | ||||
|             } else { | ||||
|                 return false; | ||||
|             } | ||||
|  | @ -242,12 +242,12 @@ template <typename T, typename X>    bool lp_solver<T, X>::row_e_is_obsolete(std | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     T low_bound; | ||||
|     bool lb = get_minimal_row_value(row, low_bound); | ||||
|     T lower_bound; | ||||
|     bool lb = get_minimal_row_value(row, lower_bound); | ||||
|     if (lb) { | ||||
|         T diff = low_bound - rs; | ||||
|         T diff = lower_bound - rs; | ||||
|         if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)){ | ||||
|             // low_bound > rs + m_settings.refactor_epsilon
 | ||||
|             // lower_bound > rs + m_settings.refactor_epsilon
 | ||||
|             m_status = lp_status::INFEASIBLE; | ||||
|             return true; | ||||
|         } | ||||
|  | @ -301,7 +301,7 @@ template <typename T, typename X>  bool lp_solver<T, X>::row_ge_is_obsolete(std: | |||
| } | ||||
| 
 | ||||
| template <typename T, typename X> bool lp_solver<T, X>::row_le_is_obsolete(std::unordered_map<unsigned, T> & row, unsigned row_index) { | ||||
|     T low_bound; | ||||
|     T lower_bound; | ||||
|     T rs = m_constraints[row_index].m_rs; | ||||
|     if (row_is_zero(row)) { | ||||
|         if (rs < zero_of_type<X>()) | ||||
|  | @ -309,10 +309,10 @@ template <typename T, typename X> bool lp_solver<T, X>::row_le_is_obsolete(std:: | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     if (get_minimal_row_value(row, low_bound)) { | ||||
|         T diff = low_bound - rs; | ||||
|     if (get_minimal_row_value(row, lower_bound)) { | ||||
|         T diff = lower_bound - rs; | ||||
|         if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)){ | ||||
|             // low_bound > rs + m_settings.refactor_tolerance
 | ||||
|             // lower_bound > rs + m_settings.refactor_tolerance
 | ||||
|             m_status = lp_status::INFEASIBLE; | ||||
|             return true; | ||||
|         } | ||||
|  | @ -504,7 +504,7 @@ template <typename T, typename X> void lp_solver<T, X>::count_slacks_and_artific | |||
|     } | ||||
| } | ||||
| 
 | ||||
| template <typename T, typename X>    T lp_solver<T, X>::low_bound_shift_for_row(unsigned i) { | ||||
| template <typename T, typename X>    T lp_solver<T, X>::lower_bound_shift_for_row(unsigned i) { | ||||
|     T ret = numeric_traits<T>::zero(); | ||||
| 
 | ||||
|     auto row = this->m_A_values.find(i); | ||||
|  | @ -522,7 +522,7 @@ template <typename T, typename X> void lp_solver<T, X>::fill_m_b() { | |||
|         lp_assert(this->m_constraints.find(this->m_core_solver_rows_to_external_rows[i]) != this->m_constraints.end()); | ||||
|         unsigned external_i = this->m_core_solver_rows_to_external_rows[i]; | ||||
|         auto & constraint = this->m_constraints[external_i]; | ||||
|         this->m_b[i] = constraint.m_rs - low_bound_shift_for_row(external_i); | ||||
|         this->m_b[i] = constraint.m_rs - lower_bound_shift_for_row(external_i); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -545,7 +545,7 @@ template <typename T, typename X> T lp_solver<T, X>::get_column_value_with_core_ | |||
|             return v; | ||||
|         } | ||||
|         if (!ci->is_flipped()) { | ||||
|             return v + ci->get_low_bound(); | ||||
|             return v + ci->get_lower_bound(); | ||||
|         } | ||||
| 
 | ||||
|         // the flipped case when there is only upper bound
 | ||||
|  | @ -23,4 +23,5 @@ namespace lp { | |||
| double numeric_traits<double>::g_zero = 0.0; | ||||
| double numeric_traits<double>::g_one = 1.0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,20 +42,25 @@ bool contains(const std::unordered_map<A, B> & map, const A& key) { | |||
| #endif | ||||
| 
 | ||||
| namespace lp { | ||||
|     inline void throw_exception(const std::string & str) { | ||||
|         throw default_exception(str); | ||||
|     } | ||||
|     typedef z3_exception exception; | ||||
| inline void throw_exception(const std::string & str) { | ||||
|     throw default_exception(str); | ||||
| } | ||||
| typedef z3_exception exception; | ||||
| 
 | ||||
| #define lp_assert(_x_) { SASSERT(_x_); } | ||||
|     inline void lp_unreachable() { lp_assert(false); } | ||||
|     template <typename X> inline X zero_of_type() { return numeric_traits<X>::zero(); } | ||||
|     template <typename X> inline X one_of_type() { return numeric_traits<X>::one(); } | ||||
|     template <typename X> inline bool is_zero(const X & v) { return numeric_traits<X>::is_zero(v); } | ||||
|     template <typename X> inline bool is_pos(const X & v) { return numeric_traits<X>::is_pos(v); } | ||||
|     template <typename X> inline bool is_neg(const X & v) { return numeric_traits<X>::is_neg(v); } | ||||
| inline void lp_unreachable() { lp_assert(false); } | ||||
| template <typename X> inline X zero_of_type() { return numeric_traits<X>::zero(); } | ||||
| template <typename X> inline X one_of_type() { return numeric_traits<X>::one(); } | ||||
| template <typename X> inline bool is_zero(const X & v) { return numeric_traits<X>::is_zero(v); } | ||||
| template <typename X> inline bool is_pos(const X & v) { return numeric_traits<X>::is_pos(v); } | ||||
| template <typename X> inline bool is_neg(const X & v) { return numeric_traits<X>::is_neg(v); } | ||||
| template <typename X> inline bool is_int(const X & v) { return numeric_traits<X>::is_int(v); } | ||||
| 
 | ||||
|     template <typename X> inline bool precise() { return numeric_traits<X>::precise(); } | ||||
| template <typename X> inline X ceil_ratio(const X & a, const X & b) { return numeric_traits<X>::ceil_ratio(a, b); } | ||||
| template <typename X> inline X floor_ratio(const X & a, const X & b) { return numeric_traits<X>::floor_ratio(a, b); } | ||||
| 
 | ||||
| 
 | ||||
| template <typename X> inline bool precise() { return numeric_traits<X>::precise(); } | ||||
| } | ||||
| namespace std { | ||||
| template<> | ||||
|  | @ -115,6 +120,12 @@ namespace lp { | |||
| template <typename X> inline bool  precise() { return numeric_traits<X>::precise();} | ||||
| template <typename X> inline X one_of_type() { return numeric_traits<X>::one(); } | ||||
| template <typename X> inline bool is_zero(const X & v) { return numeric_traits<X>::is_zero(v); } | ||||
| template <typename X> inline bool is_pos(const X & v) { return numeric_traits<X>::is_pos(v); } | ||||
| template <typename X> inline bool is_int(const X & v) { return numeric_traits<X>::is_int(v); } | ||||
| template <typename X> inline X ceil_ratio(const X & a, const X & b) { return numeric_traits<X>::ceil_ratio(a, b); } | ||||
| template <typename X> inline X floor_ratio(const X & a, const X & b) { return numeric_traits<X>::floor_ratio(v); } | ||||
| 
 | ||||
| 
 | ||||
| template <typename X> inline double  get_double(const X & v) { return numeric_traits<X>::get_double(v); } | ||||
| template <typename T> inline T zero_of_type() {return numeric_traits<T>::zero();} | ||||
| inline void throw_exception(std::string str) { throw exception(str); } | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ Revision History: | |||
| #include <string> | ||||
| #include "util/vector.h" | ||||
| #include "util/debug.h" | ||||
| #include "util/lp/lu.hpp" | ||||
| #include "util/lp/lu_def.h" | ||||
| template double lp::dot_product<double, double>(vector<double> const&, vector<double> const&); | ||||
| template lp::lu<double, double>::lu(lp::static_matrix<double, double> const&, vector<unsigned int>&, lp::lp_settings&); | ||||
| template void lp::lu<double, double>::push_matrix_to_tail(lp::tail_matrix<double, double>*); | ||||
|  | @ -19,7 +19,7 @@ Revision History: | |||
| --*/ | ||||
| #include "util/lp/lp_settings.h" | ||||
| #ifdef Z3DEBUG | ||||
| #include "util/lp/matrix.hpp" | ||||
| #include "util/lp/matrix_def.h" | ||||
| #include "util/lp/static_matrix.h" | ||||
| #include <string> | ||||
| template void lp::print_matrix<double, double>(lp::matrix<double, double> const*, std::ostream & out); | ||||
|  | @ -183,7 +183,7 @@ class mps_reader { | |||
| 
 | ||||
|     void set_boundary_for_column(unsigned col, bound * b, lp_solver<T, X> * solver){ | ||||
|         if (b == nullptr) { | ||||
|             solver->set_low_bound(col, numeric_traits<T>::zero()); | ||||
|             solver->set_lower_bound(col, numeric_traits<T>::zero()); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|  | @ -191,7 +191,7 @@ class mps_reader { | |||
|             return; | ||||
|         } | ||||
|         if (b->m_low_is_set) { | ||||
|             solver->set_low_bound(col, b->m_low); | ||||
|             solver->set_lower_bound(col, b->m_low); | ||||
|         } | ||||
|         if (b->m_upper_is_set) { | ||||
|             solver->set_upper_bound(col, b->m_upper); | ||||
|  |  | |||
|  | @ -89,7 +89,7 @@ namespace nra { | |||
|         */ | ||||
|         lbool check(lp::explanation_t& ex) { | ||||
|             SASSERT(need_check()); | ||||
|             m_nlsat = alloc(nlsat::solver, m_limit, m_params); | ||||
|             m_nlsat = alloc(nlsat::solver, m_limit, m_params, false); | ||||
|             m_lp2nl.reset(); | ||||
|             vector<nlsat::assumption, false> core; | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,10 +18,11 @@ Revision History: | |||
| 
 | ||||
| --*/ | ||||
| #pragma once | ||||
| 
 | ||||
| #define lp_for_z3 | ||||
| #include <string> | ||||
| #include <cmath> | ||||
| #include <algorithm> | ||||
| #ifdef lp_for_z3 | ||||
| #include "../rational.h" | ||||
| #include "../sstream.h" | ||||
| #include "../z3_exception.h" | ||||
|  | @ -39,7 +40,7 @@ namespace lp { | |||
| 
 | ||||
| template <typename T> | ||||
| std::string T_to_string(const T & t); // forward definition
 | ||||
| 
 | ||||
| #ifdef lp_for_z3 | ||||
| template <typename T> class numeric_traits {}; | ||||
| 
 | ||||
| template <>  class numeric_traits<unsigned> { | ||||
|  | @ -50,6 +51,7 @@ public: | |||
|     static bool is_zero(unsigned v) { return v == 0; } | ||||
|     static double get_double(unsigned const & d) { return d; } | ||||
|     static bool is_int(unsigned) {return true;} | ||||
|     static bool is_pos(unsigned) {return true;} | ||||
| }; | ||||
| 
 | ||||
| template <>  class numeric_traits<int> { | ||||
|  | @ -61,6 +63,9 @@ public: | |||
|     static double const get_double(int const & d) { return d; } | ||||
|     static bool is_int(int) {return true;} | ||||
|     static bool is_pos(int j) {return j > 0;} | ||||
|     static bool is_neg(int j) {return j < 0;} | ||||
|     static int ceil_ratio(int a, int b) { return static_cast<int>(ceil(mpq(a, b)).get_int32());} | ||||
|     static int floor_ratio(int a, int b) { return static_cast<int>(floor(mpq(a, b)).get_int32());} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -92,7 +97,15 @@ template <>  class numeric_traits<double> { | |||
|         static bool is_pos(const rational & d) {return d.is_pos();} | ||||
|         static bool is_neg(const rational & d) {return d.is_neg();} | ||||
|         static bool is_int(const rational & d) {return d.is_int();} | ||||
|         static mpq ceil_ratio(const mpq & a, const mpq & b) { | ||||
|             return ceil(a / b); | ||||
|         } | ||||
|         static mpq floor_ratio(const mpq & a, const mpq & b) { | ||||
|             return floor(a / b); | ||||
|         } | ||||
| 
 | ||||
|     }; | ||||
| #endif | ||||
| 
 | ||||
| template <typename X, typename Y> | ||||
| struct convert_struct { | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ Revision History: | |||
| --*/ | ||||
| #include <memory> | ||||
| #include "util/vector.h" | ||||
| #include "util/lp/permutation_matrix.hpp" | ||||
| #include "util/lp/permutation_matrix_def.h" | ||||
| #include "util/lp/numeric_pair.h" | ||||
| template void lp::permutation_matrix<double, double>::apply_from_right(vector<double>&); | ||||
| template void lp::permutation_matrix<double, double>::init(unsigned int); | ||||
|  | @ -17,4 +17,5 @@ Revision History: | |||
| 
 | ||||
| 
 | ||||
| --*/ | ||||
| #include "util/lp/random_updater.hpp" | ||||
| #include "util/lp/random_updater_def.h" | ||||
| 
 | ||||
|  | @ -19,7 +19,7 @@ Revision History: | |||
| --*/ | ||||
| #include <memory> | ||||
| #include "util/vector.h" | ||||
| #include "util/lp/row_eta_matrix.hpp" | ||||
| #include "util/lp/row_eta_matrix_def.h" | ||||
| #include "util/lp/lu.h" | ||||
| namespace lp { | ||||
| template void row_eta_matrix<double, double>::conjugate_by_permutation(permutation_matrix<double, double>&); | ||||
|  | @ -17,6 +17,6 @@ Revision History: | |||
| 
 | ||||
| 
 | ||||
| --*/ | ||||
| #include "util/lp/scaler.hpp" | ||||
| #include "util/lp/scaler_def.h" | ||||
| template bool lp::scaler<double, double>::scale(); | ||||
| template bool lp::scaler<lp::mpq, lp::mpq>::scale(); | ||||
|  | @ -214,6 +214,7 @@ template <typename T, typename X>    void scaler<T, X>::scale_rows() { | |||
| } | ||||
| 
 | ||||
| template <typename T, typename X>    void scaler<T, X>::scale_row(unsigned i) { | ||||
|     std::cout << "t" << "\n"; | ||||
|     T row_max = std::max(m_A.get_max_abs_in_row(i), abs(convert_struct<T, X>::convert(m_b[i]))); | ||||
|     T alpha = numeric_traits<T>::one(); | ||||
|     if (numeric_traits<T>::is_zero(row_max)) { | ||||
|  | @ -243,7 +244,7 @@ template <typename T, typename X>    void scaler<T, X>::scale_column(unsigned i) | |||
|     if (numeric_traits<T>::is_zero(column_max)){ | ||||
|         return; // the column has zeros only
 | ||||
|     } | ||||
| 
 | ||||
|     std::cout << "f"; | ||||
|     if (numeric_traits<T>::get_double(column_max) < m_scaling_minimum) { | ||||
|         do { | ||||
|             alpha *= 2; | ||||
|  | @ -25,14 +25,14 @@ struct bound_signature { | |||
|     unsigned m_i; | ||||
|     bool m_at_low; | ||||
|     bound_signature(unsigned i, bool at_low) :m_i(i), m_at_low(m_at_low) {} | ||||
|     bool at_upper_bound() const { return !m_at_low_bound;} | ||||
|     bool at_low_bound() const { return m_at_low;} | ||||
|     bool at_upper_bound() const { return !m_at_lower_bound;} | ||||
|     bool at_lower_bound() const { return m_at_low;} | ||||
| }; | ||||
| template <typename X>  | ||||
| struct signature_bound_evidence { | ||||
|     vector<bound_signature> m_evidence; | ||||
|     unsigned m_j; // found new bound
 | ||||
|     bool m_low_bound;     | ||||
|     bool m_lower_bound;     | ||||
|     X m_bound; | ||||
| }; | ||||
| } | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ Revision History: | |||
| #include "util/vector.h" | ||||
| #include "util/lp/lp_settings.h" | ||||
| #include "util/lp/lu.h" | ||||
| #include "util/lp/sparse_matrix.hpp" | ||||
| #include "util/lp/sparse_matrix_def.h" | ||||
| #include "util/lp/dense_matrix.h" | ||||
| namespace lp { | ||||
| template double sparse_matrix<double, double>::dot_product_with_row<double>(unsigned int, vector<double> const&) const; | ||||
|  | @ -19,7 +19,7 @@ Revision History: | |||
| --*/ | ||||
| #include <memory> | ||||
| #include "util/vector.h" | ||||
| #include "util/lp/square_dense_submatrix.hpp" | ||||
| #include "util/lp/square_dense_submatrix_def.h" | ||||
| template void lp::square_dense_submatrix<double, double>::init(lp::sparse_matrix<double, double>*, unsigned int); | ||||
| template lp::square_dense_submatrix<double, double>::square_dense_submatrix(lp::sparse_matrix<double, double>*, unsigned int); | ||||
| template void lp::square_dense_submatrix<double, double>::update_parent_matrix(lp::lp_settings&); | ||||
|  | @ -147,7 +147,7 @@ public: | |||
|     } | ||||
|      | ||||
|     unsigned size() const { | ||||
|         return m_map.size(); | ||||
|         return static_cast<unsigned>(m_map.size()); | ||||
|     } | ||||
| 
 | ||||
|     bool contains(const A & key) const { | ||||
|  | @ -163,6 +163,19 @@ public: | |||
|         //        d.m_deb_copy = m_map;
 | ||||
|         m_stack.push(d); | ||||
|     } | ||||
| 
 | ||||
|     void revert() { | ||||
|         if (m_stack.empty()) return; | ||||
| 
 | ||||
|         delta & d = m_stack.top(); | ||||
|         for (auto & t : d.m_new) { | ||||
|             m_map.erase(t); | ||||
|         } | ||||
|         for (auto & t: d.m_original_changed) { | ||||
|             m_map[t.first] = t.second; | ||||
|         } | ||||
|         d.clear(); | ||||
|     } | ||||
|      | ||||
|     void pop() { | ||||
|         pop(1); | ||||
|  | @ -232,7 +245,9 @@ public: | |||
|         m_map.clear(); | ||||
|     } | ||||
| 
 | ||||
| 	bool empty() const { return m_map.empty(); } | ||||
|     unsigned stack_size() const { return m_stack.size(); } | ||||
|      | ||||
|     bool empty() const { return m_map.empty(); } | ||||
| 
 | ||||
|     const std::map<A, B, _Pr, _Alloc>& operator()() const { return m_map;} | ||||
| }; | ||||
|  |  | |||
|  | @ -30,6 +30,10 @@ public: | |||
|         m_stack.push(m_value); | ||||
|     } | ||||
| 
 | ||||
|     void clear() { | ||||
|         m_stack.clear(); | ||||
|     } | ||||
|      | ||||
|     unsigned stack_size() const { | ||||
|         return static_cast<unsigned>(m_stack.size()); | ||||
|     } | ||||
|  |  | |||
|  | @ -86,10 +86,10 @@ public: | |||
|     } | ||||
| 
 | ||||
|     /*
 | ||||
|     const B & operator[](unsigned a) const { | ||||
|         lp_assert(a < m_vector.size()); | ||||
|         return m_vector[a]; | ||||
|     } | ||||
|       const B & operator[](unsigned a) const { | ||||
|       lp_assert(a < m_vector.size()); | ||||
|       return m_vector[a]; | ||||
|       } | ||||
|     */     | ||||
|     unsigned size() const { | ||||
|         return m_vector.size(); | ||||
|  | @ -106,15 +106,21 @@ public: | |||
|     } | ||||
| 
 | ||||
|     template <typename T>   | ||||
| 	void pop_tail(vector<T> & v, unsigned k) { | ||||
| 		lp_assert(v.size() >= k); | ||||
| 		v.resize(v.size() - k); | ||||
| 	} | ||||
|     void pop_tail(vector<T> & v, unsigned k) { | ||||
|         lp_assert(v.size() >= k); | ||||
|         v.resize(v.size() - k); | ||||
|     } | ||||
| 
 | ||||
|     template <typename T>   | ||||
|     void resize(vector<T> & v, unsigned new_size) { | ||||
|         v.resize(new_size); | ||||
|     } | ||||
| 
 | ||||
|     void pop_back() { | ||||
|         unsigned last = m_vector.size() - 1; | ||||
|         m_changes.push_back(std::make_pair(last, m_vector[last])); | ||||
|         m_vector.pop_back(); | ||||
|     } | ||||
|      | ||||
|     void pop(unsigned k) { | ||||
|         lp_assert(m_stack_of_vector_sizes.size() >= k); | ||||
|  | @ -132,22 +138,22 @@ public: | |||
|         resize(m_changes, first_change); | ||||
| 
 | ||||
|         /*
 | ||||
|         while (k-- > 0) { | ||||
|           while (k-- > 0) { | ||||
|              | ||||
|             if (m_stack.empty()) | ||||
|                 return; | ||||
|           if (m_stack.empty()) | ||||
|           return; | ||||
|              | ||||
|             delta & d = m_stack.back(); | ||||
|             lp_assert(m_vector.size() >= d.m_size); | ||||
|             while (m_vector.size() > d.m_size) | ||||
|                 m_vector.pop_back(); | ||||
|           delta & d = m_stack.back(); | ||||
|           lp_assert(m_vector.size() >= d.m_size); | ||||
|           while (m_vector.size() > d.m_size) | ||||
|           m_vector.pop_back(); | ||||
|              | ||||
|             for (auto & t : d.m_original_changed) { | ||||
|                 lp_assert(t.first < m_vector.size()); | ||||
|                 m_vector[t.first] = t.second; | ||||
|             } | ||||
|             //            lp_assert(d.m_deb_copy == m_vector);
 | ||||
|             m_stack.pop_back();*/ | ||||
|           for (auto & t : d.m_original_changed) { | ||||
|           lp_assert(t.first < m_vector.size()); | ||||
|           m_vector[t.first] = t.second; | ||||
|           } | ||||
|           //            lp_assert(d.m_deb_copy == m_vector);
 | ||||
|           m_stack.pop_back();*/ | ||||
|     }    | ||||
| 
 | ||||
|      | ||||
|  | @ -175,10 +181,10 @@ public: | |||
|         m_vector.resize(m_vector.size() + 1); | ||||
|     } | ||||
| 
 | ||||
| 	unsigned peek_size(unsigned k) const { | ||||
| 		lp_assert(k > 0 && k <= m_stack_of_vector_sizes.size()); | ||||
| 		return m_stack_of_vector_sizes[m_stack_of_vector_sizes.size() - k]; | ||||
| 	} | ||||
|     unsigned peek_size(unsigned k) const { | ||||
|         lp_assert(k > 0 && k <= m_stack_of_vector_sizes.size()); | ||||
|         return m_stack_of_vector_sizes[m_stack_of_vector_sizes.size() - k]; | ||||
|     } | ||||
| 
 | ||||
|     const vector<B>& operator()() const { return m_vector; } | ||||
| }; | ||||
|  |  | |||
|  | @ -17,17 +17,11 @@ Revision History: | |||
| 
 | ||||
| 
 | ||||
| --*/ | ||||
| ======= | ||||
| /*
 | ||||
|   Copyright (c) 2017 Microsoft Corporation | ||||
|   Author: Lev Nachmanson | ||||
| */ | ||||
| #include <memory> | ||||
| #include "util/vector.h" | ||||
| #include <set> | ||||
| #include <utility> | ||||
| #include "util/vector.h" | ||||
| #include "util/lp/static_matrix.hpp" | ||||
| #include "util/lp/static_matrix_def.h" | ||||
| #include "util/lp/lp_core_solver_base.h" | ||||
| #include "util/lp/lp_dual_core_solver.h" | ||||
| #include "util/lp/lp_dual_simplex.h" | ||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue