3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-14 18:06:15 +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:
Lev Nachmanson 2017-10-03 11:50:21 -07:00
parent 58ca4518e5
commit 6202b2f2e4
103 changed files with 7035 additions and 5106 deletions

View file

@ -259,9 +259,9 @@ public:
bool is_uminus(expr const * n) const { return is_app_of(n, m_afid, OP_UMINUS); } 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_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_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_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_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_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); } 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_ */ #endif /* ARITH_DECL_PLUGIN_H_ */

View file

@ -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(); 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("ast", tout << "Object " << n->m_id << " was created.\n";);
TRACE("mk_var_bug", tout << "mk_ast: " << n->m_id << "\n";); TRACE("mk_var_bug", tout << "mk_ast: " << n->m_id << "\n";);
// increment reference counters // increment reference counters

View file

@ -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); result = m_util.mk_numeral(div(v1, v2), is_int);
return BR_DONE; 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; 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) { br_status arith_rewriter::mk_mod_core(expr * arg1, expr * arg2, expr_ref & result) {
set_curr_sort(m().get_sort(arg1)); set_curr_sort(m().get_sort(arg1));
numeral v1, v2; numeral v1, v2;

View file

@ -95,7 +95,6 @@ class arith_rewriter : public poly_rewriter<arith_rewriter_core> {
expr_ref neg_monomial(expr * e) const; expr_ref neg_monomial(expr * e) const;
expr * mk_sin_value(rational const & k); expr * mk_sin_value(rational const & k);
app * mk_sqrt(rational const & k); app * mk_sqrt(rational const & k);
bool divides(expr* d, expr* n, expr_ref& quot);
public: public:
arith_rewriter(ast_manager & m, params_ref const & p = params_ref()): arith_rewriter(ast_manager & m, params_ref const & p = params_ref()):

View file

@ -19,16 +19,17 @@ Notes:
#ifndef POLYNOMIAL_H_ #ifndef POLYNOMIAL_H_
#define POLYNOMIAL_H_ #define POLYNOMIAL_H_
#include"util/mpz.h" #include "util/mpz.h"
#include"util/rational.h" #include "util/rational.h"
#include"util/obj_ref.h" #include "util/obj_ref.h"
#include"util/ref_vector.h" #include "util/ref_vector.h"
#include"util/z3_exception.h" #include "util/z3_exception.h"
#include"util/scoped_numeral.h" #include "util/scoped_numeral.h"
#include"util/scoped_numeral_vector.h" #include "util/scoped_numeral_vector.h"
#include"util/params.h" #include "util/params.h"
#include"util/mpbqi.h" #include "util/mpbqi.h"
#include"util/rlimit.h" #include "util/rlimit.h"
#include "util/lbool.h"
class small_object_allocator; class small_object_allocator;

View file

@ -21,10 +21,10 @@ Revision History:
#ifndef NLSAT_SOLVER_H_ #ifndef NLSAT_SOLVER_H_
#define NLSAT_SOLVER_H_ #define NLSAT_SOLVER_H_
#include"nlsat/nlsat_types.h" #include "nlsat/nlsat_types.h"
#include"util/params.h" #include "util/params.h"
#include"util/statistics.h" #include "util/statistics.h"
#include"util/rlimit.h" #include "util/rlimit.h"
namespace nlsat { namespace nlsat {

View file

@ -19,10 +19,10 @@ Revision History:
#ifndef NLSAT_TYPES_H_ #ifndef NLSAT_TYPES_H_
#define NLSAT_TYPES_H_ #define NLSAT_TYPES_H_
#include"math/polynomial/polynomial.h" #include "math/polynomial/polynomial.h"
#include"util/buffer.h" #include "util/buffer.h"
#include"sat/sat_types.h" #include "sat/sat_types.h"
#include"util/z3_exception.h" #include "util/z3_exception.h"
namespace algebraic_numbers { namespace algebraic_numbers {
class anum; class anum;

View file

@ -19,12 +19,12 @@ Revision History:
#ifndef SAT_TYPES_H_ #ifndef SAT_TYPES_H_
#define SAT_TYPES_H_ #define SAT_TYPES_H_
#include"util/debug.h" #include "util/debug.h"
#include"util/approx_set.h" #include "util/approx_set.h"
#include"util/lbool.h" #include "util/lbool.h"
#include"util/z3_exception.h" #include "util/z3_exception.h"
#include"util/common_msgs.h" #include "util/common_msgs.h"
#include"util/vector.h" #include "util/vector.h"
#include<iomanip> #include<iomanip>
namespace sat { namespace sat {

View file

@ -17,7 +17,7 @@ Author:
#include "util/gparams.h" #include "util/gparams.h"
#include <signal.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() { static void display_statistics() {
if (g_solver && g_solver->settings().print_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().set_message_ostream(&std::cout);
solver->settings().report_frequency = params.rep_freq(); solver->settings().report_frequency = params.rep_freq();
solver->settings().print_statistics = params.print_stats(); 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->find_maximal_solution();
*(solver->settings().get_message_ostream()) << "status is " << lp_status_to_string(solver->get_status()) << std::endl; *(solver->settings().get_message_ostream()) << "status is " << lp_status_to_string(solver->get_status()) << std::endl;

View file

@ -296,6 +296,9 @@ void parse_cmd_line_args(int argc, char ** argv) {
int STD_CALL main(int argc, char ** argv) { int STD_CALL main(int argc, char ** argv) {
try{ try{
DEBUG_CODE( for (int i = 0; i < argc; i++)
std::cout << argv[i] << " ";
std::cout << std::endl;);
unsigned return_value = 0; unsigned return_value = 0;
memory::initialize(0); memory::initialize(0);
memory::exit_when_out_of_memory(true, "ERROR: out of memory"); memory::exit_when_out_of_memory(true, "ERROR: out of memory");

View file

@ -979,7 +979,7 @@ namespace smt {
if (st.num_theories() == 2 && st.has_uf() && is_arith(st)) { if (st.num_theories() == 2 && st.has_uf() && is_arith(st)) {
if (!st.m_has_real) if (!st.m_has_real)
setup_QF_UFLIA(st); 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(); setup_QF_UFLRA();
else else
setup_unknown(); setup_unknown();

File diff suppressed because it is too large Load diff

View file

@ -11074,8 +11074,8 @@ namespace smt {
ctx.force_phase(lit); ctx.force_phase(lit);
} }
zstring aStr = gen_val_string(len, options[static_cast<int>(i) - static_cast<int>(l)]); zstring aStr = gen_val_string(len, options[i - l]);
expr * strAst; expr * strAst;
if (m_params.m_UseFastValueTesterCache) { if (m_params.m_UseFastValueTesterCache) {
if (!valueTesterCache.find(aStr, strAst)) { if (!valueTesterCache.find(aStr, strAst)) {
strAst = mk_string(aStr); strAst = mk_string(aStr);

View file

@ -211,17 +211,35 @@ tactic * mk_qflia_tactic(ast_manager & m, params_ref const & p) {
params_ref no_cut_p; params_ref no_cut_p;
no_cut_p.set_uint("arith.branch_cut_ratio", 10000000); no_cut_p.set_uint("arith.branch_cut_ratio", 10000000);
tactic * st = using_params(and_then(preamble_st, tactic * st = using_params(and_then(preamble_st,
#if 0
mk_smt_tactic()),
#else
or_else(mk_ilp_model_finder_tactic(m), or_else(mk_ilp_model_finder_tactic(m),
mk_pb_tactic(m), mk_pb_tactic(m),
and_then(fail_if_not(mk_is_quasi_pb_probe()), and_then(fail_if_not(mk_is_quasi_pb_probe()),
using_params(mk_lia2sat_tactic(m), quasi_pb_p), using_params(mk_lia2sat_tactic(m), quasi_pb_p),
mk_fail_if_undecided_tactic()), mk_fail_if_undecided_tactic()),
mk_bounded_tactic(m), mk_bounded_tactic(m),
mk_psmt_tactic(m, p))), mk_smt_tactic())),
#endif
main_p); 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); st->updt_params(p);
return st; return st;

View file

@ -35,10 +35,10 @@ Revision History:
#include "util/lp/lp_utils.h" #include "util/lp/lp_utils.h"
#include "util/lp/lp_primal_simplex.h" #include "util/lp/lp_primal_simplex.h"
#include "util/lp/mps_reader.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 "util/lp/binary_heap_priority_queue.h"
#include "test/argument_parser.h" #include "test/lp/argument_parser.h"
#include "test/test_file_reader.h" #include "test/lp/test_file_reader.h"
#include "util/lp/indexed_value.h" #include "util/lp/indexed_value.h"
#include "util/lp/lar_solver.h" #include "util/lp/lar_solver.h"
#include "util/lp/numeric_pair.h" #include "util/lp/numeric_pair.h"
@ -550,7 +550,7 @@ void test_lp_0() {
costs[5] = 0; costs[5] = 0;
costs[6] = 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; vector<double> upper_bound_values;
lp_settings settings; lp_settings settings;
simple_column_namer cn; 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; vector<double> upper_bound_values;
std::cout << "calling lp\n"; std::cout << "calling lp\n";
@ -1750,7 +1750,7 @@ void solve_rational() {
int bounds[] = {8, 6, 4, 15, 2, 10, 10, 3}; int bounds[] = {8, 6, 4, 15, 2, 10, 10, 3};
for (unsigned i = 0; i < 8; i++) { 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])); solver.set_upper_bound(i, lp::mpq(bounds[i]));
} }
@ -1883,8 +1883,7 @@ void test_replace_column() {
void setup_args_parser(argument_parser & parser) { void setup_args_parser(argument_parser & parser) {
parser.add_option_with_help_string("-dji", "test integer_domain"); parser.add_option_with_help_string("-intd", "test integer_domain");
parser.add_option_with_help_string("-cs", "test cut_solver");
parser.add_option_with_help_string("-xyz_sample", "run a small interactive scenario"); 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("--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"); 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 got to get a <= c
*/ */
std::function<bool (unsigned, bool, bool, const mpq & )> bound_is_relevant = 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; return true;
}; };
lar_solver ls; lar_solver ls;
@ -2807,7 +2806,7 @@ void test_bound_propagation_one_small_sample1() {
vector<implied_bound> ev; vector<implied_bound> ev;
ls.add_var_bound(a, LE, mpq(1)); ls.add_var_bound(a, LE, mpq(1));
ls.solve(); ls.solve();
lp_bound_propagator bp(ls); bound_propagator bp(ls);
ls.propagate_bounds_for_touched_rows(bp); ls.propagate_bounds_for_touched_rows(bp);
std::cout << " bound ev from test_bound_propagation_one_small_sample1" << std::endl; std::cout << " bound ev from test_bound_propagation_one_small_sample1" << std::endl;
for (auto & be : bp.m_ibounds) { for (auto & be : bp.m_ibounds) {
@ -2860,7 +2859,7 @@ void test_bound_propagation_one_row() {
vector<implied_bound> ev; vector<implied_bound> ev;
ls.add_var_bound(x0, LE, mpq(1)); ls.add_var_bound(x0, LE, mpq(1));
ls.solve(); ls.solve();
lp_bound_propagator bp(ls); bound_propagator bp(ls);
ls.propagate_bounds_for_touched_rows(bp); ls.propagate_bounds_for_touched_rows(bp);
} }
void test_bound_propagation_one_row_with_bounded_vars() { 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(3));
ls.add_var_bound(x0, LE, mpq(1)); ls.add_var_bound(x0, LE, mpq(1));
ls.solve(); ls.solve();
lp_bound_propagator bp(ls); bound_propagator bp(ls);
ls.propagate_bounds_for_touched_rows(bp); ls.propagate_bounds_for_touched_rows(bp);
} }
void test_bound_propagation_one_row_mixed() { void test_bound_propagation_one_row_mixed() {
@ -2890,7 +2889,7 @@ void test_bound_propagation_one_row_mixed() {
vector<implied_bound> ev; vector<implied_bound> ev;
ls.add_var_bound(x1, LE, mpq(1)); ls.add_var_bound(x1, LE, mpq(1));
ls.solve(); ls.solve();
lp_bound_propagator bp(ls); bound_propagator bp(ls);
ls.propagate_bounds_for_touched_rows(bp); ls.propagate_bounds_for_touched_rows(bp);
} }
@ -2913,7 +2912,7 @@ void test_bound_propagation_two_rows() {
vector<implied_bound> ev; vector<implied_bound> ev;
ls.add_var_bound(y, LE, mpq(1)); ls.add_var_bound(y, LE, mpq(1));
ls.solve(); ls.solve();
lp_bound_propagator bp(ls); bound_propagator bp(ls);
ls.propagate_bounds_for_touched_rows(bp); ls.propagate_bounds_for_touched_rows(bp);
} }
@ -2933,7 +2932,7 @@ void test_total_case_u() {
vector<implied_bound> ev; vector<implied_bound> ev;
ls.add_var_bound(z, GE, zero_of_type<mpq>()); ls.add_var_bound(z, GE, zero_of_type<mpq>());
ls.solve(); ls.solve();
lp_bound_propagator bp(ls); bound_propagator bp(ls);
ls.propagate_bounds_for_touched_rows(bp); ls.propagate_bounds_for_touched_rows(bp);
} }
bool contains_j_kind(unsigned j, lconstraint_kind kind, const mpq & rs, const vector<implied_bound> & ev) { 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; vector<implied_bound> ev;
ls.add_var_bound(z, LE, zero_of_type<mpq>()); ls.add_var_bound(z, LE, zero_of_type<mpq>());
ls.solve(); ls.solve();
lp_bound_propagator bp(ls); bound_propagator bp(ls);
ls.propagate_bounds_for_touched_rows(bp); ls.propagate_bounds_for_touched_rows(bp);
lp_assert(ev.size() == 4); lp_assert(ev.size() == 4);
lp_assert(contains_j_kind(x, GE, - one_of_type<mpq>(), ev)); 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) { void test_integer_domain_intersection(integer_domain<int> & d) {
int x, y; bool neg_inf, pos_inf; // int x, y; bool neg_inf, pos_inf;
get_random_interval(neg_inf, pos_inf, x, y); // get_random_interval(neg_inf, pos_inf, x, y);
if (neg_inf) { // if (neg_inf) {
if (!pos_inf) { // if (!pos_inf) {
d.intersect_with_upper_bound(y); // d.intersect_with_upper_bound(y);
} // }
} // }
else if (pos_inf) // else if (pos_inf)
d.intersect_with_lower_bound(x); // d.intersect_with_lower_bound(x);
else // else
d.intersect_with_interval(x, y); // d.intersect_with_interval(x, y);
} }
void test_integer_domain_union(integer_domain<int> & d) { 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() { void test_integer_domain() {
integer_domain<int> d; std::cout << "test_integer_domain\n";
vector<integer_domain<int>> stack; unsigned e0 = 0;
for (int i = 0; i < 10000; i++) { unsigned e1 = 1;
test_integer_domain_randomly(d); unsigned e2 = 2;
stack.push_back(d); unsigned e3 = 3; // these are explanations
d.push(); unsigned e4 = 4;
if (i > 0 && i%100 == 0) { unsigned e5 = 5;
if (stack.size() == 0) continue; integer_domain<unsigned> d;
unsigned k = my_random() % stack.size(); unsigned l0 = 0, l1 = 1, l2 = 3;
if (k == 0) unsigned u0 = 10, u1 = 9, u2 = 8;
k = 1; d.push();
d.pop(k); d.intersect_with_lower_bound(l0, e0);
d.restore_domain(); unsigned b;
for (unsigned j = 0; j + 1 < k; j++) { unsigned e;
stack.pop_back(); bool r = d.get_lower_bound_with_expl(b, e);
} lp_assert(r && b == l0 && e == e0);
std::cout<<"comparing i = " << i << std::endl; d.push();
lp_assert(d == *stack.rbegin()); d.intersect_with_upper_bound(u0, e1);
stack.pop_back(); r = d.get_upper_bound_with_expl(b, e);
} lp_assert(r && b == u0 && e == e1);
//d.print(std::cout); 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; // std::cout << "resolve constraint ";
auto ineq = cs.m_ineqs[ineq_index]; // cs.print_polynomial(std::cout, i);
cs.add_lower_bound_for_user_var(x, 1); // std::cout << " for " << cs.get_column_name(j) << " by using poly ";
cs.add_lower_bound_for_user_var(y, 1); // cs.print_polynomial(std::cout, ti);
bool has_lower = cs.lower(ineq.m_poly, l); // std::cout << std::endl;
if (has_lower) { // bool j_coeff_is_one = ti.coeff(j) == 1;
std::cout << "lower = " << l << std::endl; // cut_solver::polynomial result;
} else { // cs.resolve(i, j, j_coeff_is_one, ti);
std::cout << "no lower" << std::endl; // std::cout << "resolve result is ";
} // cs.print_polynomial(std::cout, i);
cs.add_upper_bound_for_user_var(y, 1); // std::cout << std::endl;
has_lower = cs.lower(ineq.m_poly, l);
if (has_lower) {
std::cout << "lower = " << l << std::endl;
} else {
std::cout << "no lower" << 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) { void test_lp_local(int argn, char**argv) {
// initialize_util_module(); // initialize_util_module();
@ -3230,14 +3271,11 @@ void test_lp_local(int argn, char**argv) {
args_parser.print(); args_parser.print();
if (args_parser.option_is_used("-dji")) { if (args_parser.option_is_used("-intd")) {
test_integer_domain(); test_integer_domain();
return finalize(0); return finalize(0);
} }
if (args_parser.option_is_used("-cs")) {
test_cut_solver();
return finalize(0);
}
if (args_parser.option_is_used("--test_mpq")) { if (args_parser.option_is_used("--test_mpq")) {
test_rationals(); test_rationals();
return finalize(0); return finalize(0);

View file

@ -1,35 +1,35 @@
z3_add_component(lp z3_add_component(lp
SOURCES SOURCES
lp_utils.cpp lp_utils.cpp
binary_heap_priority_queue_instances.cpp binary_heap_priority_queue.cpp
binary_heap_upair_queue_instances.cpp binary_heap_upair_queue.cpp
bound_propagator.cpp bound_propagator.cpp
cut_solver.cpp cut_solver.cpp
core_solver_pretty_printer_instances.cpp core_solver_pretty_printer.cpp
dense_matrix_instances.cpp dense_matrix.cpp
eta_matrix_instances.cpp eta_matrix.cpp
indexed_vector_instances.cpp indexed_vector.cpp
int_solver.cpp int_solver.cpp
lar_solver_instances.cpp lar_solver.cpp
lar_core_solver_instances.cpp lar_core_solver.cpp
lp_core_solver_base_instances.cpp lp_core_solver_base.cpp
lp_dual_core_solver_instances.cpp lp_dual_core_solver.cpp
lp_dual_simplex_instances.cpp lp_dual_simplex.cpp
lp_primal_core_solver_instances.cpp lp_primal_core_solver.cpp
lp_primal_simplex_instances.cpp lp_primal_simplex.cpp
lp_settings_instances.cpp lp_settings.cpp
lp_solver_instances.cpp lp_solver.cpp
lu_instances.cpp lu.cpp
matrix_instances.cpp matrix.cpp
nra_solver.cpp nra_solver.cpp
permutation_matrix_instances.cpp permutation_matrix.cpp
quick_xplain.cpp quick_xplain.cpp
row_eta_matrix_instances.cpp row_eta_matrix.cpp
scaler_instances.cpp scaler.cpp
sparse_matrix_instances.cpp sparse_matrix.cpp
square_dense_submatrix_instances.cpp square_dense_submatrix.cpp
static_matrix_instances.cpp static_matrix.cpp
random_updater_instances.cpp random_updater.cpp
COMPONENT_DEPENDENCIES COMPONENT_DEPENDENCIES
util util
polynomial polynomial

View file

@ -18,7 +18,7 @@ Revision History:
--*/ --*/
#include "util/lp/numeric_pair.h" #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 { namespace lp {
template binary_heap_priority_queue<int>::binary_heap_priority_queue(unsigned int); template binary_heap_priority_queue<int>::binary_heap_priority_queue(unsigned int);
template unsigned binary_heap_priority_queue<int>::dequeue(); template unsigned binary_heap_priority_queue<int>::dequeue();

View file

@ -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 { namespace lp {
template binary_heap_upair_queue<int>::binary_heap_upair_queue(unsigned int); 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); template binary_heap_upair_queue<unsigned int>::binary_heap_upair_queue(unsigned int);

View file

@ -20,10 +20,9 @@ Revision History:
#pragma once #pragma once
#include "util/vector.h" #include "util/vector.h"
#include "util/lp/linear_combination_iterator.h" #include "util/lp/linear_combination_iterator.h"
#include "util/lp/implied_bound.h" #include "implied_bound.h"
#include "util/lp/test_bound_analyzer.h" #include "test_bound_analyzer.h"
#include <functional> #include "util/lp/bound_propagator.h"
#include "util/lp/lp_bound_propagator.h"
// We have an equality : sum by j of row[j]*x[j] = rs // 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 // 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. // 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 { namespace lp {
class bound_analyzer_on_row { class bound_analyzer_on_row {
linear_combination_iterator<mpq> & m_it; linear_combination_iterator<mpq> & m_it;
lp_bound_propagator & m_bp; bound_propagator & m_bp;
unsigned m_row_or_term_index; unsigned m_row_or_term_index;
int m_column_of_u; // index of an unlimited from above monoid 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 int m_column_of_l; // index of an unlimited from below monoid
impq m_rs; impq m_rs;
public : public :
// constructor // constructor
bound_analyzer_on_row( bound_analyzer_on_row(
linear_combination_iterator<mpq> &it, linear_combination_iterator<mpq> &it,
const numeric_pair<mpq>& rs, const numeric_pair<mpq>& rs,
unsigned row_or_term_index, unsigned row_or_term_index,
lp_bound_propagator & bp bound_propagator & bp
) )
: :
m_it(it), m_it(it),
@ -60,7 +59,7 @@ public :
unsigned j; unsigned j;
void analyze() { void analyze() {
mpq a; unsigned j; mpq a; unsigned j;
while (((m_column_of_l != -2) || (m_column_of_u != -2)) && m_it.next(a, 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); analyze_bound_on_var_on_coeff(j, a);
@ -76,33 +75,33 @@ public :
limit_all_monoids_from_above(); limit_all_monoids_from_above();
} }
bool bound_is_available(unsigned j, bool low_bound) { bool bound_is_available(unsigned j, bool lower_bound) {
return (low_bound && low_bound_is_available(j)) || return (lower_bound && lower_bound_is_available(j)) ||
(!low_bound && upper_bound_is_available(j)); (!lower_bound && upper_bound_is_available(j));
} }
bool upper_bound_is_available(unsigned j) const { bool upper_bound_is_available(unsigned j) const {
switch (m_bp.get_column_type(j)) switch (m_bp.get_column_type(j))
{ {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: case column_type::boxed:
case column_type::upper_bound: case column_type::upper_bound:
return true; return true;
default: default:
return false; 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)) switch (m_bp.get_column_type(j))
{ {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: case column_type::boxed:
case column_type::low_bound: case column_type::lower_bound:
return true; return true;
default: default:
return false; return false;
} }
} }
const impq & ub(unsigned j) const { const impq & ub(unsigned j) const {
@ -110,8 +109,8 @@ public :
return m_bp.get_upper_bound(j); return m_bp.get_upper_bound(j);
} }
const impq & lb(unsigned j) const { const impq & lb(unsigned j) const {
lp_assert(low_bound_is_available(j)); lp_assert(lower_bound_is_available(j));
return m_bp.get_low_bound(j); return m_bp.get_lower_bound(j);
} }
@ -151,7 +150,7 @@ public :
strict = !is_zero(ub(j).y); strict = !is_zero(ub(j).y);
return a * ub(j).x; return a * ub(j).x;
} }
strict = !is_zero(lb(j).y); strict = !is_zero(lb(j).y);
return a * lb(j).x; return a * lb(j).x;
} }
@ -160,10 +159,10 @@ public :
if (is_neg(a)) { if (is_neg(a)) {
return a * ub(j).x; return a * ub(j).x;
} }
return a * lb(j).x; return a * lb(j).x;
} }
void limit_all_monoids_from_above() { void limit_all_monoids_from_above() {
int strict = 0; int strict = 0;
@ -209,7 +208,7 @@ public :
bool str; bool str;
bool a_is_pos = is_pos(a); bool a_is_pos = is_pos(a);
mpq bound = total / a + monoid_max_no_mult(a_is_pos, j, str); 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) { if (a_is_pos) {
limit_j(j, bound, true, true, astrict); limit_j(j, bound, true, true, astrict);
} }
@ -219,7 +218,7 @@ public :
} }
} }
void limit_monoid_u_from_below() { void limit_monoid_u_from_below() {
// we are going to limit from below the monoid m_column_of_u, // we are going to limit from below the monoid m_column_of_u,
// every other monoid is impossible to limit from below // every other monoid is impossible to limit from below
@ -240,7 +239,7 @@ public :
} }
bound /= u_coeff; bound /= u_coeff;
if (numeric_traits<impq>::is_pos(u_coeff)) { if (numeric_traits<impq>::is_pos(u_coeff)) {
limit_j(m_column_of_u, bound, true, true, strict); limit_j(m_column_of_u, bound, true, true, strict);
} else { } else {
@ -275,51 +274,51 @@ public :
limit_j(m_column_of_l, bound, false, true, strict); limit_j(m_column_of_l, bound, false, true, strict);
} }
} }
// // it is the coefficent before the bounded column // // it is the coefficent before the bounded column
// void provide_evidence(bool coeff_is_pos) { // void provide_evidence(bool coeff_is_pos) {
// /* // /*
// auto & be = m_ibounds.back(); // auto & be = m_ibounds.back();
// bool low_bound = be.m_low_bound; // bool lower_bound = be.m_lower_bound;
// if (!coeff_is_pos) // if (!coeff_is_pos)
// low_bound = !low_bound; // lower_bound = !lower_bound;
// auto it = m_it.clone(); // auto it = m_it.clone();
// mpq a; unsigned j; // mpq a; unsigned j;
// while (it->next(a, j)) { // while (it->next(a, j)) {
// if (be.m_j == j) continue; // 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>:: // 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; // delete it;
// */ // */
// } // }
void limit_j(unsigned j, const mpq& u, bool coeff_before_j_is_pos, bool is_low_bound, bool 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_low_bound, coeff_before_j_is_pos, m_row_or_term_index, 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) { void advance_u(unsigned j) {
if (m_column_of_u == -1) if (m_column_of_u == -1)
m_column_of_u = j; m_column_of_u = j;
else else
m_column_of_u = -2; m_column_of_u = -2;
} }
void advance_l(unsigned j) { void advance_l(unsigned j) {
if (m_column_of_l == -1) if (m_column_of_l == -1)
m_column_of_l = j; m_column_of_l = j;
else else
m_column_of_l = -2; m_column_of_l = -2;
} }
void analyze_bound_on_var_on_coeff(int j, const mpq &a) { void analyze_bound_on_var_on_coeff(int j, const mpq &a) {
switch (m_bp.get_column_type(j)) { switch (m_bp.get_column_type(j)) {
case column_type::low_bound: case column_type::lower_bound:
if (numeric_traits<mpq>::is_pos(a)) if (numeric_traits<mpq>::is_pos(a))
advance_u(j); advance_u(j);
else else
advance_l(j); advance_l(j);
break; break;
case column_type::upper_bound: case column_type::upper_bound:
@ -340,7 +339,7 @@ public :
static void analyze_row(linear_combination_iterator<mpq> &it, static void analyze_row(linear_combination_iterator<mpq> &it,
const numeric_pair<mpq>& rs, const numeric_pair<mpq>& rs,
unsigned row_or_term_index, unsigned row_or_term_index,
lp_bound_propagator & bp bound_propagator & bp
) { ) {
bound_analyzer_on_row a(it, rs, row_or_term_index, bp); bound_analyzer_on_row a(it, rs, row_or_term_index, bp);
a.analyze(); a.analyze();

View file

@ -9,8 +9,8 @@ bound_propagator::bound_propagator(lar_solver & ls):
column_type bound_propagator::get_column_type(unsigned j) const { column_type bound_propagator::get_column_type(unsigned j) const {
return m_lar_solver.m_mpq_lar_core_solver.m_column_types()[j]; return m_lar_solver.m_mpq_lar_core_solver.m_column_types()[j];
} }
const impq & bound_propagator::get_low_bound(unsigned j) const { const impq & bound_propagator::get_lower_bound(unsigned j) const {
return m_lar_solver.m_mpq_lar_core_solver.m_r_low_bounds()[j]; return m_lar_solver.m_mpq_lar_core_solver.m_r_lower_bounds()[j];
} }
const impq & bound_propagator::get_upper_bound(unsigned j) const { const impq & bound_propagator::get_upper_bound(unsigned j) const {
return m_lar_solver.m_mpq_lar_core_solver.m_r_upper_bounds()[j]; 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; return;
unsigned k; // index to ibounds unsigned k; // index to ibounds
if (is_low) { 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]; auto & found_bound = m_ibounds[k];
if (v > found_bound.m_bound || (v == found_bound.m_bound && found_bound.m_strict == false && strict)) { 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); 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);); TRACE("try_add_bound", m_lar_solver.print_implied_bound(found_bound, tout););
} }
} else { } 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)); 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);); TRACE("try_add_bound", m_lar_solver.print_implied_bound(m_ibounds.back(), tout););
} }

View 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"; }
};
}

View file

@ -30,11 +30,11 @@ inline bool is_valid(unsigned j) { return static_cast<int>(j) >= 0;}
template <typename T> template <typename T>
class column_info { class column_info {
std::string m_name; std::string m_name;
bool m_low_bound_is_set; bool m_lower_bound_is_set;
bool m_low_bound_is_strict; bool m_lower_bound_is_strict;
bool m_upper_bound_is_set; bool m_upper_bound_is_set;
bool m_upper_bound_is_strict; bool m_upper_bound_is_strict;
T m_low_bound; T m_lower_bound;
T m_upper_bound; T m_upper_bound;
T m_fixed_value; T m_fixed_value;
bool m_is_fixed; bool m_is_fixed;
@ -43,11 +43,11 @@ class column_info {
public: public:
bool operator==(const column_info & c) const { bool operator==(const column_info & c) const {
return m_name == c.m_name && return m_name == c.m_name &&
m_low_bound_is_set == c.m_low_bound_is_set && m_lower_bound_is_set == c.m_lower_bound_is_set &&
m_low_bound_is_strict == c.m_low_bound_is_strict && 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_set == c.m_upper_bound_is_set&&
m_upper_bound_is_strict == c.m_upper_bound_is_strict&& 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_upper_bound_is_set || m_upper_bound == c.m_upper_bound) &&
m_cost == c.m_cost && m_cost == c.m_cost &&
m_is_fixed == c.m_is_fixed && m_is_fixed == c.m_is_fixed &&
@ -60,8 +60,8 @@ public:
} }
// the default constructor // the default constructor
column_info(): column_info():
m_low_bound_is_set(false), m_lower_bound_is_set(false),
m_low_bound_is_strict(false), m_lower_bound_is_strict(false),
m_upper_bound_is_set (false), m_upper_bound_is_set (false),
m_upper_bound_is_strict (false), m_upper_bound_is_strict (false),
m_is_fixed(false), m_is_fixed(false),
@ -70,8 +70,8 @@ public:
{} {}
column_info(unsigned column_index) : column_info(unsigned column_index) :
m_low_bound_is_set(false), m_lower_bound_is_set(false),
m_low_bound_is_strict(false), m_lower_bound_is_strict(false),
m_upper_bound_is_set (false), m_upper_bound_is_set (false),
m_upper_bound_is_strict (false), m_upper_bound_is_strict (false),
m_is_fixed(false), m_is_fixed(false),
@ -81,11 +81,11 @@ public:
column_info(const column_info & ci) { column_info(const column_info & ci) {
m_name = ci.m_name; m_name = ci.m_name;
m_low_bound_is_set = ci.m_low_bound_is_set; m_lower_bound_is_set = ci.m_lower_bound_is_set;
m_low_bound_is_strict = ci.m_low_bound_is_strict; 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_set = ci.m_upper_bound_is_set;
m_upper_bound_is_strict = ci.m_upper_bound_is_strict; 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_upper_bound = ci.m_upper_bound;
m_cost = ci.m_cost; m_cost = ci.m_cost;
m_fixed_value = ci.m_fixed_value; m_fixed_value = ci.m_fixed_value;
@ -98,7 +98,7 @@ public:
} }
column_type get_column_type() const { 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 { column_type get_column_type_no_flipping() const {
@ -106,25 +106,25 @@ public:
return column_type::fixed; return column_type::fixed;
} }
if (m_low_bound_is_set) { if (m_lower_bound_is_set) {
return m_upper_bound_is_set? column_type::boxed: column_type::low_bound; return m_upper_bound_is_set? column_type::boxed: column_type::lower_bound;
} }
// we are flipping the bounds! // we are flipping the bounds!
return m_upper_bound_is_set? column_type::upper_bound return m_upper_bound_is_set? column_type::upper_bound
: column_type::free_column; : column_type::free_column;
} }
T get_low_bound() const { T get_lower_bound() const {
lp_assert(m_low_bound_is_set); lp_assert(m_lower_bound_is_set);
return m_low_bound; return m_lower_bound;
} }
T get_upper_bound() const { T get_upper_bound() const {
lp_assert(m_upper_bound_is_set); lp_assert(m_upper_bound_is_set);
return m_upper_bound; return m_upper_bound;
} }
bool low_bound_is_set() const { bool lower_bound_is_set() const {
return m_low_bound_is_set; return m_lower_bound_is_set;
} }
bool upper_bound_is_set() const { bool upper_bound_is_set() const {
@ -138,23 +138,23 @@ public:
if (is_flipped()){ if (is_flipped()){
return m_upper_bound; 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() { 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() { bool adjusted_lower_bound_is_set() {
return !is_flipped()? low_bound_is_set(): upper_bound_is_set(); return !is_flipped()? lower_bound_is_set(): upper_bound_is_set();
} }
bool adjusted_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() { T get_adjusted_upper_bound() {
return get_upper_bound() - get_low_bound(); return get_upper_bound() - get_lower_bound();
} }
bool is_fixed() const { bool is_fixed() const {
@ -162,7 +162,7 @@ public:
} }
bool is_free() { 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) { void set_fixed_value(T v) {
@ -191,9 +191,9 @@ public:
return m_name; return m_name;
} }
void set_low_bound(T const & l) { void set_lower_bound(T const & l) {
m_low_bound = l; m_lower_bound = l;
m_low_bound_is_set = true; m_lower_bound_is_set = true;
} }
void set_upper_bound(T const & l) { void set_upper_bound(T const & l) {
@ -201,8 +201,8 @@ public:
m_upper_bound_is_set = true; m_upper_bound_is_set = true;
} }
void unset_low_bound() { void unset_lower_bound() {
m_low_bound_is_set = false; m_lower_bound_is_set = false;
} }
void unset_upper_bound() { void unset_upper_bound() {
@ -213,8 +213,8 @@ public:
m_is_fixed = false; m_is_fixed = false;
} }
bool low_bound_holds(T v) { bool lower_bound_holds(T v) {
return !low_bound_is_set() || v >= m_low_bound -T(0.0000001); return !lower_bound_is_set() || v >= m_lower_bound -T(0.0000001);
} }
bool upper_bound_holds(T v) { bool upper_bound_holds(T v) {
@ -222,36 +222,36 @@ public:
} }
bool bounds_hold(T v) { 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) { 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) { bool adjusted_lower_bound_holds(T v) {
return !adjusted_low_bound_is_set() || v >= -T(0.0000001); return !adjusted_lower_bound_is_set() || v >= -T(0.0000001);
} }
bool adjusted_upper_bound_holds(T v) { bool adjusted_upper_bound_holds(T v) {
return !adjusted_upper_bound_is_set() || v <= get_adjusted_upper_bound() + T(0.000001); return !adjusted_upper_bound_is_set() || v <= get_adjusted_upper_bound() + T(0.000001);
} }
bool is_infeasible() { bool is_infeasible() {
if ((!upper_bound_is_set()) || (!low_bound_is_set())) if ((!upper_bound_is_set()) || (!lower_bound_is_set()))
return false; return false;
// ok, both bounds are set // 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) 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 // 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 { bool lower_bound_is_strict() const {
return m_low_bound_is_strict; return m_lower_bound_is_strict;
} }
void set_low_bound_strict(bool val) { void set_lower_bound_strict(bool val) {
m_low_bound_is_strict = val; m_lower_bound_is_strict = val;
} }
bool upper_bound_is_strict() const { bool upper_bound_is_strict() const {

View file

@ -68,7 +68,31 @@ public:
out << "v" << it.second; 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> template <typename T>
void print_linear_combination_of_column_indices(const vector<std::pair<T, unsigned>> & coeffs, std::ostream & out) const { void print_linear_combination_of_column_indices(const vector<std::pair<T, unsigned>> & coeffs, std::ostream & out) const {
bool first = true; bool first = true;

View file

@ -22,8 +22,8 @@ Revision History:
namespace lp { namespace lp {
template <typename V> template <typename V>
struct conversion_helper { struct conversion_helper {
static V get_low_bound(const column_info<mpq> & ci) { static V get_lower_bound(const column_info<mpq> & ci) {
return V(ci.get_low_bound(), ci.low_bound_is_strict()? 1 : 0); return V(ci.get_lower_bound(), ci.lower_bound_is_strict()? 1 : 0);
} }
static V get_upper_bound(const column_info<mpq> & ci) { static V get_upper_bound(const column_info<mpq> & ci) {
@ -37,20 +37,20 @@ struct conversion_helper <double> {
if (!ci.upper_bound_is_strict()) if (!ci.upper_bound_is_strict())
return ci.get_upper_bound().get_double(); return ci.get_upper_bound().get_double();
double eps = 0.00001; double eps = 0.00001;
if (!ci.low_bound_is_set()) if (!ci.lower_bound_is_set())
return ci.get_upper_bound().get_double() - eps; 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; return ci.get_upper_bound().get_double() - eps;
} }
static double get_low_bound(const column_info<mpq> & ci) { static double get_lower_bound(const column_info<mpq> & ci) {
if (!ci.low_bound_is_strict()) if (!ci.lower_bound_is_strict())
return ci.get_low_bound().get_double(); return ci.get_lower_bound().get_double();
double eps = 0.00001; double eps = 0.00001;
if (!ci.upper_bound_is_set()) if (!ci.upper_bound_is_set())
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_low_bound()).get_double() / 1000, eps); eps = std::min((ci.get_upper_bound() - ci.get_lower_bound()).get_double() / 1000, eps);
return ci.get_low_bound().get_double() + eps; return ci.get_lower_bound().get_double() + eps;
} }
}; };

View file

@ -18,7 +18,7 @@ Revision History:
--*/ --*/
#include "util/lp/numeric_pair.h" #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 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 void lp::core_solver_pretty_printer<double, double>::print();
template lp::core_solver_pretty_printer<double, double>::~core_solver_pretty_printer(); template lp::core_solver_pretty_printer<double, double>::~core_solver_pretty_printer();

View file

@ -48,7 +48,7 @@ class core_solver_pretty_printer {
std::string m_cost_title; std::string m_cost_title;
std::string m_basis_heading_title; std::string m_basis_heading_title;
std::string m_x_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_upp_bounds_title;
std::string m_exact_norm_title; std::string m_exact_norm_title;
std::string m_approx_norm_title; std::string m_approx_norm_title;
@ -75,7 +75,7 @@ public:
void init_column_widths(); 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_upper_bound(unsigned column, unsigned & w);
void adjust_width_with_bounds(unsigned column, unsigned & w); void adjust_width_with_bounds(unsigned column, unsigned & w);
@ -97,7 +97,7 @@ public:
void print_x(); 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); std::string get_upp_bound_string(unsigned j);

View file

@ -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_rs(ncols(), zero_of_type<X>()),
m_w_buff(core_solver.m_w), m_w_buff(core_solver.m_w),
m_ed_buff(core_solver.m_ed) { m_ed_buff(core_solver.m_ed) {
m_low_bounds_title = "low"; m_lower_bounds_title = "low";
m_upp_bounds_title = "upp"; m_upp_bounds_title = "upp";
m_exact_norm_title = "exact cn"; m_exact_norm_title = "exact cn";
m_approx_norm_title = "approx 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) { 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.low_bounds_are_set()) return; if (!m_core_solver.lower_bounds_are_set()) return;
w = std::max(w, (unsigned)T_to_string(m_core_solver.low_bound_value(column)).size()); 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) { 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()); 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)) { switch (m_core_solver.get_column_type(column)) {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: 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); adjust_width_with_upper_bound(column, w);
break; break;
case column_type::low_bound: case column_type::lower_bound:
adjust_width_with_low_bound(column, w); adjust_width_with_lower_bound(column, w);
break; break;
case column_type::upper_bound: case column_type::upper_bound:
adjust_width_with_upper_bound(column, w); 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; 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)){ switch (m_core_solver.get_column_type(j)){
case column_type::boxed: case column_type::boxed:
case column_type::low_bound: case column_type::lower_bound:
case column_type::fixed: case column_type::fixed:
if (m_core_solver.low_bounds_are_set()) if (m_core_solver.lower_bounds_are_set())
return T_to_string(m_core_solver.low_bound_value(j)); return T_to_string(m_core_solver.lower_bound_value(j));
else else
return std::string("0"); return std::string("0");
break; break;
@ -268,12 +268,12 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::print_l
if (ncols() == 0) { if (ncols() == 0) {
return; return;
} }
int blanks = m_title_width + 1 - static_cast<unsigned>(m_low_bounds_title.size()); int blanks = m_title_width + 1 - static_cast<unsigned>(m_lower_bounds_title.size());
m_out << m_low_bounds_title; m_out << m_lower_bounds_title;
print_blanks(blanks, m_out); print_blanks(blanks, m_out);
for (unsigned i = 0; i < ncols(); i++) { 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()); int blanks = m_column_widths[i] - static_cast<unsigned>(s.size());
print_blanks(blanks, m_out); print_blanks(blanks, m_out);
m_out << s << " "; // the column interval m_out << s << " "; // the column interval

View file

@ -4,5 +4,21 @@
*/ */
#include "util/lp/cut_solver.h" #include "util/lp/cut_solver.h"
namespace lp { 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

View file

@ -18,7 +18,7 @@ Revision History:
--*/ --*/
#include "util/lp/lp_settings.h" #include "util/lp/lp_settings.h"
#include "util/lp/dense_matrix.hpp" #include "util/lp/dense_matrix_def.h"
#ifdef Z3DEBUG #ifdef Z3DEBUG
#include "util/vector.h" #include "util/vector.h"
template lp::dense_matrix<double, double> lp::operator*<double, double>(lp::matrix<double, double>&, lp::matrix<double, double>&); template lp::dense_matrix<double, double> lp::operator*<double, double>(lp::matrix<double, double>&, lp::matrix<double, double>&);

View file

@ -100,7 +100,7 @@ public:
void swap_rows(unsigned a, unsigned b); void swap_rows(unsigned a, unsigned b);
void multiply_row_by_constant(unsigned row, T & t); void multiply_row_by_constant(unsigned row, T & t);
}; };
template <typename T, typename X> template <typename T, typename X>
dense_matrix<T, X> operator* (matrix<T, X> & a, matrix<T, X> & b); dense_matrix<T, X> operator* (matrix<T, X> & a, matrix<T, X> & b);

View file

@ -20,8 +20,8 @@ Revision History:
#include <memory> #include <memory>
#include "util/vector.h" #include "util/vector.h"
#include "util/lp/numeric_pair.h" #include "util/lp/numeric_pair.h"
#include "util/lp/eta_matrix.hpp" #include "util/lp/eta_matrix_def.h"
#ifdef LEAN_DEBUG #ifdef Z3DEBUG
template double lp::eta_matrix<double, double>::get_elem(unsigned int, unsigned int) const; 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::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; template lp::mpq lp::eta_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::get_elem(unsigned int, unsigned int) const;

View file

@ -24,31 +24,31 @@ namespace lp {
struct implied_bound { struct implied_bound {
mpq m_bound; mpq m_bound;
unsigned m_j; // the column for which the bound has been found 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; bool m_coeff_before_j_is_pos;
unsigned m_row_or_term_index; unsigned m_row_or_term_index;
bool m_strict; bool m_strict;
lconstraint_kind kind() const { 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) if (m_strict)
k = static_cast<lconstraint_kind>(k / 2); k = static_cast<lconstraint_kind>(k / 2);
return k; return k;
} }
bool operator==(const implied_bound & o) const { 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_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; m_row_or_term_index == o.m_row_or_term_index && m_strict == o.m_strict;
} }
implied_bound(){} implied_bound(){}
implied_bound(const mpq & a, implied_bound(const mpq & a,
unsigned j, unsigned j,
bool low_bound, bool lower_bound,
bool coeff_before_j_is_pos, bool coeff_before_j_is_pos,
unsigned row_or_term_index, unsigned row_or_term_index,
bool strict): bool strict):
m_bound(a), m_bound(a),
m_j(j), 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_coeff_before_j_is_pos(coeff_before_j_is_pos),
m_row_or_term_index(row_or_term_index), m_row_or_term_index(row_or_term_index),
m_strict(strict) { m_strict(strict) {

View file

@ -18,7 +18,7 @@ Revision History:
--*/ --*/
#include "util/vector.h" #include "util/vector.h"
#include "util/lp/indexed_vector.hpp" #include "util/lp/indexed_vector_def.h"
namespace lp { namespace lp {
template void indexed_vector<double>::clear(); template void indexed_vector<double>::clear();
template void indexed_vector<double>::clear_all(); template void indexed_vector<double>::clear_all();

View file

@ -90,15 +90,6 @@ public:
} }
void set_value(const T& value, unsigned index); 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();
void clear_all(); void clear_all();

View file

@ -6,6 +6,7 @@
#include "util/lp/int_solver.h" #include "util/lp/int_solver.h"
#include "util/lp/lar_solver.h" #include "util/lp/lar_solver.h"
#include "util/lp/cut_solver.h" #include "util/lp/cut_solver.h"
#include "util/lp/lp_utils.h"
#include <utility> #include <utility>
namespace lp { namespace lp {
@ -78,7 +79,7 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() {
lp_assert(!is_fixed(j)); lp_assert(!is_fixed(j));
if (!is_boxed(j)) if (!is_boxed(j))
continue; 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) if (new_range > small_range_thresold)
continue; continue;
if (result == -1) { 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 = a / f_0;
new_a.neg(); 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; // 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 { else {
lp_assert(at_upper(x_j)); 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); return m_lar_solver->get_column_upper_bound_witness(j);
} }
constraint_index int_solver::column_low_bound_constraint(unsigned j) const { constraint_index int_solver::column_lower_bound_constraint(unsigned j) const {
return m_lar_solver->get_column_low_bound_witness(j); 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 { else {
new_a = (1 - f_j) / f_0; new_a = (1 - f_j) / f_0;
} }
k.addmul(new_a, low_bound(x_j).x); k.addmul(new_a, lower_bound(x_j).x);
expl.push_justification(column_low_bound_constraint(x_j), new_a); expl.push_justification(column_lower_bound_constraint(x_j), new_a);
} }
else { else {
lp_assert(at_upper(x_j)); 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]; return m_lar_solver->m_mpq_lar_core_solver.m_r_heading[j];
} }
template <typename T> // template <typename T>
void int_solver::fill_cut_solver(cut_solver<T> & cs) { // void int_solver::fill_cut_solver_for_constraint(constraint_index ci, cut_solver<T> & cs) {
for (lar_base_constraint * c : m_lar_solver->constraints()) // const lar_base_constraint* c = m_lar_solver->constraints()[ci];
fill_cut_solver_for_constraint(c, cs); // 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 // it produces an inequality coeff*x <= rs
template <typename T> 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 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; int sign = ((int)c->m_kind > 0) ? -1 : 1;
vector<std::pair<T, var_index>> lhs = c->get_left_side_coefficients(); vector<std::pair<T, var_index>> lhs = c->get_left_side_coefficients();
T den = denominator(c->m_right_side); T den = denominator(c->m_right_side);
for (auto & kv : lhs) { 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)); den = lcm(den, denominator(kv.first));
} }
lp_assert(den > 0); lp_assert(den > 0);
for (auto& kv : lhs) { 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; rs = den * c->m_right_side * sign;
if (kind_is_strict(c->m_kind)) 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) { lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) {
init_check_data(); init_check_data();
lp_assert(inf_int_set_is_correct()); 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() // 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()) if (!has_inf_int())
return lia_move::ok; return lia_move::ok;
if (settings().m_run_gcd_test) 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()) if (!has_inf_int())
return lia_move::ok; return lia_move::ok;
// lp_assert(non_basic_columns_are_at_bounds()); if ((++m_branch_cut_counter) % settings().m_int_branch_cut_solver == 0) {
TRACE("gomory_cut", tout << m_branch_cut_counter+1 << ", " << settings().m_int_branch_cut_gomory_threshold << std::endl;); TRACE("check_main_int", tout<<"cut_solver";);
if (++m_branch_cut_counter > 0) { // testing cut_solver auto check_res = m_cut_solver.check();
cut_solver<mpq> cs([this](unsigned j) {return m_lar_solver->get_column_name(j);}); settings().st().m_cut_solver_calls++;
fill_cut_solver(cs); switch (check_res) {
} else case lbool::l_false:
if ((++m_branch_cut_counter) % settings().m_int_branch_cut_gomory_threshold == 0) { copy_explanations_from_cut_solver(ex);
if (move_non_basic_columns_to_bounds()) { settings().st().m_cut_solver_false++;
lp_status st = m_lar_solver->find_feasible_solution(); return lia_move::conflict;
lp_assert(non_basic_columns_are_at_bounds()); case lbool::l_true:
if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) { settings().st().m_cut_solver_true++;
TRACE("arith_int", tout << "give_up\n";); copy_values_from_cut_solver();
return lia_move::give_up; return lia_move::ok;
} case lbool::l_undef:
} settings().st().m_cut_solver_undef++;
int j = find_inf_int_base_column(); settings().m_int_branch_cut_solver *= (settings().m_int_branch_cut_solver); // take a square
if (j == -1) return lia_move::ok; break;
TRACE("arith_int", tout << "j = " << j << " does not have an integer assignment: " << get_value(j) << "\n";); default:
return proceed_with_gomory_cut(t, k, ex, j); 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); 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]; auto & val = lcs.m_r_x[j];
switch (lcs.m_column_types()[j]) { switch (lcs.m_column_types()[j]) {
case column_type::boxed: 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) 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 else
set_value_for_nbasic_column(j, lcs.m_r_upper_bounds()[j]); set_value_for_nbasic_column(j, lcs.m_r_upper_bounds()[j]);
return true; return true;
} }
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (val != lcs.m_r_low_bounds()[j]) { if (val != lcs.m_r_lower_bounds()[j]) {
set_value_for_nbasic_column(j, lcs.m_r_low_bounds()[j]); set_value_for_nbasic_column(j, lcs.m_r_lower_bounds()[j]);
return true; return true;
} }
break; 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)) { while (it.next(a, j)) {
if (m_lar_solver->column_is_fixed(j)) { if (m_lar_solver->column_is_fixed(j)) {
mpq aux = lcm_den * a; 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)) { else if (m_lar_solver->column_is_real(j)) {
return true; return true;
@ -744,16 +787,16 @@ bool int_solver::ext_gcd_test(iterator_on_row<mpq> & it,
if (abs_ncoeff == least_coeff) { if (abs_ncoeff == least_coeff) {
SASSERT(m_lar_solver->column_is_bounded(j)); SASSERT(m_lar_solver->column_is_bounded(j));
if (ncoeff.is_pos()) { if (ncoeff.is_pos()) {
// l += 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_low_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 += ncoeff * m_lar_solver->column_upper_bound(j).x;
u.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x); u.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x);
} }
else { else {
// l += ncoeff * upper_bound(j).get_rational(); // l += ncoeff * upper_bound(j).get_rational();
l.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x); l.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x);
// u += ncoeff * low_bound(j).get_rational(); // u += ncoeff * lower_bound(j).get_rational();
u.addmul(ncoeff, m_lar_solver->column_low_bound(j).x); u.addmul(ncoeff, m_lar_solver->column_lower_bound(j).x);
} }
add_to_explanation_from_fixed_or_boxed_column(j, ex); 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) : int_solver::int_solver(lar_solver* lar_slv) :
m_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); lp_assert(m_old_values_set.size() == 0);
m_old_values_set.resize(lar_slv->A_r().column_count()); 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>()); 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]) { switch (m_lar_solver->m_mpq_lar_core_solver.m_column_types()[j]) {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: case column_type::boxed:
case column_type::low_bound: case column_type::lower_bound:
return true; return true;
default: default:
return false; return false;
@ -853,7 +901,7 @@ bool int_solver::get_freedom_interval_for_column(unsigned j, bool & inf_l, impq
m = mpq(1); m = mpq(1);
if (has_low(j)) { if (has_low(j)) {
set_lower(l, inf_l, low_bound(j)); set_lower(l, inf_l, lower_bound(j));
} }
if (has_upper(j)) { if (has_upper(j)) {
set_upper(u, inf_u, upper_bound(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)); m = lcm(m, denominator(a));
if (a.is_neg()) { if (a.is_neg()) {
if (has_low(i)) 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)) if (has_upper(i))
set_upper(u, inf_u, xj + (xi - lcs.m_r_upper_bounds()[i]) / a); 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)) if (has_upper(i))
set_lower(l, inf_l, xj + (xi - lcs.m_r_upper_bounds()[i]) / a); set_lower(l, inf_l, xj + (xi - lcs.m_r_upper_bounds()[i]) / a);
if (has_low(i)) 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;; 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::fixed:
case column_type::boxed: case column_type::boxed:
return 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); mpq_solver.m_upper_bounds[j] == get_value(j);
case column_type::low_bound: case column_type::lower_bound:
return mpq_solver.m_low_bounds[j] == get_value(j); return mpq_solver.m_lower_bounds[j] == get_value(j);
case column_type::upper_bound: case column_type::upper_bound:
return mpq_solver.m_upper_bounds[j] == get_value(j); return mpq_solver.m_upper_bounds[j] == get_value(j);
default: default:
@ -987,8 +1035,8 @@ bool int_solver::at_low(unsigned j) const {
switch (mpq_solver.m_column_types[j] ) { switch (mpq_solver.m_column_types[j] ) {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: case column_type::boxed:
case column_type::low_bound: case column_type::lower_bound:
return mpq_solver.m_low_bounds[j] == get_value(j); return mpq_solver.m_lower_bounds[j] == get_value(j);
default: default:
return false; return false;
} }
@ -1099,11 +1147,11 @@ bool int_solver::non_basic_columns_are_at_bounds() const {
auto & val = lcs.m_r_x[j]; auto & val = lcs.m_r_x[j];
switch (lcs.m_column_types()[j]) { switch (lcs.m_column_types()[j]) {
case column_type::boxed: 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; return false;
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (val != lcs.m_r_low_bounds()[j]) if (val != lcs.m_r_lower_bounds()[j])
return false; return false;
break; break;
case column_type::upper_bound: case column_type::upper_bound:
@ -1119,8 +1167,8 @@ bool int_solver::non_basic_columns_are_at_bounds() const {
return true; return true;
} }
const impq& int_solver::low_bound(unsigned j) const { const impq& int_solver::lower_bound(unsigned j) const {
return m_lar_solver->column_low_bound(j); 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 { 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); 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();
}
} }

View file

@ -16,18 +16,23 @@ class lar_solver;
template <typename T, typename X> template <typename T, typename X>
struct lp_constraint; struct lp_constraint;
enum class lia_move { enum class lia_move {
ok, ok,
branch, branch,
cut, cut,
conflict, conflict,
give_up continue_with_check,
}; give_up,
unsat
};
struct explanation { struct explanation {
vector<std::pair<mpq, constraint_index>> m_explanation; vector<std::pair<mpq, constraint_index>> m_explanation;
void push_justification(constraint_index j, const mpq& v) { void push_justification(constraint_index j, const mpq& v) {
m_explanation.push_back(std::make_pair(v, j)); 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 { class int_solver {
@ -37,15 +42,15 @@ public:
int_set m_old_values_set; int_set m_old_values_set;
vector<impq> m_old_values_data; vector<impq> m_old_values_data;
unsigned m_branch_cut_counter; unsigned m_branch_cut_counter;
cut_solver m_cut_solver;
// methods // methods
int_solver(lar_solver* lp); int_solver(lar_solver* lp);
int_set& inf_int_set(); int_set& inf_int_set();
const int_set& inf_int_set() const; 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. // or provide a way of how it can be adjusted.
lia_move check(lar_term& t, mpq& k, explanation& ex); 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); lia_move check_wrapper(lar_term& t, mpq& k, explanation& ex);
private: private:
@ -78,11 +83,11 @@ private:
explanation & ex); explanation & ex);
void fill_explanation_from_fixed_columns(iterator_on_row<mpq> & it, explanation &); 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 add_to_explanation_from_fixed_or_boxed_column(unsigned j, explanation &);
void patch_int_infeasible_non_basic_column(unsigned j); void patch_int_infeasible_non_basic_column(unsigned j);
void patch_int_infeasible_nbasic_columns(); 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); 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); 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; const impq & upper_bound(unsigned j) const;
bool is_int(unsigned j) const; bool is_int(unsigned j) const;
bool is_real(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 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); 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 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); bool constrain_free_vars(linear_combination_iterator<mpq> * r);
lia_move proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex, unsigned j); 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); 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 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); 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_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 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); 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; bool current_solution_is_inf_on_cut(const lar_term& t, const mpq& k) const;
@ -146,11 +151,15 @@ private:
public: public:
void display_inf_or_int_inf_columns(std::ostream & out) const; void display_inf_or_int_inf_columns(std::ostream & out) const;
template <typename T> template <typename T>
void fill_cut_solver(cut_solver<T> & cs); void fill_cut_solver_vars();
template <typename T> template <typename T>
void fill_cut_solver_for_constraint(const lar_base_constraint*, cut_solver<T>& ); void get_int_coeffs_from_constraint(const lar_base_constraint* c, vector<cut_solver::monomial>& coeff, T & rs);
template <typename T> bool is_term(unsigned j) const;
void get_int_coeffs_from_constraint(const lar_base_constraint* c, vector<std::pair<T, var_index>>& coeff, T & rs); 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();
}; };
} }

View file

@ -8,17 +8,51 @@
#include "util/lp/stacked_value.h" #include "util/lp/stacked_value.h"
#include "util/lp/stacked_map.h" #include "util/lp/stacked_map.h"
namespace lp { namespace lp {
enum class endpoint_kind { START, END, STEND };
// represents the set of disjoint intervals of integer number // represents the set of disjoint intervals of integer number
template <typename T> template <typename T>
class integer_domain { class integer_domain {
#ifdef Z3DEBUG #ifdef Z3DEBUG
std::set<int> m_domain; // std::set<int> m_domain;
#endif #endif
typedef typename std::map<T, char>::iterator iter; struct endpoint { int m_start_expl; int m_end_expl;
typedef typename std::map<T, char>::const_iterator const_iter; endpoint() : m_start_expl(-1), m_end_expl(-1) {}
typedef typename std::map<T, char>::reverse_iterator riter; endpoint(int s, int e) : m_start_expl(s), m_end_expl(e) {}
stacked_map<T, char> m_endpoints; // 0 means start, 1 means end, 2 means both - for a point interval endpoint_kind kind() const {
stacked_value<bool> m_empty; 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: public:
// the default constructor creates a set containing all integer numbers // the default constructor creates a set containing all integer numbers
integer_domain() : integer_domain(false) {} integer_domain() : integer_domain(false) {}
@ -28,10 +62,10 @@ public:
// otherwise it creates an empty set // otherwise it creates an empty set
integer_domain(bool is_empty) : m_empty(is_empty) { integer_domain(bool is_empty) : m_empty(is_empty) {
#if Z3DEBUG #if Z3DEBUG
if (!is_empty) { // if (!is_empty) {
for (int i = 0; i <= 100; i++) // for (int i = 0; i <= 100; i++)
m_domain.insert(i); // m_domain.insert(i);
} // }
#endif #endif
} }
@ -39,15 +73,15 @@ public:
m_empty = false; m_empty = false;
m_endpoints.clear(); m_endpoints.clear();
#if Z3DEBUG #if Z3DEBUG
for (int i = 0; i <= 100; i++) // for (int i = 0; i <= 100; i++)
m_domain.insert(i); // m_domain.insert(i);
#endif #endif
} }
// copy constructor // copy constructor
integer_domain(const integer_domain<T> & t) : integer_domain(const integer_domain<T> & t) :
#if Z3DEBUG #if Z3DEBUG
m_domain(t.m_domain), // m_domain(t.m_domain),
#endif #endif
m_endpoints(t.m_endpoints), m_endpoints(t.m_endpoints),
m_empty(t.m_empty) m_empty(t.m_empty)
@ -57,11 +91,11 @@ public:
// needed for debug only // needed for debug only
void restore_domain() { void restore_domain() {
#if Z3DEBUG #if Z3DEBUG
for (int i = 0; i <= 100; i++) // for (int i = 0; i <= 100; i++)
if (contains(i)) // if (contains(i))
m_domain.insert(i); // m_domain.insert(i);
else // else
m_domain.erase(i); // m_domain.erase(i);
#endif #endif
} }
@ -86,6 +120,7 @@ public:
return true; return true;
return is_proper_start(l); return is_proper_start(l);
} }
void handle_right_point_in_union(const_iter &r, const T &y) { void handle_right_point_in_union(const_iter &r, const T &y) {
if (pos(r) == y) { if (pos(r) == y) {
if (is_proper_start(r)) if (is_proper_start(r))
@ -130,97 +165,98 @@ public:
} }
void unite_with_interval(const T& x, const T& y) { void unite_with_interval(const T& x, const T& y) {
TRACE("disj_intervals", tout << "unite_with_interval(" << x << ", " << y << ")\n";); lp_assert(false);
#if Z3DEBUG // TRACE("disj_intervals", tout << "unite_with_interval(" << x << ", " << y << ")\n";);
for (int i = std::max(x, 0); i <= std::min(100, y); i++) // #if Z3DEBUG
m_domain.insert(i); // // for (int i = std::max(x, 0); i <= std::min(100, y); i++)
#endif // // m_domain.insert(i);
// #endif
lp_assert(x <= y); // lp_assert(x <= y);
if (x == y) { // if (x == y) {
unite_with_one_point_interval(x); // unite_with_one_point_interval(x);
return; // return;
} // }
const_iter l, r; // const_iter l, r;
bool neg_inf, pos_inf; // bool neg_inf, pos_inf;
bool found_left_point = get_left_point(x, neg_inf, l); // bool found_left_point = get_left_point(x, neg_inf, l);
bool found_right_point = get_right_point(y, pos_inf, r); // bool found_right_point = get_right_point(y, pos_inf, r);
m_empty = false; // m_empty = false;
if (!found_left_point) { // if (!found_left_point) {
if (!found_right_point) { // if (!found_right_point) {
m_endpoints.clear(); // m_endpoints.clear();
set_start(x); // set_start(x);
set_end(y); // set_end(y);
return; // return;
} // }
// found_right_point is true // // found_right_point is true
if (pos_inf) { // if (pos_inf) {
m_endpoints.clear(); // m_endpoints.clear();
set_start(x); // set_start(x);
return; // return;
} // }
remove_from_the_left(y); // remove_from_the_left(y);
if (pos(m_endpoints.begin()) == y || pos(m_endpoints.begin()) == y + 1) { // if (pos(m_endpoints.begin()) == y || pos(m_endpoints.begin()) == y + 1) {
if (is_proper_start(m_endpoints.begin())) // if (is_proper_start(m_endpoints.begin()))
m_endpoints.erase(m_endpoints.begin()); // m_endpoints.erase(m_endpoints.begin());
else // else
set_end(pos(m_endpoints.begin())); // set_end(pos(m_endpoints.begin()));
set_start(x); // set_start(x);
} // }
else { // else {
lp_assert(pos(m_endpoints.begin()) > y + 1); // lp_assert(pos(m_endpoints.begin()) > y + 1);
if (is_start(m_endpoints.begin())) // if (is_start(m_endpoints.begin()))
set_end(y); // set_end(y);
set_start(x); // set_start(x);
} // }
return; // return;
} // }
lp_assert(found_left_point); // lp_assert(found_left_point);
if (!found_right_point) { // if (!found_right_point) {
bool neg_inf = has_neg_inf(); // bool neg_inf = has_neg_inf();
remove_from_the_right(x); // remove_from_the_right(x);
if (m_endpoints.empty()) { // if (m_endpoints.empty()) {
if (!neg_inf) // if (!neg_inf)
set_start_end(x, y); // set_start_end(x, y);
else // else
set_end(y); // set_end(y);
return; // return;
} // }
if (pos(m_endpoints.rbegin()) == x || pos(m_endpoints.rbegin()) == x - 1) { // if (pos(m_endpoints.rbegin()) == x || pos(m_endpoints.rbegin()) == x - 1) {
if (is_proper_end(m_endpoints.rbegin())) { // if (is_proper_end(m_endpoints.rbegin())) {
m_endpoints.erase(m_endpoints.rbegin()); // m_endpoints.erase(m_endpoints.rbegin());
} // }
else if (is_one_point_interval(m_endpoints.rbegin())) { // else if (is_one_point_interval(m_endpoints.rbegin())) {
set_start(pos(m_endpoints.rbegin())); // set_start(pos(m_endpoints.rbegin()));
} // }
set_end(y); // set_end(y);
} // }
else { // else {
if (is_end(m_endpoints.rbegin())) { // if (is_end(m_endpoints.rbegin())) {
set_start(x); // set_start(x);
set_end(y); // set_end(y);
} // }
else { // else {
set_end(y); // set_end(y);
} // }
} // }
return; // return;
} // }
// found_right_point and found_left_point // // found_right_point and found_left_point
if (!neg_inf) // if (!neg_inf)
handle_left_point_in_union(l, x, y); // handle_left_point_in_union(l, x, y);
else { // else {
remove_from_the_left(y); // remove_from_the_left(y);
} // }
if (!pos_inf) // if (!pos_inf)
handle_right_point_in_union(r, y); // handle_right_point_in_union(r, y);
else // else
remove_from_the_right(x); // remove_from_the_right(x);
} }
bool has_pos_inf() const { bool has_pos_inf() const {
@ -231,7 +267,7 @@ public:
return true; return true;
lp_assert(m_endpoints.rbegin() != m_endpoints.rend()); 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 { bool has_neg_inf() const {
@ -241,7 +277,7 @@ public:
if (m_endpoints.empty()) if (m_endpoints.empty())
return true; return true;
auto it = m_endpoints.begin(); 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 { bool is_correct() const {
@ -272,7 +308,7 @@ public:
return false; return false;
} }
} }
if (t.second == 2) { if (t.second.kind() == endpoint_kind::STEND) {
expect_end = false; // swallow a point interval expect_end = false; // swallow a point interval
} }
else { else {
@ -285,12 +321,12 @@ public:
prev_x = t.first; prev_x = t.first;
} }
#if Z3DEBUG #if Z3DEBUG
for (int i = 0; i <= 100; i++ ) { // for (int i = 0; i <= 100; i++ ) {
if ( (m_domain.find(i) != m_domain.end()) != contains(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;); // TRACE("disj_intervals", tout << "incorrect value of contains(" << i << ") is = " << contains(i) << std::endl;);
return false; // return false;
} // }
} // }
#endif #endif
return true; return true;
} }
@ -307,45 +343,54 @@ public:
bool first = true; bool first = true;
for (auto t : m_endpoints()) { for (auto t : m_endpoints()) {
if (first) { if (first) {
if (t.second == 1) { if (t.second.kind() == endpoint_kind::END) {
out << "[-oo," << t.first << "]"; 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; first = false;
} else { } else {
if (t.second==0) if (t.second.kind() == endpoint_kind::START) {
out << "[" << t.first << ","; out << "[" << t.first; t.second.print(out); out << ",";
else if (t.second == 1) }
out << t.first << "]"; else if (t.second.kind() == endpoint_kind::END) {
else if (t.second == 2) out << t.first; t.second.print(out); out << "]";
out << "[" << t.first << "]"; }
else if (t.second.kind() == endpoint_kind::STEND) {
out << "[" << t.first; t.second.print(out); out << "]";;
}
} }
} }
if (has_pos_inf()) if (has_pos_inf())
out << "oo]"; out << "oo]";
out << "\n"; out << "\n";
} }
void push() { m_endpoints.push(); m_empty.push(); } void push() { m_endpoints.push(); m_empty.push(); }
void pop() { m_endpoints.pop(); m_empty.pop(); } void pop() { m_endpoints.pop(); m_empty.pop(); }
void pop(unsigned k) { while(k--) 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 // 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 #ifdef Z3DEBUG
for (int i = 0; i < x; i++) // for (int i = 0; i < x; i++)
m_domain.erase(i); // m_domain.erase(i);
#endif #endif
TRACE("disj_intervals", tout << "intersect_with_lower_bound(" << x << ")\n";); TRACE("disj_intervals", tout << "intersect_with_lower_bound(" << x << ")\n";);
if (m_empty) if (m_empty)
return; return false;
if (m_endpoints.empty()) { if (m_endpoints.empty()) {
set_start(x); set_start(x, explanation);
return; return true;
} }
bool pos_inf = has_pos_inf(); bool pos_inf = has_pos_inf();
auto it = m_endpoints.begin(); auto it = m_endpoints.begin();
@ -356,70 +401,104 @@ public:
if (m_endpoints.empty()) { if (m_endpoints.empty()) {
if (!pos_inf) { if (!pos_inf) {
m_empty = true; m_empty = true;
return; return true;
} }
set_start(x); set_start(x, explanation);
return; return true;
} }
lp_assert(pos(it) >= x); lp_assert(pos(it) >= x);
if (pos(it) == x) { if (pos(it) == x) {
if (is_proper_end(it)) if (is_proper_end(it)) {
set_one_point_interval(x); set_start(x, explanation);
return true;
}
} }
else { // x(it) > x else { // x(it) > x
if (is_proper_end(it)) { 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 // 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 #ifdef Z3DEBUG
for (int i = 100; i > x; i--) // for (int i = 100; i > x; i--)
m_domain.erase(i); // m_domain.erase(i);
#endif #endif
TRACE("disj_intervals", tout << "intersect_with_upper_bound(" << x << ")\n";); TRACE("disj_intervals", tout << "intersect_with_upper_bound(" << x << ")\n";);
if (m_empty) if (m_empty)
return; return false;
if (m_endpoints.empty()) { if (m_endpoints.empty()) {
set_end(x); set_end(x, explanation);
return; return true;
} }
bool neg_inf = has_neg_inf(); bool neg_inf = has_neg_inf();
auto it = m_endpoints.rbegin(); auto it = m_endpoints.rbegin();
bool change = false;
while (!m_endpoints.empty() && pos(it) > x) { while (!m_endpoints.empty() && pos(it) > x) {
m_endpoints.erase(std::prev(m_endpoints.end())); m_endpoints.erase(std::prev(m_endpoints.end()));
it = m_endpoints.rbegin(); it = m_endpoints.rbegin();
change = true;
} }
if (m_endpoints.empty()) { if (m_endpoints.empty()) {
if (!neg_inf) { if (!neg_inf) {
m_empty = true; m_empty = true;
return; return true;
} }
set_end(x); set_end(x, explanation);
change = true;
} }
lp_assert(pos(it) <= x); lp_assert(pos(it) <= x);
if (pos(it) == x) { if (pos(it) == x) {
if (is_one_point_interval(it)) {} if (is_one_point_interval(it)) {}
else if (is_proper_end(it)) {} else if (is_proper_end(it)) {}
else {// is_proper_start(it->second) else {// is_proper_start(it->second)
set_one_point_interval(x); set_end(x, explanation);
change = true;
} }
} }
else { // pos(it) < x} else { // pos(it) < x}
if (is_proper_start(it)) if (is_proper_start(it)) {
set_end(x); set_end(x, explanation);
change = true;
}
} }
lp_assert(is_correct()); lp_assert(is_correct());
return change;
} }
public: public:
void intersect_with_interval(const T& x, const T & y) { void intersect_with_interval(const T& x, const T & y) {
#ifdef Z3DEBUG #ifdef Z3DEBUG
for (int i = 0; i <= 100; i++) // for (int i = 0; i <= 100; i++)
if (i < x || i > y) // if (i < x || i > y)
m_domain.erase(i); // m_domain.erase(i);
#endif #endif
TRACE("disj_intervals", tout << "intersect_with_interval(" << x << ", " << y <<")\n";); TRACE("disj_intervals", tout << "intersect_with_interval(" << x << ", " << y <<")\n";);
@ -432,110 +511,108 @@ public:
// add an intervar [x, inf] // add an intervar [x, inf]
void unite_with_interval_x_pos_inf(const T& x) { void unite_with_interval_x_pos_inf(const T& x) {
if (contains_all()) lp_assert(false);
return; // if (contains_all())
#if Z3DEBUG // return;
for (int i = x; i <= 100; i++) // #if Z3DEBUG
m_domain.insert(i); // // for (int i = x; i <= 100; i++)
#endif // // m_domain.insert(i);
TRACE("disj_intervals", tout << "unite_with_interval_x_pos_inf(" << x << ")\n";); // #endif
if (m_empty) { // TRACE("disj_intervals", tout << "unite_with_interval_x_pos_inf(" << x << ")\n";);
set_start(x); // if (m_empty) {
m_empty = false; // set_start(x);
return; // m_empty = false;
} // return;
bool neg_inf = has_neg_inf(); // }
remove_from_the_right(x); // bool neg_inf = has_neg_inf();
if (m_endpoints.empty()) { // remove_from_the_right(x);
if (!neg_inf) // if (m_endpoints.empty()) {
set_start(x); // if (!neg_inf)
return; // set_start(x);
} // return;
auto it = m_endpoints.rbegin(); // }
lp_assert(pos(it) <= x); // auto it = m_endpoints.rbegin();
if (pos(it) == x) { // lp_assert(pos(it) <= x);
if (is_proper_end(it)) { // if (pos(it) == x) {
m_endpoints.erase(x); // if (is_proper_end(it)) {
} else { // m_endpoints.erase(x);
set_start(x); // } else {
} // set_start(x);
} else if (pos(it) == x - 1 && is_end(it)) { // }
if (is_proper_start(it)) { // } else if (pos(it) == x - 1 && is_end(it)) {
// do nothing // if (is_proper_start(it)) {
} // // do nothing
else if (is_proper_end(it)) { // }
m_endpoints.erase(it); // else if (is_proper_end(it)) {
} // m_endpoints.erase(it);
else { // }
lp_assert(is_one_point_interval(it)); // else {
set_start(it); // lp_assert(is_one_point_interval(it));
} // set_start(it);
} else { // }
if (!has_pos_inf()) // } else {
set_start(x); // if (!has_pos_inf())
} // set_start(x);
// }
} }
// add an interval [-inf, x] // add an interval [-inf, x]
void unite_with_interval_neg_inf_x(const T& x) { void unite_with_interval_neg_inf_x(const T& x) {
#if Z3DEBUG lp_assert(false); // not implemented
for (int i = 0; i <= x; i++) // #if Z3DEBUG
m_domain.insert(i); // // for (int i = 0; i <= x; i++)
#endif // // m_domain.insert(i);
TRACE("disj_intervals", tout << "unite_with_interval_neg_inf_x(" << x << ")\n";); // #endif
if (m_empty) { // TRACE("disj_intervals", tout << "unite_with_interval_neg_inf_x(" << x << ")\n";);
set_end(x); // if (m_empty) {
m_empty = false; // set_end(x);
return; // m_empty = false;
} // return;
bool pos_inf; // }
const_iter r; // bool pos_inf;
bool found_right_point = get_right_point(x, pos_inf, r); // const_iter r;
if (!found_right_point) { // bool found_right_point = get_right_point(x, pos_inf, r);
m_endpoints.clear(); // if (!found_right_point) {
set_end(x); // m_endpoints.clear();
return; // set_end(x);
} // return;
if (pos_inf) { // }
m_endpoints.clear(); // if (pos_inf) {
return; // m_endpoints.clear();
} // return;
lp_assert(pos(r) >= x); // }
if (pos(r) == x || pos(r) == x + 1) { // lp_assert(pos(r) >= x);
if (is_proper_start(r)) // if (pos(r) == x || pos(r) == x + 1) {
erase(r); // if (is_proper_start(r))
else if (is_one_point_interval(r)) { // erase(r);
set_end(pos(r)); // else if (is_one_point_interval(r)) {
} // do nothing for the proper end // set_end(pos(r));
} else { // } // do nothing for the proper end
if (!is_proper_end(r)) // } else {
set_end(x); // if (!is_proper_end(r))
} // set_end(x);
// }
while (!m_endpoints.empty() && m_endpoints.begin()->first < x) { // while (!m_endpoints.empty() && m_endpoints.begin()->first < x) {
m_endpoints.erase(m_endpoints.begin()); // m_endpoints.erase(m_endpoints.begin());
} // }
lp_assert(is_correct()); // lp_assert(is_correct());
} }
private: 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 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 const_iter & it) const { return is_start(it->second); }
bool is_start(const riter & it) const { bool is_start(const riter & it) const { return is_start(it->second); }
return is_start(it->second); bool is_start(const endpoint & e) const { return is_start(e.kind()); }
}
bool is_end(char x) const { return x == 1 || x == 2; } bool is_end(endpoint_kind x) const { return x == endpoint_kind::END || x == endpoint_kind::STEND; }
bool is_end(const iter & it) const { bool is_end(const iter & it) const { return is_end(it->second); }
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 const_iter & it) const { bool is_end(const endpoint& e) const { return is_end(e.kind()); }
return is_end(it->second);
}
bool is_end(const riter & it) const {
return is_end(it->second);
}
T pos(const iter & it) const { T pos(const iter & it) const {
return it->first; return it->first;
} }
@ -554,22 +631,21 @@ private:
return it->second; 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 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 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 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(endpoint_kind x) const { return x == endpoint_kind::END; }
bool is_proper_end(const iter & it) const { return is_proper_end(it->second); } 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 const_iter & it) const { return is_proper_end(it->second); }
bool is_proper_end(const riter & it) const { bool is_proper_end(const riter & it) const { return is_proper_end(it->second); }
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 endpoint & x) const { return is_one_point_interval(x.kind()); }
bool is_one_point_interval(const iter & it) const { bool is_one_point_interval(endpoint_kind x) const { return x == endpoint_kind::STEND; }
return is_one_point_interval(it->second); 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 { bool is_one_point_interval(const const_iter & it) const {
return is_one_point_interval(it->second); return is_one_point_interval(it->second);
} }
@ -592,41 +668,54 @@ private:
m_endpoints.erase(x); m_endpoints.erase(x);
} }
void set_one_point_interval(const T& x) { /* void set_one_point_interval(const T& x, unsigned explanation) {
m_endpoints[x] = 2; 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) { void set_start(const T& x, unsigned explanation) {
m_endpoints[x] = 0; endpoint e = get_endpoint(x);
e.m_start_expl = explanation;
m_endpoints[x] = e;
} }
void set_start(const iter &t ) { endpoint get_endpoint(const T& x) const {
t->second = 0; 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_end(const_iter& t, unsigned expl) {
void set_start(riter &t ) { endpoint e = t->second;
t->second = 0; e.m_end_expl = expl;
m_endpoints[t->first] = e;
} }
void set_end(const T& x) { void set_end(riter& t, unsigned explanation) {
m_endpoints[x] = 1; 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: private:
void set_start_end(const T& x, const T & y) { /* void set_start_end(const T& x, const T & y, unsigned expl) {
set_start(x); set_start(x, expl);
set_end(y); set_end(y, expl);
} }*/
void unite_with_one_point_interval(const T &x) { void unite_with_one_point_interval(const T &x) {
TRACE("disj_intervals", tout << "unite_with_one_point_interval(" << x << ")\n";); TRACE("disj_intervals", tout << "unite_with_one_point_interval(" << x << ")\n";);
@ -855,6 +944,18 @@ private:
} }
} }
public: 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 { bool get_lower_bound(T& b) const {
if (m_empty) if (m_empty)
return false; return false;
@ -864,6 +965,45 @@ public:
return true; 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 { bool get_upper_bound(T& b) const {
if (m_empty) if (m_empty)
return false; return false;
@ -872,5 +1012,39 @@ public:
b = m_endpoints.rbegin()->first; b = m_endpoints.rbegin()->first;
return true; 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);
}
}; };
} }

View file

@ -22,4 +22,4 @@ Revision History:
#include <string> #include <string>
#include "util/vector.h" #include "util/vector.h"
#include <functional> #include <functional>
#include "util/lp/lar_core_solver.hpp" #include "util/lp/lar_core_solver_def.h"

View file

@ -50,7 +50,7 @@ public:
stacked_vector<column_type> m_column_types; stacked_vector<column_type> m_column_types;
// r - solver fields, for rational numbers // r - solver fields, for rational numbers
vector<numeric_pair<mpq>> m_r_x; // the solution 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; stacked_vector<numeric_pair<mpq>> m_r_upper_bounds;
static_matrix<mpq, numeric_pair<mpq>> m_r_A; static_matrix<mpq, numeric_pair<mpq>> m_r_A;
stacked_vector<unsigned> m_r_pushed_basis; stacked_vector<unsigned> m_r_pushed_basis;
@ -62,7 +62,7 @@ public:
// d - solver fields, for doubles // d - solver fields, for doubles
vector<double> m_d_x; // the solution in 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; vector<double> m_d_upper_bounds;
static_matrix<double, double> m_d_A; static_matrix<double, double> m_d_A;
stacked_vector<unsigned> m_d_pushed_basis; stacked_vector<unsigned> m_d_pushed_basis;
@ -159,7 +159,7 @@ public:
void solve(); 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 { const indexed_vector<mpq> & get_pivot_row() const {
return m_r_solver.m_pivot_row; return m_r_solver.m_pivot_row;
@ -192,7 +192,7 @@ public:
// rational // rational
if (!settings().use_tableau()) if (!settings().use_tableau())
m_r_A.push(); m_r_A.push();
m_r_low_bounds.push(); m_r_lower_bounds.push();
m_r_upper_bounds.push(); m_r_upper_bounds.push();
if (!settings().use_tableau()) { if (!settings().use_tableau()) {
push_vector(m_r_pushed_basis, m_r_basis); push_vector(m_r_pushed_basis, m_r_basis);
@ -234,7 +234,7 @@ public:
// rationals // rationals
if (!settings().use_tableau()) if (!settings().use_tableau())
m_r_A.pop(k); m_r_A.pop(k);
m_r_low_bounds.pop(k); m_r_lower_bounds.pop(k);
m_r_upper_bounds.pop(k); m_r_upper_bounds.pop(k);
m_column_types.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) { 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]; auto & x = m_r_x[j];
switch (pos_type) { switch (pos_type) {
case at_low_bound: case at_lower_bound:
if (x == m_r_solver.m_low_bounds[j]) if (x == m_r_solver.m_lower_bounds[j])
return false; return false;
delta = m_r_solver.m_low_bounds[j] - x; delta = m_r_solver.m_lower_bounds[j] - x;
m_r_solver.m_x[j] = m_r_solver.m_low_bounds[j]; m_r_solver.m_x[j] = m_r_solver.m_lower_bounds[j];
break; break;
case at_fixed: case at_fixed:
case at_upper_bound: case at_upper_bound:
@ -300,22 +300,22 @@ public:
delta = m_r_solver.m_upper_bounds[j] - x; delta = m_r_solver.m_upper_bounds[j] - x;
x = m_r_solver.m_upper_bounds[j]; x = m_r_solver.m_upper_bounds[j];
break; break;
case column_type::low_bound: case column_type::lower_bound:
delta = m_r_solver.m_low_bounds[j] - x; delta = m_r_solver.m_lower_bounds[j] - x;
x = m_r_solver.m_low_bounds[j]; x = m_r_solver.m_lower_bounds[j];
break; break;
case column_type::boxed: case column_type::boxed:
if (x > m_r_solver.m_upper_bounds[j]) { if (x > m_r_solver.m_upper_bounds[j]) {
delta = m_r_solver.m_upper_bounds[j] - x; delta = m_r_solver.m_upper_bounds[j] - x;
x += m_r_solver.m_upper_bounds[j]; x += m_r_solver.m_upper_bounds[j];
} else { } else {
delta = m_r_solver.m_low_bounds[j] - x; delta = m_r_solver.m_lower_bounds[j] - x;
x = m_r_solver.m_low_bounds[j]; x = m_r_solver.m_lower_bounds[j];
} }
break; break;
case column_type::fixed: case column_type::fixed:
delta = m_r_solver.m_low_bounds[j] - x; delta = m_r_solver.m_lower_bounds[j] - x;
x = m_r_solver.m_low_bounds[j]; x = m_r_solver.m_lower_bounds[j];
break; break;
default: default:
@ -359,8 +359,8 @@ public:
lp_assert(m_r_heading[j] < 0); lp_assert(m_r_heading[j] < 0);
auto pos_type = t.second; auto pos_type = t.second;
switch (pos_type) { switch (pos_type) {
case at_low_bound: case at_lower_bound:
s.m_x[j] = s.m_low_bounds[j]; s.m_x[j] = s.m_lower_bounds[j];
break; break;
case at_fixed: case at_fixed:
case at_upper_bound: case at_upper_bound:
@ -377,18 +377,18 @@ public:
case column_type::upper_bound: case column_type::upper_bound:
s.m_x[j] = s.m_upper_bounds[j]; s.m_x[j] = s.m_upper_bounds[j];
break; break;
case column_type::low_bound: case column_type::lower_bound:
s.m_x[j] = s.m_low_bounds[j]; s.m_x[j] = s.m_lower_bounds[j];
break; break;
case column_type::boxed: case column_type::boxed:
if (settings().random_next() % 2) { if (settings().random_next() % 2) {
s.m_x[j] = s.m_low_bounds[j]; s.m_x[j] = s.m_lower_bounds[j];
} else { } else {
s.m_x[j] = s.m_upper_bounds[j]; s.m_x[j] = s.m_upper_bounds[j];
} }
break; break;
case column_type::fixed: case column_type::fixed:
s.m_x[j] = s.m_low_bounds[j]; s.m_x[j] = s.m_lower_bounds[j];
break; break;
default: default:
lp_assert(false); lp_assert(false);
@ -665,27 +665,27 @@ public:
void get_bounds_for_double_solver() { void get_bounds_for_double_solver() {
unsigned n = m_n(); unsigned n = m_n();
m_d_low_bounds.resize(n); m_d_lower_bounds.resize(n);
m_d_upper_bounds.resize(n); m_d_upper_bounds.resize(n);
double delta = find_delta_for_strict_boxed_bounds().get_double(); double delta = find_delta_for_strict_boxed_bounds().get_double();
if (delta > 0.000001) if (delta > 0.000001)
delta = 0.000001; delta = 0.000001;
for (unsigned j = 0; j < n; j++) { for (unsigned j = 0; j < n; j++) {
if (low_bound_is_set(j)) { if (lower_bound_is_set(j)) {
const auto & lb = m_r_solver.m_low_bounds[j]; const auto & lb = m_r_solver.m_lower_bounds[j];
m_d_low_bounds[j] = lb.x.get_double() + delta * lb.y.get_double(); m_d_lower_bounds[j] = lb.x.get_double() + delta * lb.y.get_double();
} }
if (upper_bound_is_set(j)) { if (upper_bound_is_set(j)) {
const auto & ub = m_r_solver.m_upper_bounds[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(); 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( void scale_problem_for_doubles(
static_matrix<double, double>& A, static_matrix<double, double>& A,
vector<double> & low_bounds, vector<double> & lower_bounds,
vector<double> & upper_bounds) { vector<double> & upper_bounds) {
vector<double> column_scale_vector; vector<double> column_scale_vector;
vector<double> right_side_vector(A.column_count()); vector<double> right_side_vector(A.column_count());
@ -705,8 +705,8 @@ public:
if (m_r_solver.column_has_upper_bound(j)) { if (m_r_solver.column_has_upper_bound(j)) {
upper_bounds[j] /= column_scale_vector[j]; upper_bounds[j] /= column_scale_vector[j];
} }
if (m_r_solver.column_has_low_bound(j)) { if (m_r_solver.column_has_lower_bound(j)) {
low_bounds[j] /= column_scale_vector[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]) { switch (m_column_types[j]) {
case column_type::free_column: case column_type::free_column:
case column_type::upper_bound: case column_type::upper_bound:
return false; return false;
case column_type::low_bound: case column_type::lower_bound:
case column_type::boxed: case column_type::boxed:
case column_type::fixed: case column_type::fixed:
return true; return true;
@ -751,7 +751,7 @@ public:
bool upper_bound_is_set(unsigned j) const { bool upper_bound_is_set(unsigned j) const {
switch (m_column_types[j]) { switch (m_column_types[j]) {
case column_type::free_column: case column_type::free_column:
case column_type::low_bound: case column_type::lower_bound:
return false; return false;
case column_type::upper_bound: case column_type::upper_bound:
case column_type::boxed: case column_type::boxed:
@ -780,7 +780,7 @@ public:
for (unsigned j = 0; j < m_r_A.column_count(); j++ ) { for (unsigned j = 0; j < m_r_A.column_count(); j++ ) {
if (m_column_types()[j] != column_type::boxed) if (m_column_types()[j] != column_type::boxed)
continue; 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; return delta;
} }
@ -789,8 +789,8 @@ public:
mpq find_delta_for_strict_bounds(const mpq & initial_delta) const{ mpq find_delta_for_strict_bounds(const mpq & initial_delta) const{
mpq delta = initial_delta; mpq delta = initial_delta;
for (unsigned j = 0; j < m_r_A.column_count(); j++ ) { for (unsigned j = 0; j < m_r_A.column_count(); j++ ) {
if (low_bound_is_set(j)) if (lower_bound_is_set(j))
update_delta(delta, m_r_low_bounds[j], m_r_x[j]); update_delta(delta, m_r_lower_bounds[j], m_r_x[j]);
if (upper_bound_is_set(j)) if (upper_bound_is_set(j))
update_delta(delta, m_r_x[j], m_r_upper_bounds[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 { bool column_is_fixed(unsigned j) const {
return m_column_types()[j] == column_type::fixed || return m_column_types()[j] == column_type::fixed ||
( m_column_types()[j] == column_type::boxed && ( 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 || lp_assert(m_column_types()[j] == column_type::fixed ||
m_column_types()[j] == column_type::boxed || m_column_types()[j] == column_type::boxed ||
m_column_types()[j] == column_type::low_bound); m_column_types()[j] == column_type::lower_bound);
return m_r_low_bounds[j]; return m_r_lower_bounds[j];
} }
const impq & upper_bound(unsigned j) const { const impq & upper_bound(unsigned j) const {

View file

@ -54,7 +54,7 @@ lar_core_solver::lar_core_solver(
m_r_heading, m_r_heading,
m_costs_dummy, m_costs_dummy,
m_column_types(), m_column_types(),
m_r_low_bounds(), m_r_lower_bounds(),
m_r_upper_bounds(), m_r_upper_bounds(),
settings, settings,
column_names), column_names),
@ -66,7 +66,7 @@ lar_core_solver::lar_core_solver(
m_d_heading, m_d_heading,
m_d_costs_dummy, m_d_costs_dummy,
m_column_types(), m_column_types(),
m_d_low_bounds, m_d_lower_bounds,
m_d_upper_bounds, m_d_upper_bounds,
settings, settings,
column_names){} column_names){}
@ -108,17 +108,17 @@ void lar_core_solver::init_cost_for_column(unsigned j) {
if (x > this->m_upper_bounds[j]) { if (x > this->m_upper_bounds[j]) {
this->m_costs[j] = 1; this->m_costs[j] = 1;
this->m_infeasibility += x - this->m_upper_bounds[j]; this->m_infeasibility += x - this->m_upper_bounds[j];
} else if (x < this->m_low_bounds[j]) { } else if (x < this->m_lower_bounds[j]) {
this->m_infeasibility += this->m_low_bounds[j] - x; this->m_infeasibility += this->m_lower_bounds[j] - x;
this->m_costs[j] = -1; this->m_costs[j] = -1;
} else { } else {
this->m_costs[j] = numeric_traits<T>::zero(); this->m_costs[j] = numeric_traits<T>::zero();
} }
break; break;
case low_bound: case lower_bound:
if (x < this->m_low_bounds[j]) { if (x < this->m_lower_bounds[j]) {
this->m_costs[j] = -1; this->m_costs[j] = -1;
this->m_infeasibility += this->m_low_bounds[j] - x; this->m_infeasibility += this->m_lower_bounds[j] - x;
} else { } else {
this->m_costs[j] = numeric_traits<T>::zero(); 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 1;
} }
return 0; return 0;
case low_bound: case lower_bound:
if (this->x_below_low_bound(j)) { if (this->x_below_low_bound(j)) {
return -1; return -1;
} }

View file

@ -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) { void lar_solver::explain_implied_bound(implied_bound & ib, bound_propagator & bp) {
unsigned i = ib.m_row_or_term_index; 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; int j_sign = (ib.m_coeff_before_j_is_pos ? 1 :-1) * bound_sign;
unsigned m_j = ib.m_j; unsigned m_j = ib.m_j;
if (is_term(m_j)) { if (is_term(m_j)) {
auto it = m_ext_vars_to_columns.find(m_j); auto it = m_ext_vars_to_columns.find(m_j);
lp_assert(it != m_ext_vars_to_columns.end()); 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]) { for (auto const& r : A_r().m_rows[i]) {
unsigned j = r.m_j; 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)) { if (is_term(j)) {
auto it = m_ext_vars_to_columns.find(j); auto it = m_ext_vars_to_columns.find(j);
lp_assert(it != m_ext_vars_to_columns.end()); 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 a_sign = is_pos(a)? 1: -1;
int sign = j_sign * a_sign; int sign = j_sign * a_sign;
const ul_pair & ul = m_columns_to_ul_pairs[j]; 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)); lp_assert(is_valid(witness));
bp.consume(a, 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) { for (unsigned i : m_rows_with_changed_bounds.m_index) {
calculate_implied_bounds_for_row(i, bp); calculate_implied_bounds_for_row(i, bp);
if (settings().get_cancel_flag())
return;
} }
m_rows_with_changed_bounds.clear(); m_rows_with_changed_bounds.clear();
if (!use_tableau()) { 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 // 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]; 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.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_term_count.push();
m_constraint_count = m_constraints.size(); m_constraint_count = m_constraints.size();
m_constraint_count.push(); m_constraint_count.push();
m_int_solver->push();
} }
void lar_solver::clean_popped_elements(unsigned n, int_set& set) { 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; m_settings.simplex_strategy() = m_simplex_strategy;
lp_assert(sizes_are_correct()); lp_assert(sizes_are_correct());
lp_assert((!m_settings.use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); 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 { 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; 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_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; 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) { 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()); ci.set_fixed_value(ci.get_upper_bound());
return true; 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) { column_type lar_solver::get_column_type(const column_info<mpq> & ci) {
auto ret = ci.get_column_type_no_flipping(); auto ret = ci.get_column_type_no_flipping();
if (ret == column_type::boxed) { // changing boxed to fixed because of the no span 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; ret = column_type::fixed;
} }
return ret; return ret;
@ -1069,9 +1074,9 @@ bool lar_solver::has_lower_bound(var_index var, constraint_index& ci, mpq& value
return false; return false;
} }
const ul_pair & ul = m_columns_to_ul_pairs[var]; 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)) { 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; value = p.x;
is_strict = p.y.is_pos(); is_strict = p.y.is_pos();
return true; 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; int adj_sign = coeff.is_pos() ? inf_sign : -inf_sign;
const ul_pair & ul = m_columns_to_ul_pairs[j]; 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()); lp_assert(bound_constr_i < m_constraints.size());
explanation.push_back(std::make_pair(coeff, bound_constr_i)); 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; 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) { 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;); TRACE("add_var", tout << "adding var " << ext_j << (is_int? " int" : " nonint") << std::endl;);
var_index i; var_index i;
lp_assert(ext_j < m_terms_start_index); 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? throw 0; // todo : what is the right way to exit?
auto it = m_ext_vars_to_columns.find(ext_j); auto it = m_ext_vars_to_columns.find(ext_j);
if (it != m_ext_vars_to_columns.end()) { 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()); lp_assert(m_columns_to_ul_pairs.size() == A_r().column_count());
i = 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(); unsigned j = A_d().column_count();
A_d().add_column(); 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_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_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); 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 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) { 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(); unsigned j = A_r().column_count();
A_r().add_column(); 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_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_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_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_inf_set.increase_size_by_one();
m_mpq_lar_core_solver.m_r_solver.m_costs.resize(j + 1); 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); 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)) if (!column_is_int(j))
return true; return true;
return right_side.is_int(); 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;); TRACE("lar_solver", tout << "j = " << j << std::endl;);
constraint_index ci = m_constraints.size(); constraint_index ci = m_constraints.size();
if (!is_term(j)) { // j is a var 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); auto vc = new lar_var_constraint(j, kind, right_side);
m_constraints.push_back(vc); 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); update_column_type_and_bound(j, kind, right_side, ci);
} }
else { else {
@ -1657,8 +1674,8 @@ void lar_solver::update_column_type_and_bound(var_index j, lconstraint_kind kind
case column_type::boxed: case column_type::boxed:
update_boxed_column_type_and_bound(j, kind, right_side, constr_index); update_boxed_column_type_and_bound(j, kind, right_side, constr_index);
break; break;
case column_type::low_bound: case column_type::lower_bound:
update_low_bound_column_type_and_bound(j, kind, right_side, constr_index); update_lower_bound_column_type_and_bound(j, kind, right_side, constr_index);
break; break;
case column_type::upper_bound: case column_type::upper_bound:
update_upper_bound_column_type_and_bound(j, kind, right_side, constr_index); 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()); lp_assert(!term_is_int(m_terms[adjusted_term_index]) || right_side.is_int());
auto it = m_ext_vars_to_columns.find(j); auto it = m_ext_vars_to_columns.find(j);
if (it != m_ext_vars_to_columns.end()) { 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; 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)); 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); update_column_type_and_bound(term_j, kind, rs, ci);
} }
else { else {
@ -1738,7 +1757,7 @@ void lar_solver::adjust_initial_state_for_lu() {
copy_from_mpq_matrix(A_d()); copy_from_mpq_matrix(A_d());
unsigned n = A_d().column_count(); unsigned n = A_d().column_count();
m_mpq_lar_core_solver.m_d_x.resize(n); 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_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_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; 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(); unsigned j = A_d().column_count();
A_d().add_column(); 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_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_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); 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 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) { if (register_in_basis) {
@ -1805,19 +1824,19 @@ void lar_solver::update_free_column_type_and_bound(var_index j, lconstraint_kind
case GT: case GT:
y_of_bound = 1; y_of_bound = 1;
case GE: 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); lp_assert(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j);
{ {
auto low = numeric_pair<mpq>(right_side, y_of_bound); 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; break;
case EQ: case EQ:
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; 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_upper_bound_witness(j, constr_ind);
set_low_bound_witness(j, constr_ind); set_lower_bound_witness(j, constr_ind);
break; break;
default: 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; m_mpq_lar_core_solver.m_column_types[j] = column_type::boxed;
{ {
auto low = numeric_pair<mpq>(right_side, y_of_bound); 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, ci); set_lower_bound_witness(j, ci);
m_columns_with_changed_bound.insert(j); m_columns_with_changed_bound.insert(j);
if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
m_status = lp_status::INFEASIBLE; m_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
} }
else { 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; 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>()); auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
m_status = lp_status::INFEASIBLE; m_status = lp_status::INFEASIBLE;
set_low_bound_witness(j, ci); set_lower_bound_witness(j, ci);
m_infeasible_column_index = j; m_infeasible_column_index = j;
} }
else { 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); 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); set_upper_bound_witness(j, ci);
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; 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) { 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); mpq y_of_bound(0);
switch (kind) { switch (kind) {
case LT: 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); 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_status = lp_status::INFEASIBLE;
lp_assert(false); lp_assert(false);
m_infeasible_column_index = j; m_infeasible_column_index = j;
} }
else { 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; 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: case GE:
{ {
auto low = numeric_pair<mpq>(right_side, y_of_bound); auto low = numeric_pair<mpq>(right_side, y_of_bound);
if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) { if (low > m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
m_mpq_lar_core_solver.m_r_low_bounds[j] = low; m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
m_columns_with_changed_bound.insert(j); 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]) { if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
m_status = lp_status::INFEASIBLE; 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: case EQ:
{ {
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>()); 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_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
set_upper_bound_witness(j, ci); 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]) { else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
m_status = lp_status::INFEASIBLE; m_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
set_low_bound_witness(j, ci); set_lower_bound_witness(j, ci);
} }
else { 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;
set_low_bound_witness(j, ci); set_lower_bound_witness(j, ci);
set_upper_bound_witness(j, ci); set_upper_bound_witness(j, ci);
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
m_columns_with_changed_bound.insert(j); 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) { 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::low_bound); lp_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::lower_bound);
mpq y_of_bound(0); mpq y_of_bound(0);
switch (kind) { switch (kind) {
case LT: 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); set_upper_bound_witness(j, ci);
m_columns_with_changed_bound.insert(j); 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_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
} }
else { 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; break;
@ -1987,24 +2006,24 @@ void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint
case GE: case GE:
{ {
auto low = numeric_pair<mpq>(right_side, y_of_bound); auto low = numeric_pair<mpq>(right_side, y_of_bound);
if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) { if (low > m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
m_mpq_lar_core_solver.m_r_low_bounds[j] = low; m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
m_columns_with_changed_bound.insert(j); m_columns_with_changed_bound.insert(j);
set_low_bound_witness(j, ci); set_lower_bound_witness(j, ci);
} }
} }
break; break;
case EQ: case EQ:
{ {
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>()); 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_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
set_upper_bound_witness(j, ci); set_upper_bound_witness(j, ci);
} }
else { 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;
set_low_bound_witness(j, ci); set_lower_bound_witness(j, ci);
set_upper_bound_witness(j, ci); set_upper_bound_witness(j, ci);
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; 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) { 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_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_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_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)); auto v = numeric_pair<mpq>(right_side, mpq(0));
mpq y_of_bound(0); mpq y_of_bound(0);
switch (kind) { switch (kind) {
case LT: 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_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
set_upper_bound_witness(j, ci); 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; break;
case LE: 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_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
set_upper_bound_witness(j, ci); 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]) { if (v >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
m_status = lp_status::INFEASIBLE; m_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
set_low_bound_witness(j, ci); set_lower_bound_witness(j, ci);
} }
} }
break; 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]) { if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
m_status = lp_status::INFEASIBLE; m_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
set_low_bound_witness(j, ci); set_lower_bound_witness(j, ci);
} }
} }
break; break;
case EQ: 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_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
set_upper_bound_witness(j, ci); 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]) { else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
m_status = lp_status::INFEASIBLE; m_status = lp_status::INFEASIBLE;
m_infeasible_column_index = j; m_infeasible_column_index = j;
set_low_bound_witness(j, ci); set_lower_bound_witness(j, ci);
} }
break; 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 } // namespace lp

File diff suppressed because it is too large Load diff

View file

@ -34,7 +34,7 @@ struct linear_combination_iterator_on_vector : linear_combination_iterator<T> {
vector<std::pair<T, unsigned>> & m_vector; vector<std::pair<T, unsigned>> & m_vector;
int m_offset; int m_offset;
bool next(T & a, unsigned & i) { bool next(T & a, unsigned & i) {
if(m_offset >= m_vector.size()) if(static_cast<unsigned>(m_offset) >= m_vector.size())
return false; return false;
auto & p = m_vector[m_offset]; auto & p = m_vector[m_offset];
a = p.first; a = p.first;
@ -44,7 +44,7 @@ struct linear_combination_iterator_on_vector : linear_combination_iterator<T> {
} }
bool next(unsigned & i) { bool next(unsigned & i) {
if(m_offset >= m_vector.size()) if(static_cast<unsigned>(m_offset) >= m_vector.size())
return false; return false;
auto & p = m_vector[m_offset]; auto & p = m_vector[m_offset];
i = p.second; i = p.second;

View file

@ -21,8 +21,8 @@ Revision History:
#include "util/lp/lp_settings.h" #include "util/lp/lp_settings.h"
namespace lp { namespace lp {
class lar_solver; class lar_solver;
class lp_bound_propagator { class bound_propagator {
std::unordered_map<unsigned, unsigned> m_improved_low_bounds; // these maps map a column index to the corresponding index in ibounds 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; std::unordered_map<unsigned, unsigned> m_improved_upper_bounds;
lar_solver & m_lar_solver; lar_solver & m_lar_solver;
public: public:
@ -30,7 +30,7 @@ public:
public: public:
lp_bound_propagator(lar_solver & ls); lp_bound_propagator(lar_solver & ls);
column_type get_column_type(unsigned) const; 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; 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); 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, virtual bool bound_is_interesting(unsigned vi,

View file

@ -22,7 +22,7 @@ Revision History:
#include <string> #include <string>
#include "util/vector.h" #include "util/vector.h"
#include <functional> #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() 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>::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; template bool lp::lp_core_solver_base<double, double>::basis_heading_is_correct() const;

View file

@ -77,7 +77,7 @@ public:
vector<T> m_d; // the vector of reduced costs vector<T> m_d; // the vector of reduced costs
indexed_vector<T> m_ed; // the solution of B*m_ed = a indexed_vector<T> m_ed; // the solution of B*m_ed = a
const vector<column_type> & m_column_types; 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; const vector<X> & m_upper_bounds;
vector<T> m_column_norms; // the approximate squares of column norms that help choosing a profitable column vector<T> m_column_norms; // the approximate squares of column norms that help choosing a profitable column
vector<X> m_copy_of_xB; vector<X> m_copy_of_xB;
@ -127,7 +127,7 @@ public:
lp_settings & settings, lp_settings & settings,
const column_namer& column_names, const column_namer& column_names,
const vector<column_type> & column_types, const vector<column_type> & column_types,
const vector<X> & low_bound_values, const vector<X> & lower_bound_values,
const vector<X> & upper_bound_values); const vector<X> & upper_bound_values);
void allocate_basis_heading(); void allocate_basis_heading();
@ -272,14 +272,14 @@ public:
} }
bool x_below_low_bound(unsigned p) const { 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_costs_are_correct() const;
bool infeasibility_cost_is_correct_for_column(unsigned j) const; bool infeasibility_cost_is_correct_for_column(unsigned j) const;
bool x_above_low_bound(unsigned p) const { bool x_above_lower_bound(unsigned p) const {
return above_bound(m_x[p], m_low_bounds[p]); return above_bound(m_x[p], m_lower_bounds[p]);
} }
bool x_below_upper_bound(unsigned p) const { bool x_below_upper_bound(unsigned p) const {
@ -290,15 +290,15 @@ public:
bool x_above_upper_bound(unsigned p) const { bool x_above_upper_bound(unsigned p) const {
return above_bound(m_x[p], m_upper_bounds[p]); return above_bound(m_x[p], m_upper_bounds[p]);
} }
bool x_is_at_low_bound(unsigned j) const { bool x_is_at_lower_bound(unsigned j) const {
return at_bound(m_x[j], m_low_bounds[j]); return at_bound(m_x[j], m_lower_bounds[j]);
} }
bool x_is_at_upper_bound(unsigned j) const { bool x_is_at_upper_bound(unsigned j) const {
return at_bound(m_x[j], m_upper_bounds[j]); return at_bound(m_x[j], m_upper_bounds[j]);
} }
bool x_is_at_bound(unsigned j) const { 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; bool column_is_feasible(unsigned j) const;
@ -337,8 +337,8 @@ public:
void fill_reduced_costs_from_m_y_by_rows(); void fill_reduced_costs_from_m_y_by_rows();
void copy_rs_to_xB(vector<X> & rs); void copy_rs_to_xB(vector<X> & rs);
virtual bool low_bounds_are_set() const { return false; } virtual bool lower_bounds_are_set() const { return false; }
X low_bound_value(unsigned j) const { return m_low_bounds[j]; } X lower_bound_value(unsigned j) const { return m_lower_bounds[j]; }
X upper_bound_value(unsigned j) const { return m_upper_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]; } column_type get_column_type(unsigned j) const {return m_column_types[j]; }
@ -348,7 +348,7 @@ public:
} }
X bound_span(unsigned j) const { 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; std::string column_name(unsigned column) const;
@ -376,21 +376,21 @@ public:
case column_type::fixed: case column_type::fixed:
if (x_is_at_bound(j)) if (x_is_at_bound(j))
break; break;
m_x[j] = m_low_bounds[j]; m_x[j] = m_lower_bounds[j];
return true; return true;
case column_type::boxed: case column_type::boxed:
if (x_is_at_bound(j)) if (x_is_at_bound(j))
break; // we should preserve x if possible break; // we should preserve x if possible
// snap randomly // snap randomly
if (m_settings.random_next() % 2 == 1) if (m_settings.random_next() % 2 == 1)
m_x[j] = m_low_bounds[j]; m_x[j] = m_lower_bounds[j];
else else
m_x[j] = m_upper_bounds[j]; m_x[j] = m_upper_bounds[j];
return true; return true;
case column_type::low_bound: case column_type::lower_bound:
if (x_is_at_low_bound(j)) if (x_is_at_lower_bound(j))
break; break;
m_x[j] = m_low_bounds[j]; m_x[j] = m_lower_bounds[j];
return true; return true;
case column_type::upper_bound: case column_type::upper_bound:
if (x_is_at_upper_bound(j)) if (x_is_at_upper_bound(j))
@ -409,15 +409,15 @@ public:
auto & x = m_x[j]; auto & x = m_x[j];
switch (m_column_types[j]) { switch (m_column_types[j]) {
case column_type::fixed: case column_type::fixed:
lp_assert(m_low_bounds[j] == m_upper_bounds[j]); lp_assert(m_lower_bounds[j] == m_upper_bounds[j]);
if (x != m_low_bounds[j]) { if (x != m_lower_bounds[j]) {
delta = m_low_bounds[j] - x; delta = m_lower_bounds[j] - x;
ret = true;; ret = true;;
} }
break; break;
case column_type::boxed: case column_type::boxed:
if (x < m_low_bounds[j]) { if (x < m_lower_bounds[j]) {
delta = m_low_bounds[j] - x; delta = m_lower_bounds[j] - x;
ret = true;; ret = true;;
} }
if (x > m_upper_bounds[j]) { if (x > m_upper_bounds[j]) {
@ -425,9 +425,9 @@ public:
ret = true; ret = true;
} }
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (x < m_low_bounds[j]) { if (x < m_lower_bounds[j]) {
delta = m_low_bounds[j] - x; delta = m_lower_bounds[j] - x;
ret = true; ret = true;
} }
break; break;
@ -540,8 +540,8 @@ public:
if (!this->x_is_at_bound(j)) if (!this->x_is_at_bound(j))
return false; return false;
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (!this->x_is_at_low_bound(j)) if (!this->x_is_at_lower_bound(j))
return false; return false;
break; break;
case column_type::upper_bound: case column_type::upper_bound:
@ -570,10 +570,10 @@ public:
switch (m_column_types[j]) { switch (m_column_types[j]) {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: 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; break;
case column_type::low_bound: case column_type::lower_bound:
out << m_low_bounds[j] << std::endl; out << m_lower_bounds[j] << std::endl;
break; break;
case column_type::upper_bound: case column_type::upper_bound:
out << m_upper_bounds[j] << std::endl; out << m_upper_bounds[j] << std::endl;
@ -588,10 +588,10 @@ public:
switch (m_column_types[j]) { switch (m_column_types[j]) {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: case column_type::boxed:
out << " [" << m_low_bounds[j] << ", " << m_upper_bounds[j] << "]"; out << " [" << m_lower_bounds[j] << ", " << m_upper_bounds[j] << "]";
break; break;
case column_type::low_bound: case column_type::lower_bound:
out << " [" << m_low_bounds[j] << "," << "oo" << "]"; out << " [" << m_lower_bounds[j] << "," << "oo" << "]";
break; break;
case column_type::upper_bound: case column_type::upper_bound:
out << " [-oo, " << m_upper_bounds[j] << ']'; out << " [-oo, " << m_upper_bounds[j] << ']';
@ -619,7 +619,7 @@ public:
bool column_has_upper_bound(unsigned j) { bool column_has_upper_bound(unsigned j) {
switch(m_column_types[j]) { switch(m_column_types[j]) {
case column_type::free_column: case column_type::free_column:
case column_type::low_bound: case column_type::lower_bound:
return false; return false;
default: default:
return true; return true;
@ -629,13 +629,13 @@ public:
bool bounds_for_boxed_are_set_correctly() const { bool bounds_for_boxed_are_set_correctly() const {
for (unsigned j = 0; j < m_column_types.size(); j++) { for (unsigned j = 0; j < m_column_types.size(); j++) {
if (m_column_types[j] != column_type::boxed) continue; 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 false;
} }
return true; return true;
} }
bool column_has_low_bound(unsigned j) { bool column_has_lower_bound(unsigned j) {
switch(m_column_types[j]) { switch(m_column_types[j]) {
case column_type::free_column: case column_type::free_column:
case column_type::upper_bound: case column_type::upper_bound:

View file

@ -35,7 +35,7 @@ lp_core_solver_base(static_matrix<T, X> & A,
lp_settings & settings, lp_settings & settings,
const column_namer& column_names, const column_namer& column_names,
const vector<column_type> & column_types, const vector<column_type> & column_types,
const vector<X> & low_bound_values, const vector<X> & lower_bound_values,
const vector<X> & upper_bound_values): const vector<X> & upper_bound_values):
m_total_iterations(0), m_total_iterations(0),
m_iters_with_no_cost_growing(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_d(m_n()),
m_ed(m_m()), m_ed(m_m()),
m_column_types(column_types), m_column_types(column_types),
m_low_bounds(low_bound_values), m_lower_bounds(lower_bound_values),
m_upper_bounds(upper_bound_values), m_upper_bounds(upper_bound_values),
m_column_norms(m_n()), m_column_norms(m_n()),
m_copy_of_xB(m_m()), m_copy_of_xB(m_m()),
@ -392,10 +392,10 @@ set_non_basic_x_to_correct_bounds() {
for (unsigned j : non_basis()) { for (unsigned j : non_basis()) {
switch (m_column_types[j]) { switch (m_column_types[j]) {
case column_type::boxed: 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; break;
case column_type::low_bound: case column_type::lower_bound:
m_x[j] = m_low_bounds[j]; m_x[j] = m_lower_bounds[j];
lp_assert(column_is_dual_feasible(j)); lp_assert(column_is_dual_feasible(j));
break; break;
case column_type::upper_bound: case column_type::upper_bound:
@ -412,12 +412,12 @@ column_is_dual_feasible(unsigned j) const {
switch (m_column_types[j]) { switch (m_column_types[j]) {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: 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)); (x_is_at_upper_bound(j) && d_is_not_positive(j));
case column_type::low_bound: case column_type::lower_bound:
return x_is_at_low_bound(j) && d_is_not_negative(j); return x_is_at_lower_bound(j) && d_is_not_negative(j);
case column_type::upper_bound: 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 lp_assert(false); // impossible case
case column_type::free_column: case column_type::free_column:
return numeric_traits<X>::is_zero(m_d[j]); 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: case column_type::boxed:
if (this->above_bound(x, this->m_upper_bounds[j])) { if (this->above_bound(x, this->m_upper_bounds[j])) {
return false; 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; return false;
} else { } else {
return true; return true;
} }
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (this->below_bound(x, this->m_low_bounds[j])) { if (this->below_bound(x, this->m_lower_bounds[j])) {
return false; return false;
} else { } else {
return true; return true;
@ -861,8 +861,8 @@ snap_non_basic_x_to_bound_and_free_to_zeroes() {
switch (m_column_types[j]) { switch (m_column_types[j]) {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: case column_type::boxed:
case column_type::low_bound: case column_type::lower_bound:
m_x[j] = m_low_bounds[j]; m_x[j] = m_lower_bounds[j];
break; break;
case column_type::upper_bound: case column_type::upper_bound:
m_x[j] = m_upper_bounds[j]; 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 { get_non_basic_column_value_position(unsigned j) const {
switch (m_column_types[j]) { switch (m_column_types[j]) {
case column_type::fixed: 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: case column_type::free_column:
return free_of_bounds; return free_of_bounds;
case column_type::boxed: 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: x_is_at_upper_bound(j)? at_upper_bound:
not_at_bound not_at_bound
); );
case column_type::low_bound: case column_type::lower_bound:
return x_is_at_low_bound(j)? at_low_bound : not_at_bound; return x_is_at_lower_bound(j)? at_lower_bound : not_at_bound;
case column_type::upper_bound: case column_type::upper_bound:
return x_is_at_upper_bound(j)? at_upper_bound : not_at_bound; return x_is_at_upper_bound(j)? at_upper_bound : not_at_bound;
default: default:
lp_unreachable(); lp_unreachable();
} }
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() { 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]); return is_zero(this->m_costs[j]);
case column_type::low_bound: case column_type::lower_bound:
if (this->x_below_low_bound(j)) { if (this->x_below_low_bound(j)) {
return this->m_costs[j] == -r; return this->m_costs[j] == -r;
} }

View file

@ -22,7 +22,7 @@ Revision History:
#include <string> #include <string>
#include "util/vector.h" #include "util/vector.h"
#include <functional> #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>::start_with_initial_basis_and_make_it_dual_feasible();
template void lp::lp_dual_core_solver<lp::mpq, lp::mpq>::solve(); 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>&, template lp::lp_dual_core_solver<double, double>::lp_dual_core_solver(lp::static_matrix<double, double>&, vector<bool>&,

View file

@ -56,7 +56,7 @@ public:
vector<int> & heading, vector<int> & heading,
vector<T> & costs, vector<T> & costs,
vector<column_type> & column_type_array, vector<column_type> & column_type_array,
vector<X> & low_bound_values, vector<X> & lower_bound_values,
vector<X> & upper_bound_values, vector<X> & upper_bound_values,
lp_settings & settings, lp_settings & settings,
const column_namer & column_names): const column_namer & column_names):
@ -70,7 +70,7 @@ public:
settings, settings,
column_names, column_names,
column_type_array, column_type_array,
low_bound_values, lower_bound_values,
upper_bound_values), upper_bound_values),
m_can_enter_basis(can_enter_basis), m_can_enter_basis(can_enter_basis),
m_a_wave(this->m_m()), m_a_wave(this->m_m()),
@ -110,7 +110,7 @@ public:
bool done(); 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); 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 // 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) { 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(); void add_tight_breakpoints_and_q_to_flipped_set();
@ -207,6 +207,6 @@ public:
void solve(); void solve();
bool low_bounds_are_set() const override { return true; } bool lower_bounds_are_set() const override { return true; }
}; };
} }

View file

@ -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 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()); 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; del *= del;
return del / this->m_betas[this->m_basis_heading[p]]; 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::fixed:
case column_type::boxed: case column_type::boxed:
if (this->x_below_low_bound(p)) { 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 del;
} }
if (this->x_above_upper_bound(p)) { 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 del;
} }
return numeric_traits<T>::zero(); return numeric_traits<T>::zero();
case column_type::low_bound: case column_type::lower_bound:
if (this->x_below_low_bound(p)) { 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 del;
} }
return numeric_traits<T>::zero(); 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; return 1;
} }
lp_unreachable(); lp_unreachable();
case column_type::low_bound: case column_type::lower_bound:
if (this->x_below_low_bound(m_p)) { if (this->x_below_low_bound(m_p)) {
return -1; 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) { 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; if (this->pivot_row_element_is_too_small_for_ratio_test(j)) return false;
switch (this->m_column_types[j]) { switch (this->m_column_types[j]) {
case column_type::low_bound: case column_type::lower_bound:
lp_assert(this->m_settings.abs_val_is_smaller_than_harris_tolerance(this->m_x[j] - this->m_low_bounds[j])); 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; return m_sign_of_alpha_r * this->m_pivot_row[j] > 0;
case column_type::upper_bound: 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])); 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; return m_sign_of_alpha_r * this->m_pivot_row[j] < 0;
case column_type::boxed: 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; 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 case column_type::fixed: // is always dual feasible so we ingore it
return false; 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]) { switch (this->m_column_types[m_p]) {
case column_type::boxed: case column_type::boxed:
if (this->x_below_low_bound(m_p)) { 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)) { if (this->x_above_upper_bound(m_p)) {
return this->m_x[m_p] - this->m_upper_bounds[m_p]; return this->m_x[m_p] - this->m_upper_bounds[m_p];
} }
lp_unreachable(); lp_unreachable();
case column_type::low_bound: case column_type::lower_bound:
if (this->x_below_low_bound(m_p)) { 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(); lp_unreachable();
case column_type::upper_bound: 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() { template <typename T, typename X> void lp_dual_core_solver<T, X>::apply_flips() {
for (unsigned j : m_flipped_boxed) { for (unsigned j : m_flipped_boxed) {
lp_assert(this->x_is_at_bound(j)); 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]; this->m_x[j] = this->m_upper_bounds[j];
} else { } 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) { 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]) { switch (this->m_column_type[j]) {
case column_type::fixed: case column_type::fixed:
this->m_x[j] = this->m_low_bounds[j]; this->m_x[j] = this->m_lower_bounds[j];
break; break;
case column_type::boxed: case column_type::boxed:
if (this->x_is_at_low_bound(j)) { if (this->x_is_at_lower_bound(j)) {
this->m_x[j] = this->m_low_bounds[j]; this->m_x[j] = this->m_lower_bounds[j];
} else { } else {
this->m_x[j] = this->m_upper_bounds[j]; this->m_x[j] = this->m_upper_bounds[j];
} }
break; break;
case column_type::low_bound: case column_type::lower_bound:
this->m_x[j] = this->m_low_bounds[j]; this->m_x[j] = this->m_lower_bounds[j];
break; break;
case column_type::upper_bound: case column_type::upper_bound:
this->m_x[j] = this->m_upper_bounds[j]; 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() { template <typename T, typename X> void lp_dual_core_solver<T, X>::recover_leaving() {
switch (m_entering_boundary_position) { switch (m_entering_boundary_position) {
case at_low_bound: case at_lower_bound:
case at_fixed: 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; break;
case at_upper_bound: case at_upper_bound:
this->m_x[m_q] = this->m_upper_bounds[m_q]; 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) { template <typename T, typename X> bool lp_dual_core_solver<T, X>::snap_runaway_nonbasic_column(unsigned j) {
switch (this->m_column_types[j]) { switch (this->m_column_types[j]) {
case column_type::fixed: case column_type::fixed:
case column_type::low_bound: case column_type::lower_bound:
if (!this->x_is_at_low_bound(j)) { if (!this->x_is_at_lower_bound(j)) {
this->m_x[j] = this->m_low_bounds[j]; this->m_x[j] = this->m_lower_bounds[j];
return true; return true;
} }
break; break;
case column_type::boxed: 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]); 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_low_bound) { if (closer_to_lower_bound) {
if (!this->x_is_at_low_bound(j)) { if (!this->x_is_at_lower_bound(j)) {
this->m_x[j] = this->m_low_bounds[j]; this->m_x[j] = this->m_lower_bounds[j];
return true; return true;
} }
} else { } else {
if (!this->x_is_at_upper_bound(j)) { 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; 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 << "m_d[" << j << "] = " << this->m_d[j] << std::endl;
// std::cout << "x[" << j << "] = " << this->m_x[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 << "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; // std::cout << "total_iterations = " << this->total_iterations() << std::endl;
return false; 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); lp_assert(m_breakpoint_set.size() > 0);
for (auto j : m_breakpoint_set) { for (auto j : m_breakpoint_set) {
T t; 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]); t = abs((std::max(this->m_d[j], numeric_traits<T>::zero()) + m_harris_tolerance) / this->m_pivot_row[j]);
} else { } else {
t = abs((std::min(this->m_d[j], numeric_traits<T>::zero()) - m_harris_tolerance) / this->m_pivot_row[j]); 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 ){ 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(); m_tight_set.clear();
for (auto j : m_breakpoint_set) { 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){ if (abs(std::max(this->m_d[j], numeric_traits<T>::zero()) / this->m_pivot_row[j]) <= harris_delta){
m_tight_set.insert(j); m_tight_set.insert(j);
} }

View file

@ -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 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 void lp::lp_dual_simplex<lp::mpq, lp::mpq>::find_maximal_solution();
template double lp::lp_dual_simplex<double, double>::get_current_cost() const; template double lp::lp_dual_simplex<double, double>::get_current_cost() const;

View file

@ -28,7 +28,7 @@ template <typename T, typename X>
class lp_dual_simplex: public lp_solver<T, X> { class lp_dual_simplex: public lp_solver<T, X> {
lp_dual_core_solver<T, X> * m_core_solver; lp_dual_core_solver<T, X> * m_core_solver;
vector<T> m_b_copy; 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_core_solver;
vector<column_type> m_column_types_of_logicals; vector<column_type> m_column_types_of_logicals;
vector<bool> m_can_enter_basis; vector<bool> m_can_enter_basis;

View file

@ -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) { 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()); lp_assert(j >= this->number_of_core_structurals());
switch (m_column_types_of_logicals[j - this->number_of_core_structurals()]) { switch (m_column_types_of_logicals[j - this->number_of_core_structurals()]) {
case column_type::low_bound: case column_type::lower_bound:
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::low_bound; m_column_types_of_core_solver[j] = column_type::lower_bound;
m_can_enter_basis[j] = true; m_can_enter_basis[j] = true;
break; break;
case column_type::fixed: 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_column_types_of_core_solver[j] = column_type::fixed;
m_can_enter_basis[j] = false; m_can_enter_basis[j] = false;
break; 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) { 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]]; 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()) { switch (ci->get_column_type()) {
case column_type::low_bound: case column_type::lower_bound:
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::low_bound; m_column_types_of_core_solver[j] = column_type::lower_bound;
m_can_enter_basis[j] = true; m_can_enter_basis[j] = true;
break; break;
case column_type::fixed: case column_type::fixed:
@ -76,7 +76,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fix_structural_for
lp_unreachable(); lp_unreachable();
case column_type::boxed: case column_type::boxed:
this->m_upper_bounds[j] = ci->get_adjusted_upper_bound() / this->m_column_scale[j]; 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_column_types_of_core_solver[j] = column_type::boxed;
m_can_enter_basis[j] = true; m_can_enter_basis[j] = true;
break; break;
@ -158,7 +158,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::stage1() {
this->m_heading, this->m_heading,
this->m_costs, this->m_costs,
this->m_column_types_of_core_solver, this->m_column_types_of_core_solver,
this->m_low_bounds, this->m_lower_bounds,
this->m_upper_bounds, this->m_upper_bounds,
this->m_settings, this->m_settings,
*this); *this);
@ -216,10 +216,10 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_bounds_
throw_exception(s.str()); throw_exception(s.str());
break; break;
} }
case column_type::low_bound: { case column_type::lower_bound: {
m_can_enter_basis[j] = true; m_can_enter_basis[j] = true;
this->set_scaled_cost(j); 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(); this->m_upper_bounds[j] =numeric_traits<T>::one();
break; 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; m_can_enter_basis[j] = true;
this->set_scaled_cost(j); this->set_scaled_cost(j);
this->m_upper_bounds[j] = free_bound; this->m_upper_bounds[j] = free_bound;
this->m_low_bounds[j] = -free_bound; this->m_lower_bounds[j] = -free_bound;
break; break;
} }
case column_type::boxed: case column_type::boxed:
m_can_enter_basis[j] = false; m_can_enter_basis[j] = false;
this->m_costs[j] = numeric_traits<T>::zero(); 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; break;
default: default:
lp_unreachable(); 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) { 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; this->m_costs[j] = 0;
lp_assert(get_column_type(j) != column_type::upper_bound); 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; 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(); this->m_upper_bounds[j] = numeric_traits<T>::one();
} else { } else {
m_column_types_of_core_solver[j] = column_type::fixed; 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(); 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; break;
case Greater_or_equal: 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(); (*this->m_A)(row, slack_var) = - numeric_traits<T>::one();
if (rs > 0) { if (rs > 0) {
// adding one artificial // adding one artificial
@ -301,7 +301,7 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_first_stage_s
break; break;
case Less_or_equal: case Less_or_equal:
// introduce a non-negative slack variable // 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(); (*this->m_A)(row, slack_var) = numeric_traits<T>::one();
if (rs < 0) { if (rs < 0) {
// adding one artificial // 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); m_column_types_of_logicals.resize(this->m_slacks + this->m_artificials);
this->m_costs.resize(n); this->m_costs.resize(n);
this->m_upper_bounds.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); m_can_enter_basis.resize(n);
this->m_basis.resize(this->m_A->row_count()); this->m_basis.resize(this->m_A->row_count());
} }

View file

@ -23,8 +23,8 @@ Revision History:
#include "util/vector.h" #include "util/vector.h"
#include <functional> #include <functional>
#include "util/lp/lar_solver.h" #include "util/lp/lar_solver.h"
#include "util/lp/lp_primal_core_solver.hpp" #include "util/lp/lp_primal_core_solver_def.h"
#include "util/lp/lp_primal_core_solver_tableau.hpp" #include "util/lp/lp_primal_core_solver_tableau_def.h"
namespace lp { namespace lp {
template void lp_primal_core_solver<double, double>::find_feasible_solution(); template void lp_primal_core_solver<double, double>::find_feasible_solution();

View file

@ -40,7 +40,7 @@ Revision History:
#include "util/lp/iterator_on_row.h" #include "util/lp/iterator_on_row.h"
namespace lp { 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 // The right side b is given implicitly by x and the basis
template <typename T, typename X> template <typename T, typename X>
class lp_primal_core_solver:public lp_core_solver_base<T, X> { class lp_primal_core_solver:public lp_core_solver_base<T, X> {
@ -118,17 +118,17 @@ public:
switch (this->m_column_types[j]) { switch (this->m_column_types[j]) {
case column_type::free_column: return true; case column_type::free_column: return true;
case column_type::fixed: return false; case column_type::fixed: return false;
case column_type::low_bound: case column_type::lower_bound:
if (sign < 0) if (sign < 0)
return true; return true;
return !this->x_is_at_low_bound(j); return !this->x_is_at_lower_bound(j);
case column_type::upper_bound: case column_type::upper_bound:
if (sign > 0) if (sign > 0)
return true; return true;
return !this->x_is_at_upper_bound(j); return !this->x_is_at_upper_bound(j);
case column_type::boxed: case column_type::boxed:
if (sign < 0) 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); return !this->x_is_at_upper_bound(j);
} }
@ -143,7 +143,7 @@ public:
case column_type::free_column: case column_type::free_column:
return false; return false;
case column_type::fixed: case column_type::fixed:
case column_type::low_bound: case column_type::lower_bound:
case column_type::boxed: case column_type::boxed:
return this-> x_below_low_bound(bj); return this-> x_below_low_bound(bj);
default: default:
@ -158,7 +158,7 @@ public:
switch(this->m_column_types[bj]) { switch(this->m_column_types[bj]) {
case column_type::free_column: case column_type::free_column:
return 0; return 0;
case column_type::low_bound: case column_type::lower_bound:
return 1; return 1;
case column_type::fixed: case column_type::fixed:
case column_type::boxed: case column_type::boxed:
@ -180,9 +180,9 @@ public:
return true; return true;
case column_type::fixed: case column_type::fixed:
return false; return false;
case column_type::low_bound: case column_type::lower_bound:
if (is_pos(rc.get_val())) { if (is_pos(rc.get_val())) {
return this->x_above_low_bound(j); return this->x_above_lower_bound(j);
} }
return true; return true;
@ -194,7 +194,7 @@ public:
return this->x_below_upper_bound(j); return this->x_below_upper_bound(j);
case column_type::boxed: case column_type::boxed:
if (is_pos(rc.get_val())) { 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); return this->x_below_upper_bound(j);
@ -213,9 +213,9 @@ public:
return true; return true;
case column_type::fixed: case column_type::fixed:
return false; return false;
case column_type::low_bound: case column_type::lower_bound:
if (is_neg(rc.get_val())) { if (is_neg(rc.get_val())) {
return this->x_above_low_bound(j); return this->x_above_lower_bound(j);
} }
return true; return true;
@ -227,7 +227,7 @@ public:
return this->x_below_upper_bound(j); return this->x_below_upper_bound(j);
case column_type::boxed: case column_type::boxed:
if (is_neg(rc.get_val())) { 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); 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) { 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::low_bound); 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_low_bounds[j], theta, unlimited); 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) { 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::low_bound); lp_assert(m > 0 && this->m_column_types[j] == column_type::lower_bound);
limit_inf_on_low_bound_m_pos(m, this->m_x[j], this->m_low_bounds[j], theta, unlimited); 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) { 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); 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); X get_max_bound(vector<X> & b);
@ -464,14 +464,14 @@ public:
case column_type::upper_bound: case column_type::upper_bound:
new_val_for_leaving = this->m_upper_bounds[j]; new_val_for_leaving = this->m_upper_bounds[j];
break; break;
case column_type::low_bound: case column_type::lower_bound:
new_val_for_leaving = this->m_low_bounds[j]; new_val_for_leaving = this->m_lower_bounds[j];
break; break;
case column_type::boxed: case column_type::boxed:
if (this->x_above_upper_bound(j)) if (this->x_above_upper_bound(j))
new_val_for_leaving = this->m_upper_bounds[j]; new_val_for_leaving = this->m_upper_bounds[j];
else else
new_val_for_leaving = this->m_low_bounds[j]; new_val_for_leaving = this->m_lower_bounds[j];
break; break;
default: default:
lp_assert(false); 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) { // void limit_theta_on_basis_column_for_feas_case_m_neg(unsigned j, const T & m, X & theta) {
// lp_assert(m < 0); // lp_assert(m < 0);
// lp_assert(this->m_column_type[j] == low_bound || this->m_column_type[j] == boxed); // lp_assert(this->m_column_type[j] == lower_bound || this->m_column_type[j] == boxed);
// const X & eps = harris_eps_for_bound(this->m_low_bounds[j]); // const X & eps = harris_eps_for_bound(this->m_lower_bounds[j]);
// if (this->above_bound(this->m_x[j], this->m_low_bounds[j])) { // if (this->above_bound(this->m_x[j], this->m_lower_bounds[j])) {
// theta = std::min((this->m_low_bounds[j] -this->m_x[j] - eps) / m, theta); // 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>(); // 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) { 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); lp_assert(m < 0);
const X& eps = harris_eps_for_bound(this->m_low_bounds[j]); const X& eps = harris_eps_for_bound(this->m_lower_bounds[j]);
limit_theta((this->m_low_bounds[j] - this->m_x[j] - eps) / m, theta, unlimited); 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>(); if (theta < zero_of_type<X>()) theta = zero_of_type<X>();
} }
@ -591,7 +591,7 @@ public:
return true; 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()) { if (numeric_traits<T>::precise()) {
// x gets larger // x gets larger
lp_assert(m > 0); 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) { 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); // lp_assert(m > 0 && this->m_column_type[j] == column_type::boxed);
const X & x = this->m_x[j]; 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)) { if (this->below_bound(x, lbound)) {
const X& eps = harris_eps_for_bound(this->m_upper_bounds[j]); 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); const X& eps = harris_eps_for_bound(ubound);
limit_theta((ubound - x - eps) / m, theta, unlimited); limit_theta((ubound - x - eps) / m, theta, unlimited);
} else { } else {
const X & lbound = this->m_low_bounds[j]; const X & lbound = this->m_lower_bounds[j];
if (this->above_bound(x, lbound)){ if (this->above_bound(x, lbound)){
const X& eps = harris_eps_for_bound(lbound); const X& eps = harris_eps_for_bound(lbound);
limit_theta((lbound - x - eps) / m, theta, unlimited); 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. // 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 // 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 // or
// x[j] + t * m <= this->m_upper_bounds[j] + harris_feasibility_tolerance ( if m > 0) // 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) { 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); limit_theta_on_basis_column_for_inf_case_m_neg_upper_bound(j, m, theta, unlimited);
} }
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (this->current_x_is_feasible()) { if (this->current_x_is_feasible()) {
if (m < 0) if (m < 0)
limit_theta_on_basis_column_for_feas_case_m_neg_no_check(j, m, theta, unlimited); limit_theta_on_basis_column_for_feas_case_m_neg_no_check(j, m, theta, unlimited);
} else { } else {
if (m < 0) 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 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; break;
// case fixed: // case fixed:
@ -770,7 +770,7 @@ public:
void init_reduced_costs(); 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); int advance_on_sorted_breakpoints(unsigned entering, X & t);
@ -807,7 +807,7 @@ public:
if (this->x_above_upper_bound(j)) if (this->x_above_upper_bound(j))
return 1; return 1;
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (this->x_below_low_bound(j)) if (this->x_below_low_bound(j))
return -1; return -1;
break; break;
@ -842,11 +842,11 @@ public:
case column_type::fixed: case column_type::fixed:
return 0; return 0;
case column_type::boxed: case column_type::boxed:
if (this->x_is_at_low_bound(j)) if (this->x_is_at_lower_bound(j))
return 1; return 1;
return -1; return -1;
break; break;
case column_type::low_bound: case column_type::lower_bound:
return 1; return 1;
break; break;
case column_type::upper_bound: case column_type::upper_bound:
@ -906,7 +906,7 @@ public:
vector<int> & heading, vector<int> & heading,
vector<T> & costs, vector<T> & costs,
const vector<column_type> & column_type_array, 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, const vector<X> & upper_bound_values,
lp_settings & settings, lp_settings & settings,
const column_namer& column_names): const column_namer& column_names):
@ -919,7 +919,7 @@ public:
settings, settings,
column_names, column_names,
column_type_array, column_type_array,
low_bound_values, lower_bound_values,
upper_bound_values), upper_bound_values),
m_beta(A.row_count()), m_beta(A.row_count()),
m_epsilon_of_reduced_cost(T(1)/T(10000000)), m_epsilon_of_reduced_cost(T(1)/T(10000000)),
@ -954,12 +954,12 @@ public:
settings, settings,
column_names, column_names,
column_type_array, column_type_array,
m_low_bounds_dummy, m_lower_bounds_dummy,
upper_bound_values), upper_bound_values),
m_beta(A.row_count()), m_beta(A.row_count()),
m_converted_harris_eps(convert_struct<T, double>::convert(this->m_settings.harris_feasibility_tolerance)) { m_converted_harris_eps(convert_struct<T, double>::convert(this->m_settings.harris_feasibility_tolerance)) {
lp_assert(initial_x_is_correct()); 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); m_enter_price_eps = numeric_traits<T>::precise() ? numeric_traits<T>::zero() : T(1e-5);
#ifdef Z3DEBUG #ifdef Z3DEBUG
// check_correctness(); // check_correctness();
@ -972,7 +972,7 @@ public:
basis_set.insert(this->m_basis[i]); basis_set.insert(this->m_basis[i]);
} }
for (unsigned j = 0; j < this->m_n(); j++) { 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); 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; return false;
} }
@ -983,7 +983,7 @@ public:
} }
if (basis_set.find(j) != basis_set.end()) continue; 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]) { 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); 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; return false;

View file

@ -25,7 +25,7 @@ Revision History:
#include <string> #include <string>
#include "util/lp/lp_primal_core_solver.h" #include "util/lp/lp_primal_core_solver.h"
namespace lp { 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 // The right side b is given implicitly by x and the basis
template <typename T, typename X> 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; bool ret;
const T & d = this->m_d[j]; const T & d = this->m_d[j];
switch (this->m_column_types[j]) { switch (this->m_column_types[j]) {
case column_type::low_bound: case column_type::lower_bound:
lp_assert(this->x_is_at_low_bound(j)); lp_assert(this->x_is_at_lower_bound(j));
ret = d < -m_epsilon_of_reduced_cost; ret = d < -m_epsilon_of_reduced_cost;
break; break;
case column_type::upper_bound: case column_type::upper_bound:
@ -97,9 +97,9 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_on_breakpoin
break; break;
case column_type::boxed: case column_type::boxed:
{ {
bool low_bound = this->x_is_at_low_bound(j); bool lower_bound = this->x_is_at_lower_bound(j);
lp_assert(low_bound || this->x_is_at_upper_bound(j)); lp_assert(lower_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); ret = (lower_bound && d < -m_epsilon_of_reduced_cost) || ((!lower_bound) && d > m_epsilon_of_reduced_cost);
} }
break; break;
case column_type::free_column: 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) if (dj > m_epsilon_of_reduced_cost || dj < -m_epsilon_of_reduced_cost)
return true; return true;
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (dj > m_epsilon_of_reduced_cost) return true;; if (dj > m_epsilon_of_reduced_cost) return true;;
break; break;
case column_type::upper_bound: 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; return true;
break; break;
} else if (dj < - m_epsilon_of_reduced_cost) { } 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; return true;
} }
break; break;
@ -159,9 +159,9 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precis
if (!is_zero(dj)) if (!is_zero(dj))
return true; return true;
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (dj > zero_of_type<T>()) return true; 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; return true;
} }
break; break;
@ -177,7 +177,7 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precis
return true; return true;
break; break;
} else if (dj < zero_of_type<T>()) { } 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; return true;
} }
break; break;
@ -364,7 +364,7 @@ template <typename T, typename X> bool lp_primal_core_solver<T, X>::try_jump_to_
return true; return true;
} }
} else { // m_sign_of_entering_delta == -1 } 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) { if (unlimited || t <= theta) {
lp_assert(t >= zero_of_type<X>()); lp_assert(t >= zero_of_type<X>());
return true; return true;
@ -380,9 +380,9 @@ template <typename T, typename X> bool lp_primal_core_solver<T, X>::try_jump_to_
} }
} }
return false; return false;
case column_type::low_bound: case column_type::lower_bound:
if (m_sign_of_entering_delta < 0) { 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) { if (unlimited || t <= theta) {
lp_assert(t >= zero_of_type<X>()); lp_assert(t >= zero_of_type<X>());
return true; return true;
@ -404,7 +404,7 @@ try_jump_to_another_bound_on_entering_unlimited(unsigned entering, X & t ) {
return true; return true;
} }
// m_sign_of_entering_delta == -1 // 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; 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 // 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 // or
// x[j] + t * m <= this->m_upper_bounds[j] ( if m > 0) // x[j] + t * m <= this->m_upper_bounds[j] ( if m > 0)
template <typename T, typename X> void 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; return;
default:break; 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)) if (numeric_traits<X>::is_neg(tt))
tt = zero_of_type<X>(); tt = zero_of_type<X>();
if (leavings.size() == 0 || tt < t || (tt == t && m > abs_of_d_of_leaving)) { 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){ } else if (m < 0){
switch (this->m_column_types[j]) { // check that j has an upper bound switch (this->m_column_types[j]) { // check that j has an upper bound
case column_type::free_column: case column_type::free_column:
case column_type::low_bound: case column_type::lower_bound:
return; return;
default:break; 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) { 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]))); 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(); ret = numeric_traits<T>::zero();
} }
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (this->x_below_low_bound(j)) { if (this->x_below_low_bound(j)) {
ret = -1; ret = -1;
} else { } 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(); this->m_costs[j] = numeric_traits<T>::zero();
} }
break; break;
case column_type::low_bound: case column_type::lower_bound:
if (this->x_below_low_bound(j)) { if (this->x_below_low_bound(j)) {
this->m_costs[j] = -1; this->m_costs[j] = -1;
} else { } 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]) { switch (this->m_column_type[j]) {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: 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; break;
case column_type::upper_bound: case column_type::upper_bound:
out << "( _" << this->m_x[j] << " " << this->m_upper_bounds[j] << ")" << std::endl; out << "( _" << this->m_x[j] << " " << this->m_upper_bounds[j] << ")" << std::endl;
break; break;
case column_type::low_bound: case column_type::lower_bound:
out << "( " << this->m_low_bounds[j] << " " << this->m_x[j] << " " << "_ )" << std::endl; out << "( " << this->m_lower_bounds[j] << " " << this->m_x[j] << " " << "_ )" << std::endl;
break; break;
case column_type::free_column: case column_type::free_column:
out << "( _" << this->m_x[j] << "_)" << std::endl; 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]; const X & x = this->m_x[j];
switch (this->m_column_types[j]) { switch (this->m_column_types[j]) {
case column_type::fixed: 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; break;
case column_type::boxed: 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]); try_add_breakpoint(j, x, d, upper_break, this->m_upper_bounds[j]);
break; break;
case column_type::low_bound: case column_type::lower_bound:
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]);
break; break;
case column_type::upper_bound: case column_type::upper_bound:
try_add_breakpoint(j, x, d, upper_break, this->m_upper_bounds[j]); 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]) { switch (this->m_column_types[j]) {
case column_type::fixed: case column_type::fixed:
case column_type::boxed: 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; break;
case column_type::low_bound: case column_type::lower_bound:
out << "[" << this->m_low_bounds[j] << ", inf" << std::endl; out << "[" << this->m_lower_bounds[j] << ", inf" << std::endl;
break; break;
case column_type::upper_bound: case column_type::upper_bound:
out << "inf ," << this->m_upper_bounds[j] << "]" << std::endl; out << "inf ," << this->m_upper_bounds[j] << "]" << std::endl;

View file

@ -177,13 +177,13 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
default: default:
break; // do nothing 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 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); this->m_settings.get_cancel_flag() == false);
if (this->m_settings.get_cancel_flag()) { 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 lp_assert(
|| this->get_status() == lp_status::FLOATING_POINT_ERROR
this->current_x_is_feasible() == false ||
|| this->get_status() == lp_status::CANCELLED
this->calc_current_x_is_feasible_include_non_basis()); ||
this->current_x_is_feasible() == false
||
this->calc_current_x_is_feasible_include_non_basis());
return this->total_iterations(); return this->total_iterations();
} }

View file

@ -22,7 +22,7 @@ Revision History:
#include <string> #include <string>
#include "util/vector.h" #include "util/vector.h"
#include <functional> #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>::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 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; template double lp::lp_primal_simplex<double, double>::get_current_cost() const;

View file

@ -31,7 +31,7 @@ namespace lp {
template <typename T, typename X> template <typename T, typename X>
class lp_primal_simplex: public lp_solver<T, X> { class lp_primal_simplex: public lp_solver<T, X> {
lp_primal_core_solver<T, X> * m_core_solver; lp_primal_core_solver<T, X> * m_core_solver;
vector<X> m_low_bounds; vector<X> m_lower_bounds;
private: private:
unsigned original_rows() { return this->m_external_rows_to_core_solver_rows.size(); } unsigned original_rows() { return this->m_external_rows_to_core_solver_rows.size(); }

View file

@ -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(); T artificial_cost = - numeric_traits<T>::one();
switch (constraint.m_relation) { switch (constraint.m_relation) {
case Equal: // no slack variable here 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_costs[artificial] = artificial_cost; // we are maximizing, so the artificial, which is non-negatiive, will be pushed to zero
this->m_basis[row] = artificial; this->m_basis[row] = artificial;
if (rs >= 0) { if (rs >= 0) {
@ -97,13 +97,13 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::fill_costs_and_x
break; break;
case Greater_or_equal: 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(); (*this->m_A)(row, slack_var) = - numeric_traits<T>::one();
if (rs > 0) { if (rs > 0) {
lp_assert(numeric_traits<T>::is_zero(this->m_x[slack_var])); lp_assert(numeric_traits<T>::is_zero(this->m_x[slack_var]));
// adding one artificial // 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_A)(row, artificial) = numeric_traits<T>::one();
this->m_costs[artificial] = artificial_cost; this->m_costs[artificial] = artificial_cost;
this->m_basis[row] = artificial; 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; break;
case Less_or_equal: case Less_or_equal:
// introduce a non-negative slack variable // 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(); (*this->m_A)(row, slack_var) = numeric_traits<T>::one();
if (rs < 0) { if (rs < 0) {
// adding one artificial // adding one artificial
lp_assert(numeric_traits<T>::is_zero(this->m_x[slack_var])); 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_A)(row, artificial) = - numeric_traits<T>::one();
this->m_costs[artificial] = artificial_cost; this->m_costs[artificial] = artificial_cost;
this->m_x[artificial] = - rs; 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_x[j] = this->m_b[row];
(*this->m_A)(row, j) = numeric_traits<T>::one(); (*this->m_A)(row, j) = numeric_traits<T>::one();
this->m_column_types[j] = column_type::fixed; 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; break;
case Greater_or_equal: case Greater_or_equal:
this->m_x[j] = - this->m_b[row]; this->m_x[j] = - this->m_b[row];
(*this->m_A)(row, j) = - numeric_traits<T>::one(); (*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>(); this->m_upper_bounds[j] = zero_of_type<X>();
break; break;
case Less_or_equal: case Less_or_equal:
this->m_x[j] = this->m_b[row]; this->m_x[j] = this->m_b[row];
(*this->m_A)(row, j) = numeric_traits<T>::one(); (*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] = m_low_bounds[j] = zero_of_type<X>(); this->m_upper_bounds[j] = m_lower_bounds[j] = zero_of_type<X>();
break; break;
default: default:
lp_unreachable(); 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; this->m_status = lp_status::OPTIMAL;
return; return;
} }
m_low_bounds.clear(); m_lower_bounds.clear();
m_low_bounds.resize(total_vars, zero_of_type<X>()); // low bounds are shifted ot zero 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_x.resize(total_vars, numeric_traits<T>::zero());
this->m_basis.resize(this->row_count()); this->m_basis.resize(this->row_count());
this->m_costs.clear(); 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_heading,
this->m_costs, this->m_costs,
this->m_column_types, this->m_column_types,
m_low_bounds, m_lower_bounds,
this->m_upper_bounds, this->m_upper_bounds,
this->m_settings, *this); this->m_settings, *this);
m_core_solver->solve(); m_core_solver->solve();

View file

@ -19,7 +19,7 @@ Revision History:
--*/ --*/
#include <memory> #include <memory>
#include "util/vector.h" #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<double>(vector<double> const&, vector<double> const&);
template bool lp::vectors_are_equal<lp::mpq>(vector<lp::mpq > const&, vector<lp::mpq> const&); template bool lp::vectors_are_equal<lp::mpq>(vector<lp::mpq > const&, vector<lp::mpq> const&);

View file

@ -36,7 +36,7 @@ typedef vector<std::pair<mpq, constraint_index>> explanation_t;
enum class column_type { enum class column_type {
free_column = 0, free_column = 0,
low_bound = 1, lower_bound = 1,
upper_bound = 2, upper_bound = 2,
boxed = 3, boxed = 3,
fixed = 4 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); 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 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_need_to_solve_inf;
unsigned m_max_cols; unsigned m_max_cols;
unsigned m_max_rows; 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(); } stats() { reset(); }
void reset() { memset(this, 0, sizeof(*this)); } void reset() { memset(this, 0, sizeof(*this)); }
}; };
@ -222,7 +226,10 @@ public:
backup_costs(true), backup_costs(true),
column_number_threshold_for_using_lu_in_lar_solver(4000), column_number_threshold_for_using_lu_in_lar_solver(4000),
m_int_branch_cut_gomory_threshold(4), 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; } void set_resource_limit(lp_resource_limit& lim) { m_resource_limit = &lim; }
@ -330,7 +337,10 @@ public:
bool backup_costs; bool backup_costs;
unsigned column_number_threshold_for_using_lu_in_lar_solver; unsigned column_number_threshold_for_using_lu_in_lar_solver;
unsigned m_int_branch_cut_gomory_threshold; unsigned m_int_branch_cut_gomory_threshold;
unsigned m_int_branch_cut_solver;
bool m_run_gcd_test; bool m_run_gcd_test;
unsigned m_cut_solver_bound_propagation_factor;
unsigned m_cut_solver_cycle_on_var;
}; // end of lp_settings class }; // end of lp_settings class

View file

@ -26,7 +26,7 @@ std::string column_type_to_string(column_type t) {
switch (t) { switch (t) {
case column_type::fixed: return "fixed"; case column_type::fixed: return "fixed";
case column_type::boxed: return "boxed"; 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::upper_bound: return "upper_bound";
case column_type::free_column: return "free_column"; case column_type::free_column: return "free_column";
default: lp_unreachable(); default: lp_unreachable();

View file

@ -18,7 +18,7 @@ Revision History:
--*/ --*/
#include <string> #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>::add_constraint(lp::lp_relation, double, unsigned int);
template void lp::lp_solver<double, double>::cleanup(); template void lp::lp_solver<double, double>::cleanup();
template void lp::lp_solver<double, double>::count_slacks_and_artificials(); template void lp::lp_solver<double, double>::count_slacks_and_artificials();

View file

@ -114,9 +114,9 @@ public:
// returns -1 if not found // returns -1 if not found
virtual int get_column_index_by_name(std::string name) const; 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); 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) { void set_upper_bound(unsigned i, T bound) {
@ -124,8 +124,8 @@ public:
ci->set_upper_bound(bound); ci->set_upper_bound(bound);
} }
void unset_low_bound(unsigned i) { void unset_lower_bound(unsigned i) {
get_or_create_column_info(i)->unset_low_bound(); get_or_create_column_info(i)->unset_lower_bound();
} }
void unset_upper_bound(unsigned i) { 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 ); 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); bool row_is_zero(std::unordered_map<unsigned, T> & row);
@ -244,7 +244,7 @@ protected:
void count_slacks_and_artificials_for_row(unsigned i); 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(); void fill_m_b();

View file

@ -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()); lp_assert(ci->upper_bound_is_set());
ci->set_fixed_value(ci->get_upper_bound()); ci->set_fixed_value(ci->get_upper_bound());
} else { } else {
lp_assert(ci->low_bound_is_set()); lp_assert(ci->lower_bound_is_set());
ci->set_fixed_value(ci->get_low_bound()); 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) { template <typename T, typename X> bool lp_solver<T, X>::get_minimal_row_value(std::unordered_map<unsigned, T> & row, T & lower_bound) {
low_bound = numeric_traits<T>::zero(); lower_bound = numeric_traits<T>::zero();
for (auto & t : row) { for (auto & t : row) {
T a = t.second; T a = t.second;
column_info<T> * ci = m_map_from_var_index_to_column_info[t.first]; column_info<T> * ci = m_map_from_var_index_to_column_info[t.first];
if (a > numeric_traits<T>::zero()) { if (a > numeric_traits<T>::zero()) {
if (ci->low_bound_is_set()) { if (ci->lower_bound_is_set()) {
low_bound += ci->get_low_bound() * a; lower_bound += ci->get_lower_bound() * a;
} else { } else {
return false; return false;
} }
} else { } else {
if (ci->upper_bound_is_set()) { if (ci->upper_bound_is_set()) {
low_bound += ci->get_upper_bound() * a; lower_bound += ci->get_upper_bound() * a;
} else { } else {
return false; return false;
} }
@ -204,20 +204,20 @@ template <typename T, typename X> bool lp_solver<T, X>::get_minimal_row_value
return true; 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) { template <typename T, typename X> bool lp_solver<T, X>::get_maximal_row_value(std::unordered_map<unsigned, T> & row, T & lower_bound) {
low_bound = numeric_traits<T>::zero(); lower_bound = numeric_traits<T>::zero();
for (auto & t : row) { for (auto & t : row) {
T a = t.second; T a = t.second;
column_info<T> * ci = m_map_from_var_index_to_column_info[t.first]; column_info<T> * ci = m_map_from_var_index_to_column_info[t.first];
if (a < numeric_traits<T>::zero()) { if (a < numeric_traits<T>::zero()) {
if (ci->low_bound_is_set()) { if (ci->lower_bound_is_set()) {
low_bound += ci->get_low_bound() * a; lower_bound += ci->get_lower_bound() * a;
} else { } else {
return false; return false;
} }
} else { } else {
if (ci->upper_bound_is_set()) { if (ci->upper_bound_is_set()) {
low_bound += ci->get_upper_bound() * a; lower_bound += ci->get_upper_bound() * a;
} else { } else {
return false; return false;
} }
@ -242,12 +242,12 @@ template <typename T, typename X> bool lp_solver<T, X>::row_e_is_obsolete(std
return true; return true;
} }
T low_bound; T lower_bound;
bool lb = get_minimal_row_value(row, low_bound); bool lb = get_minimal_row_value(row, lower_bound);
if (lb) { if (lb) {
T diff = low_bound - rs; T diff = lower_bound - rs;
if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)){ 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; m_status = lp_status::INFEASIBLE;
return true; 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) { 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; T rs = m_constraints[row_index].m_rs;
if (row_is_zero(row)) { if (row_is_zero(row)) {
if (rs < zero_of_type<X>()) 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; return true;
} }
if (get_minimal_row_value(row, low_bound)) { if (get_minimal_row_value(row, lower_bound)) {
T diff = low_bound - rs; T diff = lower_bound - rs;
if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)){ 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; m_status = lp_status::INFEASIBLE;
return true; 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(); T ret = numeric_traits<T>::zero();
auto row = this->m_A_values.find(i); 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()); 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]; unsigned external_i = this->m_core_solver_rows_to_external_rows[i];
auto & constraint = this->m_constraints[external_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; return v;
} }
if (!ci->is_flipped()) { 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 // the flipped case when there is only upper bound

View file

@ -23,4 +23,5 @@ namespace lp {
double numeric_traits<double>::g_zero = 0.0; double numeric_traits<double>::g_zero = 0.0;
double numeric_traits<double>::g_one = 1.0; double numeric_traits<double>::g_one = 1.0;
} }
#endif

View file

@ -42,20 +42,25 @@ bool contains(const std::unordered_map<A, B> & map, const A& key) {
#endif #endif
namespace lp { namespace lp {
inline void throw_exception(const std::string & str) { inline void throw_exception(const std::string & str) {
throw default_exception(str); throw default_exception(str);
} }
typedef z3_exception exception; typedef z3_exception exception;
#define lp_assert(_x_) { SASSERT(_x_); } #define lp_assert(_x_) { SASSERT(_x_); }
inline void lp_unreachable() { lp_assert(false); } 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 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 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_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_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_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 { namespace std {
template<> template<>
@ -115,6 +120,12 @@ namespace lp {
template <typename X> inline bool precise() { return numeric_traits<X>::precise();} 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 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_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 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();} template <typename T> inline T zero_of_type() {return numeric_traits<T>::zero();}
inline void throw_exception(std::string str) { throw exception(str); } inline void throw_exception(std::string str) { throw exception(str); }

View file

@ -22,7 +22,7 @@ Revision History:
#include <string> #include <string>
#include "util/vector.h" #include "util/vector.h"
#include "util/debug.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 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 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>*); template void lp::lu<double, double>::push_matrix_to_tail(lp::tail_matrix<double, double>*);

View file

@ -19,7 +19,7 @@ Revision History:
--*/ --*/
#include "util/lp/lp_settings.h" #include "util/lp/lp_settings.h"
#ifdef Z3DEBUG #ifdef Z3DEBUG
#include "util/lp/matrix.hpp" #include "util/lp/matrix_def.h"
#include "util/lp/static_matrix.h" #include "util/lp/static_matrix.h"
#include <string> #include <string>
template void lp::print_matrix<double, double>(lp::matrix<double, double> const*, std::ostream & out); template void lp::print_matrix<double, double>(lp::matrix<double, double> const*, std::ostream & out);

View file

@ -183,7 +183,7 @@ class mps_reader {
void set_boundary_for_column(unsigned col, bound * b, lp_solver<T, X> * solver){ void set_boundary_for_column(unsigned col, bound * b, lp_solver<T, X> * solver){
if (b == nullptr) { if (b == nullptr) {
solver->set_low_bound(col, numeric_traits<T>::zero()); solver->set_lower_bound(col, numeric_traits<T>::zero());
return; return;
} }
@ -191,7 +191,7 @@ class mps_reader {
return; return;
} }
if (b->m_low_is_set) { 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) { if (b->m_upper_is_set) {
solver->set_upper_bound(col, b->m_upper); solver->set_upper_bound(col, b->m_upper);

View file

@ -89,7 +89,7 @@ namespace nra {
*/ */
lbool check(lp::explanation_t& ex) { lbool check(lp::explanation_t& ex) {
SASSERT(need_check()); 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(); m_lp2nl.reset();
vector<nlsat::assumption, false> core; vector<nlsat::assumption, false> core;

View file

@ -18,10 +18,11 @@ Revision History:
--*/ --*/
#pragma once #pragma once
#define lp_for_z3
#include <string> #include <string>
#include <cmath> #include <cmath>
#include <algorithm> #include <algorithm>
#ifdef lp_for_z3
#include "../rational.h" #include "../rational.h"
#include "../sstream.h" #include "../sstream.h"
#include "../z3_exception.h" #include "../z3_exception.h"
@ -39,7 +40,7 @@ namespace lp {
template <typename T> template <typename T>
std::string T_to_string(const T & t); // forward definition std::string T_to_string(const T & t); // forward definition
#ifdef lp_for_z3
template <typename T> class numeric_traits {}; template <typename T> class numeric_traits {};
template <> class numeric_traits<unsigned> { template <> class numeric_traits<unsigned> {
@ -50,6 +51,7 @@ public:
static bool is_zero(unsigned v) { return v == 0; } static bool is_zero(unsigned v) { return v == 0; }
static double get_double(unsigned const & d) { return d; } static double get_double(unsigned const & d) { return d; }
static bool is_int(unsigned) {return true;} static bool is_int(unsigned) {return true;}
static bool is_pos(unsigned) {return true;}
}; };
template <> class numeric_traits<int> { template <> class numeric_traits<int> {
@ -61,6 +63,9 @@ public:
static double const get_double(int const & d) { return d; } static double const get_double(int const & d) { return d; }
static bool is_int(int) {return true;} static bool is_int(int) {return true;}
static bool is_pos(int j) {return j > 0;} 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_pos(const rational & d) {return d.is_pos();}
static bool is_neg(const rational & d) {return d.is_neg();} static bool is_neg(const rational & d) {return d.is_neg();}
static bool is_int(const rational & d) {return d.is_int();} 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> template <typename X, typename Y>
struct convert_struct { struct convert_struct {

View file

@ -19,7 +19,7 @@ Revision History:
--*/ --*/
#include <memory> #include <memory>
#include "util/vector.h" #include "util/vector.h"
#include "util/lp/permutation_matrix.hpp" #include "util/lp/permutation_matrix_def.h"
#include "util/lp/numeric_pair.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>::apply_from_right(vector<double>&);
template void lp::permutation_matrix<double, double>::init(unsigned int); template void lp::permutation_matrix<double, double>::init(unsigned int);

View file

@ -17,4 +17,5 @@ Revision History:
--*/ --*/
#include "util/lp/random_updater.hpp" #include "util/lp/random_updater_def.h"

View file

@ -19,7 +19,7 @@ Revision History:
--*/ --*/
#include <memory> #include <memory>
#include "util/vector.h" #include "util/vector.h"
#include "util/lp/row_eta_matrix.hpp" #include "util/lp/row_eta_matrix_def.h"
#include "util/lp/lu.h" #include "util/lp/lu.h"
namespace lp { namespace lp {
template void row_eta_matrix<double, double>::conjugate_by_permutation(permutation_matrix<double, double>&); template void row_eta_matrix<double, double>::conjugate_by_permutation(permutation_matrix<double, double>&);

View file

@ -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<double, double>::scale();
template bool lp::scaler<lp::mpq, lp::mpq>::scale(); template bool lp::scaler<lp::mpq, lp::mpq>::scale();

View file

@ -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) { 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 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(); T alpha = numeric_traits<T>::one();
if (numeric_traits<T>::is_zero(row_max)) { 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)){ if (numeric_traits<T>::is_zero(column_max)){
return; // the column has zeros only return; // the column has zeros only
} }
std::cout << "f";
if (numeric_traits<T>::get_double(column_max) < m_scaling_minimum) { if (numeric_traits<T>::get_double(column_max) < m_scaling_minimum) {
do { do {
alpha *= 2; alpha *= 2;

View file

@ -25,14 +25,14 @@ struct bound_signature {
unsigned m_i; unsigned m_i;
bool m_at_low; bool m_at_low;
bound_signature(unsigned i, bool at_low) :m_i(i), m_at_low(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_upper_bound() const { return !m_at_lower_bound;}
bool at_low_bound() const { return m_at_low;} bool at_lower_bound() const { return m_at_low;}
}; };
template <typename X> template <typename X>
struct signature_bound_evidence { struct signature_bound_evidence {
vector<bound_signature> m_evidence; vector<bound_signature> m_evidence;
unsigned m_j; // found new bound unsigned m_j; // found new bound
bool m_low_bound; bool m_lower_bound;
X m_bound; X m_bound;
}; };
} }

View file

@ -21,7 +21,7 @@ Revision History:
#include "util/vector.h" #include "util/vector.h"
#include "util/lp/lp_settings.h" #include "util/lp/lp_settings.h"
#include "util/lp/lu.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" #include "util/lp/dense_matrix.h"
namespace lp { namespace lp {
template double sparse_matrix<double, double>::dot_product_with_row<double>(unsigned int, vector<double> const&) const; template double sparse_matrix<double, double>::dot_product_with_row<double>(unsigned int, vector<double> const&) const;

View file

@ -19,7 +19,7 @@ Revision History:
--*/ --*/
#include <memory> #include <memory>
#include "util/vector.h" #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 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 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&); template void lp::square_dense_submatrix<double, double>::update_parent_matrix(lp::lp_settings&);

View file

@ -147,7 +147,7 @@ public:
} }
unsigned size() const { unsigned size() const {
return m_map.size(); return static_cast<unsigned>(m_map.size());
} }
bool contains(const A & key) const { bool contains(const A & key) const {
@ -163,6 +163,19 @@ public:
// d.m_deb_copy = m_map; // d.m_deb_copy = m_map;
m_stack.push(d); 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() { void pop() {
pop(1); pop(1);
@ -232,7 +245,9 @@ public:
m_map.clear(); 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;} const std::map<A, B, _Pr, _Alloc>& operator()() const { return m_map;}
}; };

View file

@ -30,6 +30,10 @@ public:
m_stack.push(m_value); m_stack.push(m_value);
} }
void clear() {
m_stack.clear();
}
unsigned stack_size() const { unsigned stack_size() const {
return static_cast<unsigned>(m_stack.size()); return static_cast<unsigned>(m_stack.size());
} }

View file

@ -86,10 +86,10 @@ public:
} }
/* /*
const B & operator[](unsigned a) const { const B & operator[](unsigned a) const {
lp_assert(a < m_vector.size()); lp_assert(a < m_vector.size());
return m_vector[a]; return m_vector[a];
} }
*/ */
unsigned size() const { unsigned size() const {
return m_vector.size(); return m_vector.size();
@ -106,15 +106,21 @@ public:
} }
template <typename T> template <typename T>
void pop_tail(vector<T> & v, unsigned k) { void pop_tail(vector<T> & v, unsigned k) {
lp_assert(v.size() >= k); lp_assert(v.size() >= k);
v.resize(v.size() - k); v.resize(v.size() - k);
} }
template <typename T> template <typename T>
void resize(vector<T> & v, unsigned new_size) { void resize(vector<T> & v, unsigned new_size) {
v.resize(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) { void pop(unsigned k) {
lp_assert(m_stack_of_vector_sizes.size() >= k); lp_assert(m_stack_of_vector_sizes.size() >= k);
@ -132,22 +138,22 @@ public:
resize(m_changes, first_change); resize(m_changes, first_change);
/* /*
while (k-- > 0) { while (k-- > 0) {
if (m_stack.empty()) if (m_stack.empty())
return; return;
delta & d = m_stack.back(); delta & d = m_stack.back();
lp_assert(m_vector.size() >= d.m_size); lp_assert(m_vector.size() >= d.m_size);
while (m_vector.size() > d.m_size) while (m_vector.size() > d.m_size)
m_vector.pop_back(); m_vector.pop_back();
for (auto & t : d.m_original_changed) { for (auto & t : d.m_original_changed) {
lp_assert(t.first < m_vector.size()); lp_assert(t.first < m_vector.size());
m_vector[t.first] = t.second; m_vector[t.first] = t.second;
} }
// lp_assert(d.m_deb_copy == m_vector); // lp_assert(d.m_deb_copy == m_vector);
m_stack.pop_back();*/ m_stack.pop_back();*/
} }
@ -175,10 +181,10 @@ public:
m_vector.resize(m_vector.size() + 1); m_vector.resize(m_vector.size() + 1);
} }
unsigned peek_size(unsigned k) const { unsigned peek_size(unsigned k) const {
lp_assert(k > 0 && k <= m_stack_of_vector_sizes.size()); lp_assert(k > 0 && k <= m_stack_of_vector_sizes.size());
return m_stack_of_vector_sizes[m_stack_of_vector_sizes.size() - k]; return m_stack_of_vector_sizes[m_stack_of_vector_sizes.size() - k];
} }
const vector<B>& operator()() const { return m_vector; } const vector<B>& operator()() const { return m_vector; }
}; };

View file

@ -17,17 +17,11 @@ Revision History:
--*/ --*/
=======
/*
Copyright (c) 2017 Microsoft Corporation
Author: Lev Nachmanson
*/
#include <memory> #include <memory>
#include "util/vector.h" #include "util/vector.h"
#include <set> #include <set>
#include <utility> #include <utility>
#include "util/vector.h" #include "util/lp/static_matrix_def.h"
#include "util/lp/static_matrix.hpp"
#include "util/lp/lp_core_solver_base.h" #include "util/lp/lp_core_solver_base.h"
#include "util/lp/lp_dual_core_solver.h" #include "util/lp/lp_dual_core_solver.h"
#include "util/lp/lp_dual_simplex.h" #include "util/lp/lp_dual_simplex.h"

Some files were not shown because too many files have changed in this diff Show more