mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 16:45:31 +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